Skip to content

Feature: deception layer — modern decoy/junk code, honeypots, synthesis-resistant opaque predicates #112

Description

@mcpolo99

Summary

Add a deliberate deception layer — decoy code, honeypot data, and stronger opaque predicates — to send reverse engineers down rabbit holes, and to modernize the existing "junk code" which is effectively dead on current runtimes. Goal: raise manual-RE cost and defeat pattern/tooling that keys on the real logic, for legitimate IP protection.

What we have today (source analysis)

Confuser.Protections/ControlFlow:

  • Control-flow obfuscation — block splitting + SwitchMangler/JumpMangler + a key-transformed switch dispatcher. Solid baseline.
  • Predicate types (PredicateType): Normal (simple), Expression (ExpressionPredicate → DynCipher.GenerateExpressionPair, a reversible arithmetic transform), x86 (x86Predicate, native — Windows/x86 only).
  • Junk code (CFContext.AddJunk) and opaque junk branches (CFContext.AddJump): crude invalid-IL (pop/dup/throw/ldarg 0xff/ldloc 0xff/ldtoken) placed on never-taken paths.

Gaps

Gap Detail
Junk is dead on modern runtimes AddJunk and the fancy AddJump branches are gated if (Method.Module.IsClr40 ...) return; → off for .NET 4.x / Core / 5–10. Only pre-CLR-4 (net2.0/3.5) gets them.
Junk is invalid-IL, not deceptive logic It's anti-decompiler noise that would crash if executed — not plausible fake code that wastes an analyst's time.
No decoy methods No plausible fake routines (fake license check, fake crypto, fake config parsing) to sink RE effort into.
No honeypot data No fake strings/constants/metadata (fake keys, fake endpoints) that lead nowhere.
Opaque predicates aren't synthesis-resistant Expression is reversible arithmetic → resolvable by symbolic execution / program synthesis (Syntia/QSynth-class).
Nothing survives pruning No reachable / data-dependent decoys; static dead code gets removed by reachability analysis.

Proposed improvements

  1. Modern valid junk/decoy — replace invalid-IL junk with valid, verifiable dead-but-plausible code that runs on CLR 4.0+ (not gated off), guarded by strong predicates so it isn't trivially dead-code-eliminated.
  2. Decoy methods + honeypot data — inject plausible fake routines and fake strings/constants/metadata; make some data-dependent / reachable-looking so dynamic tracing can't cleanly separate real from fake.
  3. Synthesis-resistant opaque predicates — add predicates hard for symbolic execution / synthesis (verified-complex / MBA-style, LOKI-inspired), beyond the current reversible-arithmetic Expression.
  4. Survive reachability/dead-code elimination — weave decoys into reachable paths; where a VM is present (Feature: method virtualization (VM-based protection) #111), place decoy handlers/bytecode inside the VM's dispatched paths so they can't be cheaply pruned.

The honest catch

Naive decoys get pruned — reachability analysis and dynamic tracing strip static dead code and ignore never-executed branches. Decoys are effective only when guarded by strong opaque predicates or woven into genuinely reachable/dispatched paths. Deception raises cost; it does not prevent RE.

Relationship

  • Complements Feature: method virtualization (VM-based protection) #111 (method virtualization): the strongest decoys live inside a per-build-unique VM's dispatched paths.
  • Modernizing junk to run on CLR 4.0+ is a concrete, standalone win independent of the VM — the current behavior means modern targets get no junk at all.

Scope as opt-in, incremental (junk-modernization first; decoy methods/honeypots and synthesis-resistant predicates as follow-ups).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestneeds-evaluationRequires further analysis before implementation

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions