v0.8.0
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 (requiresencBytecode).constInStream=1— carry int/i64/fp constants inside the encrypted bytecode
(OP_LOADI/OP_LOADI64/OP_LOADI_Fprologue) 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=Ncaps how many opcodes nest.
Dispatch
threadedDispatch=1— inline fetch/decode/indirectbrinto every handler; removes the single
centralvm.dispatch/vm.fetchfingerprint.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— fusemul+addchains into a singleOP_MULADDopcode (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_COUNTgrows to0x35(53 opcodes).
Anti-debug
bindAntiDebug=1— foldIsDebuggerPresent/CheckRemoteDebuggerPresent/
NtQueryInformationProcessdetection into the AES round-key mask, so under a debugger the
bytecode decrypts to garbage and crashes before the first opcode (requireshardened+antiDebug).- Handler-level RDTSC timing traps are now debounced over consecutive slow executions and the
defaultadHandlerThresholdraised 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
useAESknob were removed — AES-128-CTR is
now the only bytecode cipher (useAES=…in an annotation is silently ignored). VMPass_Impl.cppsplit by concern intoVMPass_{Handlers,Wrapper,Dispatch,Nested,Crypto,AntiDebug,Harden}.cpp.docs/VM.mdfully 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