| name | reverse-engineering-avance |
| description | Reverse Engineering Avancé — obfuscation, packing, anti-debug, symbol recovery, microcode, VM-based protection, firmware RE, et décompilation de high-level languages |
| tags | ["reverse-engineering","obfuscation","packing","anti-debug","VM","firmware","microcode","IDA","Ghidra"] |
| version | 1 |
Reverse Engineering Avancé
Guide de RE avancé au-delà de l'analyse statique de base — techniques de désassemblage, désobfuscation, et remontée de code complexe.
1. Obfuscation et Anti-Analyse
Opaque Predicates
if (x * x % 2 == 0) { }
if (x == (x ^ y) ^ y) { }
Control Flow Flattening
while (1) {
switch (state) {
case 0: ; state = 3; break;
case 1: ; state = 4; break;
case 3: ; state = 1; break;
case 4: ; state = 5; break;
case 5: goto end;
}
}
Code Virtualization (VMProtect, Themida, VMProtect)
- Code natif transformé en bytecode interprété
- VM interpreter = handler dispatch loop
- Chaque instruction = handler ID + operands
- Désobfuscation :
1. Capturer trace d'exécution (Intel PT, PIN)
2. Identifier handlers (tables de saut, dispatch)
3. Reconstruire bytecode → microcode intermédiaire
4. Lift à LLVM IR → recompiler
Encrypted Code Sections
2. Packers et Unpacking
Types de Packers
| Type | Exemples | Technique Unpacking |
|---|
| Compress | UPX, MPRESS, ASPack | Décompression automatique + OEP find |
| Crypt | Themida, Enigma, Armadillo | Dump after OEP + IAT rebuild |
| VM | VMProtect, Code Virtualizer | Trace + symbolique |
| Multi-layer | Obsidium, EXECryptor | Breakpoints OEP + multi-dump |
| .NET | ConfuserEx, .NET Reactor | de4dot, dnSpy, custom |
Unpacking Workflow
OEP Finder Script (x64dbg)
3. Anti-Debug et Anti-Hook
Anti-Debug Techniques
IsDebuggerPresent();
CheckRemoteDebuggerPresent();
NtGlobalFlag();
PEB->BeingDebugged;
OutputDebugString();
int 2Dh / int 3h;
CloseHandle(INVALID_HANDLE_VALUE);
Anti-Debug Bypass
Timing Checks
QueryPerformanceCounter(&start);
QueryPerformanceCounter(&end);
if (end - start > threshold) exit(0);
Integrity Checks
if (CRC32(.text) != valid_hash) ExitProcess(0);
4. Symbol Recovery
Stripped Binaries
Recovering vtables (C++ OOP)
# Identifiers virtual functions
# 1. Trouver vtable dans .rdata
# 2. Vérifier constructors (appel en début de fonction)
# 3. Thunk functions (adjustors) dans vtables
# 4. RTTI (Run-Time Type Information) dans .rdata
# IDA : vtable detection via FLAIR
# Ghidra : C++ class analyzer
5. Firmware & Embedded RE
UEFI Reverse Engineering
Print("Téléchargement de firmware en cours...")
# Bootloader : often ARM Thumb
# - Bare-metal (pas d'OS) → directes adresses mémoire
# - Memory-mapped peripherals
# - Interrupt vector table
# - Watchdog, boot signature
Micro-Controller RE
6. Decompilation High-Level Languages
.NET (C#, VB.NET)
Java / Android
Go binaries
Rust
7. Microcode & Intermediate Representations
Lifting to IR
Binary → intermediate representation → recompile
Angr VEX IR (Valgrind's VEX):
- Architecture agnostic
- IMark, Get, Put, LoadG, StoreG
- Symbolic execution ready
Ghidra P-Code:
- Machine-independent ops
- SLEIGH specifications
- Decompiler → P-Code → C
Binary Ninja BNIL:
- Low-level IL (LLIL)
- Medium-level IL (MLIL)
- High-level IL (HLIL)
LLVM-based Deobfuscation
8. Symbolic Execution & Concolic
Angr Framework
import angr
proj = angr.Project('./target', auto_load_libs=False)
state = proj.factory.entry_state()
simgr = proj.factory.simulation_manager(state)
simgr.explore(find=0x401234)
if simgr.found:
solution = simgr.found[0]
print(solution.posix.dumps(0))
Triton
from triton import *
9. Tools Deep Dive
IDA Pro Plugins
| Plugin | Usage |
|---|
| HexRays Decompiler | Décompilation C |
| FLIRT | Library identification |
| BinDiff | Binary diff + patch |
| x86Emu / Unicorn | Emulation de code |
| KeyPatch | Patch assembleur en direct |
| LazyIDA | Data conversion automation |
| Findcrypt | Crypto constants |
| SigMaker | Create FLIRT signatures |
Ghidra Scripting
from ghidra.program.model.listing import CodeUnit
def analyze():
listing = currentProgram.getListing()
for func in listing.getFunctions(True):
if func.getName() == "FUN_*":
refs = getReferencesTo(func.entryPoint)
if len(refs) == 0:
func.setName("deadcode_%s" % func.entryPoint)
10. Patch & Modify
Binary Patching
11. Ressources