Lion Cipher Lab
Emulate shellcode safely with the Unicorn Engine
- Threat Intel Analyst
- Advanced
- ~75 min
- Free · no account required
Why it matters
A huge amount of what a threat-intel or malware analyst has to understand arrives as a raw blob of bytes with no file header, no imports and no obvious structure: the shellcode inside an exploit, the first stage a loader decrypts into memory, the position-independent payload a document macro sprays onto the heap. You cannot just double-click it, and running it on a real machine is exactly what the author wants you to do. Static disassembly gets you the instructions but not the answers — a loader that XOR-decodes its real payload, or computes a C2 address from a runtime value, shows a static…
What you'll learn
- what CPU emulation is and why analysts run untrusted position-independent code inside a virtual CPU instead of on the host
- standing up a Unicorn instance: choosing arch/mode, mapping memory, writing code bytes, seeding registers, and starting/stopping emulation at explicit addresses
- instrumenting execution with hooks: a per-instruction code hook, an invalid-memory hook, and a memory-write hook that captures runtime-computed values
- hand-assembling a few benign x86-64 instructions as raw machine-code bytes and predicting the exact register result before you run them
- recovering an 'indicator' (a value a loader writes to memory at runtime) that a static disassembler would never reveal — the core payoff of emulation
- reading and fixing the classic failure: an UC_ERR_* on unmapped memory, and why you must map every page the code touches (stack included)
- the honest limits of emulation: no real OS/syscalls, anti-emulation and timing checks, self-modifying code, and API-heavy loaders that need a full environment
- when to graduate from raw Unicorn to a production framework (Qiling) that supplies a loader, an OS layer and syscall handling
Steps in this lab
- What emulation buys you — and why not just run it
- Install Unicorn's Python binding
- The mental model: map memory, write code, run a range
- Stub 1 — three instructions you can predict by hand
- Instrument it: watch every instruction retire
- Meet the classic failure: unmapped memory
- Stub 2 — recover an indicator the code computes at runtime
- Know the limits — when emulation lies or stalls
- Do it better: graduate to Qiling when you need an OS