بنقرة واحدة
re-handbook
Reverse engineering reference — techniques, patterns, and fallback strategies
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Reverse engineering reference — techniques, patterns, and fallback strategies
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Full analysis of a single function — disassemble, identify args, find string refs, callers/callees, RTTI, generate signature, label in GUI
Fully analyze a C++ virtual function table — detect params, find string refs, measure sizes, and label all entries
Detect function parameters from prologue and register usage — infer types, count, and calling convention
Discover a C++ class by name via RTTI — map its vtable, disassemble key virtual functions, explore inheritance hierarchy, and label everything
Find all functions that call a given function address — shows argument setup, string refs, and containing function names
Compare a function between sessions — generate a signature, find it after binary update, compare disassembly, report changes
| name | re-handbook |
| description | Reverse engineering reference — techniques, patterns, and fallback strategies |
Reverse engineering reference — techniques, patterns, and fallback strategies for common tasks.
Load this when starting an investigation session. It covers the "what to do when X doesn't work" cases.
Three methods, use whichever is available:
probe.exe "<command>" → JSON to stdout127.0.0.1:9998 — send command\n, receive JSONPOST http://localhost:9996 with {"action":"probe","command":"..."} (requires GUI)Always expect failure. Every probe_read_* call can return an error if the address is invalid. ARC Probe wraps all reads in SEH so the target won't crash, but you need to handle errors.
Address validation heuristics:
Reading large regions:
probe_dump for visual inspection (max 256 bytes, includes ASCII)probe_read for raw hex when you need to parse specific bytesWrite commands:
write <addr> <hex> — raw bytes (for instruction patching)write_int <addr> <value> — 32-bit integerwrite_float <addr> <value> — 32-bit floatwrite_ptr <addr> <value> — 8-byte pointerRules:
uint8 (1 byte) or int32 (4 bytes) — check the schemaInstruction patching:
90 (1 byte per NOP, use 9090909090 for a 5-byte CALL)CC (software breakpoint)C3 (force immediate return)Common pitfalls:
write_int to a uint8 field → overwrites 3 adjacent bytesWhen you have an address and don't know what's there:
Hex dump first: probe_dump address=<addr> size=128
4D 5A at the start? It's a PE header (module base)Check if it's a C++ object: Read first 8 bytes
probe_rtti_resolve to get the class nameCheck if it's a string: probe_read_string address=<addr>
probe_strings_at address=<addr> wide=true for UTF-16Check which module it belongs to: Compare address against module base+size ranges from probe_modules
Understanding calling conventions is critical for interpreting register state at breakpoints.
Arguments: RCX, RDX, R8, R9, then stack (left to right) Return value: RAX (64-bit), EAX (32-bit), XMM0 (float/double) Caller-saved (volatile): RAX, RCX, RDX, R8, R9, R10, R11 Callee-saved (non-volatile): RBX, RBP, RDI, RSI, R12, R13, R14, R15
What this means in practice:
this pointer for methods)this pointer: Always RCX for non-static member functions. So mov eax, [rcx+0x354] means "read field at offset 0x354 from the object".
Virtual function calls:
mov rax, [rcx] ; load vtable from this (RCX)
call qword ptr [rax+0x28] ; call vtable entry at index 5 (0x28 / 8 = 5)
Getters (return a field value):
mov eax, [rcx+0x354] ; 32-bit field at +0x354
ret
or
movss xmm0, [rcx+0x40] ; float field at +0x40
ret
Setters (write a field value):
mov [rcx+0x354], edx ; write second arg (EDX) to field at +0x354
ret
Boolean flags:
movzx eax, byte ptr [rcx+0x103] ; read 1-byte boolean at +0x103
test al, al
jz skip
Bitfield test:
test dword ptr [rcx+0x48], 0x4 ; test bit 2 of flags at +0x48
jnz has_flag
Array access:
movsxd rax, edx ; sign-extend index (EDX) to 64-bit
lea rcx, [rcx+rax*4+0x100] ; base + index*stride + offset → int32 array at +0x100
Linked list traversal:
.loop:
mov rcx, [rcx+0x8] ; next = current->next (offset 0x8)
test rcx, rcx ; while (current != NULL)
jnz .loop
Process memory is dynamic. Addresses change because:
Fix: Don't store absolute addresses long-term. Instead:
Common causes:
Fix: Always check for NULL at each step of the chain. Read the chain multiple times to confirm stability.
Fix: Try a broader approach — set the breakpoint on the function prologue instead of a specific instruction. Or use probe_watch to poll for value changes first, then narrow down.
Fix: Look for a known instruction pattern to re-synchronize. Function prologues are recognizable. Or disassemble from a known-good address (like an export or vtable entry) and follow the control flow forward.
Alternative approaches:
If you're inspecting a Source 2 game (CS2, Deadlock, Dota 2):
CreateInterface pattern:
Most Source 2 DLLs export CreateInterface. Walking the interface registry gives you pointers to engine subsystems.
probe_interfaces_list module=<dll>
Entity system:
Schema system:
All networked classes have schema metadata at runtime. Use probe_rtti_scan to discover all classes, then probe_rtti_hierarchy to understand inheritance.
Common base classes:
Key offsets pattern: