Skip to content

About

Tool for injecting tailored corrupted Java bytecode patterns to crash popular decompilers

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

5 Commits

Folders and files

Repository files navigation

DcmpKiller

Scatter anti-decompilation bytecode patterns from the helios-decompiler/decompiler-vulnerabilities-and-bugs research catalogue (DVB) across a target JAR.

Every real class in the input JAR is infected with a randomised mix of techniques, emitted as private synthetic methods with seeded-random names. Techniques whose class-file-version requirements don't fit the host (DVB-0001/0002/0009 cap at v50/v49 because they rely on JSR or uninitialised-across-jump bytecode) are dropped into the JAR as shadow classes, scattered into real packages with names that mimic compiler-generated synthetics (com/example/$$3537d8d9.class). The original methods are never touched, so the program runs identically — but every class now carries multiple decompiler tripwires.

Usage

Double-click GUI

java -jar dcmpkiller-1.0.0.jar (or just double-click on Windows) opens the workbench: pick an input JAR, an output JAR, dial in the scatter parameters, tick the techniques you want, click Inject.

CLI

dcmpkiller [command] [options]

Commands:
  inject (default)        Inject techniques into a JAR.
  list                    Print every registered transformer.
  gui                     Launch the graphical interface.
  help                    Print this message.

Inject options:
  --in <path>             Input JAR (required).
  --out <path>            Output JAR (required).
  --only <ids>            Comma-separated transformer IDs.
  --all                   Apply every registered transformer.
  --seed <hex|long>       RNG seed (default 0xD0C04D11).
  --per-class-min <int>   Minimum techniques per real class (default 1).
  --per-class-max <int>   Maximum techniques per real class (default 3).
  --shadow-multiplier <int>
                          Shadow-class copies per technique (default 3).
  --verbose, -v           Verbose logging.
# Aggressive default-style scatter
java -jar dcmpkiller-1.0.0.jar --in app.jar --out app-protected.jar --all

# Saturate every class (10–18 techniques each) and a deterministic seed
java -jar dcmpkiller-1.0.0.jar --in app.jar --out app-protected.jar --all \
    --per-class-min 10 --per-class-max 18 --seed cafef00d

# A curated subset
java -jar dcmpkiller-1.0.0.jar --in app.jar --out app-protected.jar \
    --only DVB-0007,DVB-0021,DVB-0023

# Inspect the catalogue
java -jar dcmpkiller-1.0.0.jar list

Programmatic API

TransformResult result = new DcmpKiller().run(
    DcmpKillerOptions.builder()
        .input(Path.of("app.jar"))
        .output(Path.of("app-protected.jar"))
        .useAll(true)
        .perClassMin(3)
        .perClassMax(6)
        .seed(0xCAFEF00DL)
        .build());

System.out.println(result.perTransformer());

How the scattering works

  1. Per-host embed. For every real class, the engine picks [perClassMin..perClassMax] compatible transformers in seeded-random order. "Compatible" means the host's class-file major version falls within the transformer's [minClassVersion..maxClassVersion] window. Each picked transformer adds a private static synthetic method (sometimes two — DVB-0023 needs a helper) with a randomised hex-string name.

  2. Try-then-rollback. After each embed, the host class is round-tripped through ASM with COMPUTE_FRAMES. If frame computation or structural validation fails for a particular technique on a particular host, the method(s) are reverted and the engine moves on. The original code is never affected by failures.

  3. Shadow-class scatter. Transformers that can't embed anywhere (DVB-0001/0002/0009 on a v51+ jar) are written as shadow classes. Each shadow lands in a randomly-chosen real package with a randomised $$xxxxxxxx-style name so it blends with compiler-generated synthetics. The engine also emits extra shadow copies of every other technique (controlled by --shadow-multiplier) for additional surface.

  4. Seeded RNG. All randomisation is seeded — a given input + seed produces a reproducible output. Change the seed and the output layout changes completely: different host counts, different class names, different technique placements. No static signature can identify the injections across builds.

Adding a new transformer

  1. Subclass AbstractTransformer under com.dcmpkiller.transformer.impl.
  2. Implement emitInto(ClassNode host, String methodName, Random random) — emit the technique's bytecode as a method on host. Use host.name for any INVOKESTATIC self-references so the same payload works in both real-class and shadow-class modes.
  3. Override getMinClassVersion / getMaxClassVersion if the technique requires a specific class-file-version window.
  4. Register the new transformer in TransformerRegistry.builtIn() (one line).

The CLI list command, the GUI checklist, the --only flag, and the scatter engine pick it up automatically.

Current state of the targeted decompilers (May 2026 research)

Each transformer's metadata declares the decompilers the technique is documented to break. Below is the status from May 2026 research — useful when picking a curated subset.

Decompiler Latest version (May 2026) DVB status
CFR (leibnitz27/cfr) 0.152 (Dec 2021), master 0.153-SNAPSHOT actively maintained 4/11 fixed (DVB-0013, 0019, 0021, 0023), 2 partial, 5 still broken
Fernflower (JetBrains) Active, IDEA-tagged correctness fixes through Apr 2026 Most DVBs not directly addressed; same error strings (parsing failure!, Statement cannot be decomposed) still emitted
Vineflower (active fork) 1.12.0 (Apr 29 2026) DVB-0003 fixed (PR #46, 1.8.0); DVB-0006 / 0014 partial (PR #494, 1.11.2); rest substantially the same as Fernflower
Procyon (mstrobel/procyon) 0.6.0 (Feb 2022) — effectively dormant All 8 Procyon DVBs still broken; bundled vanilla in Recaf, Bytecode Viewer, Luyten
JD-Core / JD-GUI 1.1.3 / 1.6.6 (Dec 2019) — dormant; nbauma109/jd-core 1.3.3 (Feb 2026) is the active community fork 0 of 18 JD-GUI DVBs have a documented fix

So even nine years after the original DVB report, the techniques still trip popular Java decompilers in 2026. DVB-0001 / 0002 / 0009 / 0023 are particularly stubborn across the board.

Building

Java 25 + Maven. Lombok handles the @Getter/@Builder on the API and core-state classes. ASM 9.9.1 is used for bytecode generation (it understands class file v69 / Java 25).

mvn package
# -> target/dcmpkiller-1.0.0.jar (shaded, double-clickable)

About

Tool for injecting tailored corrupted Java bytecode patterns to crash popular decompilers

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages