A complete protection pipeline
Every Dhaedalida build combines multiple, independently generated layers of defense. Here is what runs under the hood.
Your logic becomes a virtual machine that only exists in your build
Dhaedalida converts each selected function into a self-contained virtual machine embedded in a new section of the executable. The original instructions no longer exist in the file to be disassembled. An analyst finds a custom VM executing the logic indirectly, not readable code.
- Function-level protection: shield license checks, crypto and core IP while the rest of the app stays fast
- Executables and DLLs: a virtualized DLL derives its own base at load time, so exports, relocations and
DllMainkeep working - Entry point included: pass your entry point as a protection target and it runs under VM protection from the very first instruction
- No two builds alike: every run produces byte-different output with no shared static signature
- Custom protection section name so the protected code blends into the app
- Zero behavioral change: the protected function computes the same results as before
; generated VM - layout differs every build vm_enter ctx, 0x4A19 handler_0x3F ; push imm handler_0x08 ; xor rot handler_0xC1 ; branch pred handler_0x77 ; native bridge vm_leave ctx
No plaintext secrets left in your binary
Sensitive text is often the easiest clue an attacker uses to locate protection. With
--encrypt-strings, the string literals used by protected functions are
stored encrypted at rest and decrypted only for a moment, inside the virtual machine,
at the instant they are used.
- A
strings-style scan of the shipped file reveals no plaintext messages or secrets - Each string gets its own key: no single point to unravel
- Supports both ANSI and wide (UTF-16) text
- Strings shared with unprotected code are left intact, so nothing breaks
$ strings yourapp.protected.exe | grep -i license (no matches) ; at runtime, inside the VM only: vm_decrypt str_0x2c, key_0x2c ; one use vm_wipe str_0x2c ; then gone
Layered hardening, out of the box
Every virtualized function is automatically strengthened with multiple layers of obfuscation that resist both static and dynamic analysis. These protections are on by default, with adjustable complexity.
- Encrypted constants: no meaningful values sit in the protected code as plaintext
- Anti-disassembly hardening that defeats linear-sweep disassemblers
- Randomized internal structure, shuffled per build, so it isn't a stable fingerprint
- Decoy operations and opaque predicates that automated analysis cannot simplify away
- Non-linear control flow: logic scattered and chained so its structure is hard to reconstruct
- Anti-single-step protection that resists being walked one instruction at a time
; non-linear dispatch state = 0x11 loop: switch (state) 0x11 -> ... ; state = 0x9C 0x9C -> ... ; state = 0x02 0x02 -> ... ; state = 0xFF goto loop
Wrap the whole program in a self-unpacking, encrypted shell
Beyond per-function virtualization, --packer compresses and encrypts the
entire application behind a self-unpacking loader. On disk the shipped file contains no
readable code or data; it restores itself in memory at launch and then runs normally.
- Protects the whole program, not just the virtualized functions
- Smaller shipped file thanks to compression
- Defeats casual static inspection: an editor or disassembler shows only the protected shell
- Use it together with virtualization for defense in depth, or on its own (pack-only)
; yourapp.protected.exe [ self-unpacking loader ] [ compressed + encrypted image ] ; no readable code or data ; at launch loader -> decompress + decrypt in memory -> run
The protection protects itself
Dhaedalida protects its own unpacking loader with the same virtualization engine it applies to your code, so there is no readable version of the protection mechanism for an attacker to study.
- The loader is virtualized with the same per-build VM as your functions
; the loader itself is virtualized vm_enter loader_ctx unpack_image ; in memory only verify_integrity vm_leave loader_ctx ; no readable loader on disk to study
Fits the way you already build and ship
Protect interactively in the Dhaedalida desktop app while you tune settings, then automate the exact same profile in your build pipeline with the command-line engine. Mark functions once in source with the marker SDK, detected with or without a PDB.
- Desktop app: open your EXE or DLL → review the function list → tick protections → Protect
- Marker SDK: bracket functions with
VMStart()/VMEnd(); bindings for C, C++, Rust, Go, Delphi and more, harmless no-ops in a normal build - Marked functions detected with or without debug symbols (a PDB), even in a stripped release build
- Opt-in
--stripscrubs debug info from the shipped file (PE debug directory, embedded PDB path, symbol tables and debug sections) so no build paths or symbols leak - The CLI takes protection targets from a list file: hundreds of functions in one CI run
# protect step in CI - run: dhaedalida-cli bin/app.exe \ --out dist/app.protected.exe \ --addr-file protect.list \ --encrypt-strings --strip \ --packer --anti-debug --anti-tamper --protect-imports
Composable tamper-resistance layers
Each layer defends a specific avenue of attack. Compose exactly the profile you want: enable the packer with --packer and add layers as flags. The packer suite ships in the Pro edition.
| Protection | Flag | What it does | Default |
|---|---|---|---|
| Import protection | --protect-imports | Hides the app's Windows API references | Selectable |
| Debugger resistance | --anti-debug | Declines to run under a debugger | Selectable |
| Analysis-VM resistance | --anti-vm | Stops running inside a VM (VMware, Hyper-V, VirtualBox...) | Selectable |
| Monitoring resistance | --anti-monitor | Declines to run under system-monitoring tools | Selectable |
| Integrity / anti-tamper | --anti-tamper | Refuses to run if the file has been patched | Selectable |
| Containment-tool resistance | --anti-sandbox | Detects analysis sandboxes and declines to run | Selectable |
| Anti-dump | --anti-dump | Blocks reconstruction of a usable copy from process memory | Off (advanced, opt-in) |
| Direct system calls | --syscalls | Hardens the loader's own integrity against user-space tools | Selectable |
Product questions
Which platforms does Dhaedalida support?
.exe and .dll). A virtualized or packed DLL derives its own base at load time, so exports, relocations and DllMain keep working. The marker SDK ships bindings for C (MSVC and GCC/Clang), C++, Rust, Go, Delphi/Object Pascal, D, Zig, Nim and assembly. Any native x86/x64 language works; .NET and other managed code are out of scope.Does protection change how my application behaves?
Do I have to change my source code?
VMStart() / VMEnd(). Marked functions are detected with or without a PDB, and the markers are harmless no-ops in a normal build. Additionally, it's possible to protect a specific function using only its address with the CLI.