Skip to content

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 04 Aug 17:26
· 49 commits to main since this release
fbe671e

xollvm — v0.8.0

Built against stock LLVM release/22.x.

A large code-virtualisation (vm) hardening release: data-at-rest crypto, nested
virtualisation, decentralised dispatch, ISA diversification, key-schedule anti-debug, and the
engine pool — per-function, metamorphic interpreter engines. Every new feature is
behind its own knob, defaults OFF, and is byte-identical to v0.7.0 when off.
The new
preset=max bundle opts the whole set in. Full vm runtime suite green (125/125).

Highlights

  • Engine pool Spread virtualised functions across many structurally-distinct
    interpreter engines instead of one shared engine — so lifting one function's engine gives no
    shortcut for a function that runs a different one.
  • Metamorphic engines. Each engine's handler bodies are MBA-diversified per clone: distinct
    code, not just distinct names.
  • Bytecode at rest stays ciphertext via lazy per-fetch AES decryption, with constants moved
    inside the encrypted stream.
  • No single dispatch fingerprint — dispatch can be threaded into every handler and each
    opcode byte keyed per instruction pointer.
  • Cross-build diversity — per-build operand-encoding randomisation means two builds of the
    same source share no static handler signature.

What's new (vm pass)

Engine pool — per-function metamorphic virtualisation

  • enginePoolSize=N — build N structurally-distinct engines per module; each function is
    assigned to one by a name+seed hash (__vm_engine, __vm_engine.p1, …).
  • perFnEngine=1 — give a function its own dedicated engine (annotation-selective: set it on the
    critical functions only, or everywhere for a full per-function build).
  • metamorphicEngines=1 — rewrite each engine's integer handler arithmetic with a
    per-clone-seeded MBA identity, so pool engines have structurally distinct bodies even at
    handlerVariants=1, hardened=0.
  • Pooling extends to the nested layer (__vm_engine.nest.pN) while the shared __vm_h_* helpers
    are virtualised exactly once.

Data-at-rest crypto

  • lazyDecrypt=1 — decrypt bytecode per fetch from a recomputed AES-CTR keystream block instead
    of decrypting the whole buffer at load; the runtime bytecode never exists as contiguous
    plaintext (requires encBytecode).
  • constInStream=1 — carry int/i64/fp constants inside the encrypted bytecode
    (OP_LOADI/OP_LOADI64/OP_LOADI_F prologue) instead of plaintext wrapper stores (requires
    encBytecode).

Nested virtualisation

  • nestedVM=1 — the compute step of BINOP/BINOP64/ICMP/ICMP64/FCMP/CAST/BINOP_F opcodes is
    outlined into __vm_h_* helpers that are themselves virtualised against a second engine
    (__vm_engine.nest), giving depth-2 interpretation with no possible recursion.
  • nestedVMOpcodes=N caps how many opcodes nest.

Dispatch

  • threadedDispatch=1 — inline fetch/decode/indirectbr into every handler; removes the single
    central vm.dispatch/vm.fetch fingerprint.
  • keyedDispatch=1 — XOR each opcode byte with a per-IP compile-time key; the same physical byte
    decodes to different opcodes at different IPs.

ISA

  • superOps=1 — fuse mul+add chains into a single OP_MULADD opcode (new opcode 0x34).
  • randISA=1 — per-build, module-uniform permutation of five operand-field encodings (BinSubop,
    ICmp predicates, CastKind, FBinSubop, FCmp predicates), so cross-sample signatures don't match.
  • New opcode OP_LOADI64 (0x33); OP_COUNT grows to 0x35 (53 opcodes).

Anti-debug

  • bindAntiDebug=1 — fold IsDebuggerPresent / CheckRemoteDebuggerPresent /
    NtQueryInformationProcess detection into the AES round-key mask, so under a debugger the
    bytecode decrypts to garbage and crashes before the first opcode (requires hardened+antiDebug).
  • Handler-level RDTSC timing traps are now debounced over consecutive slow executions and the
    default adHandlerThreshold raised to 5000, eliminating scheduling-noise false positives.

Configuration

  • preset=<light|medium|high|max> — canned knob bundles applied before explicit knobs.
    max = full stack + nested VM + super-operators + rolling register key + bind-anti-debug +
    ISA randomisation + per-function metamorphic engines.

Internal / breaking

  • The legacy LCG bytecode-encryption path and the useAES knob were removed — AES-128-CTR is
    now the only bytecode cipher (useAES=… in an annotation is silently ignored).
  • VMPass_Impl.cpp split by concern into VMPass_{Handlers,Wrapper,Dispatch,Nested,Crypto,AntiDebug,Harden}.cpp.
  • docs/VM.md fully updated for all of the above.

Artifacts

File What OS
xollvm-linux-Release.tar.zst clang/opt with obfuscator built in Linux x86_64
xollvm-windows-Release.7z clang/opt with obfuscator built in Windows x64
Obfuscator-linux-x64.so loadable -fpass-plugin Linux x86_64

Cross-compilation backends

-DLLVM_TARGETS_TO_BUILD="X86;AArch64;ARM;RISCV" — X86, AArch64, ARM, RISC-V.

Full diff: v0.7.0...v0.8.0