Code Obfuscation in Reversing
reversingintermediate
Identify and defeat common code obfuscation techniques in CTF reversing challenges.
reversingobfuscationpackingvirtualizationollvmdeobfuscation
Code Obfuscation in Reversing
Challenge authors add obfuscation to make reversing harder. Recognizing and bypassing it is a core CTF skill. The key insight: most obfuscation is designed to slow you down, not stop you. With the right tools (angr, GDB, memory dumps), you can bypass almost anything.
Obfuscation Types
| Type | Description | Bypass |
|---|---|---|
| Packing | Binary compressed/encrypted, self-decrypts at runtime | Unpack or dump from memory |
| String encryption | Strings XOR'd or AES'd, decrypted lazily | Breakpoint after decrypt routine |
| Control flow flattening | All blocks jump through a dispatcher | Use angr or trace execution |
| Opaque predicates | Always-true/false conditions to confuse analysis | Recognize and remove manually |
| Virtualization | Code runs in custom VM | Reverse the VM bytecode |
| Junk code insertion | Dead code between real instructions | Identify by tracing |
Bypass Techniques
file packed_binary # → "UPX compressed"
strings packed_binary | grep -i upx
upx -d packed_binary -o unpacked_binary
file unpacked_binary # should show original ELF formatDetection Workflow
Check if binary is packed
file ./binary # UPX compressed?
strings ./binary | head -30 # very few strings = packed/encrypted
strings ./binary | grep UPXCheck for string encryption
strings ./binary
# Normal binary: function names, error messages, format strings
# Encrypted binary: almost no readable strings, only junkRun and observe
strace ./binary 2>&1 | head -20
ltrace ./binary 2>&1 | head -20
# mmap + mprotect = self-unpackingDynamic analysis to bypass
Use GDB + GEF to step through unpacking, then analyze the clean code. Always prefer dynamic analysis to confirm static findings.
Checklist
-
file→ packed (UPX)? -
strings→ encrypted? (no readable strings) -
upx -d→ try to unpack - Run + breakpoint + memory dump for custom packers
- Ghidra decompiler often handles moderate obfuscation
- For CFF: use angr symbolic execution
- String encryption: breakpoint after decrypt function
- Always use dynamic analysis to confirm static analysis findings
Last updated on