Reverse-skills rev-struct
Reconstruct data structures by analyzing memory access patterns across functions
install
source · Clone the upstream repo
git clone https://github.com/P4nda0s/reverse-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/P4nda0s/reverse-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/rev-struct" ~/.claude/skills/p4nda0s-reverse-skills-rev-struct && rm -rf "$T"
manifest:
skills/rev-struct/SKILL.mdsource content
rev-struct - Structure Recovery
Recover data structure definitions by analyzing memory access patterns in functions and their call chains.
Pre-check
First, verify that IDA-NO-MCP exported data exists in the current directory:
- Check if
directory existsdecompile/ - Check if there are
files inside.c
If not found, prompt the user:
IDA-NO-MCP export data not detected. Please export decompilation results using IDA-NO-MCP plugin first: 1. Download plugin: https://github.com/P4nda0s/IDA-NO-MCP 2. Copy INP.py to IDA plugins directory 3. Press Ctrl-Shift-E in IDA to export 4. Open the exported directory with Claude Code
Export Directory Structure
./ ├── decompile/ # Decompiled C code directory │ ├── 0x401000.c # One file per function, named by hex address │ ├── 0x401234.c │ └── ... ├── decompile_failed.txt # Failed decompilation list ├── decompile_skipped.txt # Skipped functions list ├── strings.txt # String table (address, length, type, content) ├── imports.txt # Import table (address:function_name) ├── exports.txt # Export table (address:function_name) └── memory/ # Memory hexdump (1MB chunks)
Function File Format (decompile/*.c)
Each
.c file contains function metadata comments and decompiled code:
/* * func-name: sub_401000 * func-address: 0x401000 * callers: 0x402000, 0x403000 // List of functions that call this function * callees: 0x404000, 0x405000 // List of functions called by this function */ int __fastcall sub_401000(int a1, int a2) { // Decompiled code... }
Structure Recovery Steps
Step 1: Read Target Function
- Based on the user-provided address, read
decompile/<address>.c - Parse function metadata, extract callers and callees lists
- Identify pointer parameters in the function (potential structure pointers)
Step 2: Collect Memory Access Patterns
Search for the following patterns in the target function:
Direct offset access:
*(a1 + 0x10) // offset 0x10 *(_DWORD *)(a1 + 8) // offset 0x8, DWORD type *(_QWORD *)(a1 + 0x20) // offset 0x20, QWORD type *(_BYTE *)(a1 + 4) // offset 0x4, BYTE type
Array access:
*(a1 + 8 * i) // array, element size 8 bytes a1[i] // array access
Nested structures:
*(*a1 + 0x10) // first field of struct pointed by a1 is a pointer
Record format:
offset=0x00, size=8, access=read/write, type=QWORD offset=0x08, size=4, access=read, type=DWORD ...
Step 3: Traverse Callers for Analysis
Read each caller function and analyze:
-
Parameter passing: What is passed when calling?
sub_401000(v1); // v1 might be a struct pointer sub_401000(&v2); // v2 is a struct sub_401000(malloc(64)); // struct size is ~64 bytes -
Operations before/after the call:
v1 = malloc(0x40); // allocate 0x40 bytes *v1 = 0; // offset 0x00 initialization *(v1 + 8) = callback; // offset 0x08 is a function pointer sub_401000(v1); -
Collect more offset accesses
Step 4: Traverse Callees for Analysis
Read each callee function and analyze:
-
How parameters are used:
// In callee int callee(void *a1) { return *(a1 + 0x18); // accesses offset 0x18 } -
Passed to other functions:
another_func(a1 + 0x20); // offset 0x20 might be a nested struct
Step 5: Aggregate and Infer
- Merge all offset information, sort by offset
- Calculate struct size: max(offset) + last_field_size
- Infer field types:
- Called as function pointer → function pointer
- Passed to
/strlen
→ string pointerprintf - Compared with constants → enum/flags
- Increment/decrement operations → counter/index
- Identify common patterns:
- Offset 0 is a function pointer table → vtable (C++ object)
- next/prev pointers → linked list node
- refcount field → reference counted object
Output Format
/* * Structure Recovery Analysis * Source function: <func_address> * Analysis scope: <number of callers/callees analyzed> * * Functions using this struct: * - 0x401000 (initialization) * - 0x401100 (field access) * - 0x401200 (destruction) */ // Estimated size: 0x48 bytes // Confidence: High / Medium / Low struct suggested_name { /* 0x00 */ void *vtable; // vtable pointer, called: (*(*this))() /* 0x08 */ int refcount; // reference count, has ++/-- operations /* 0x0C */ int flags; // flags, AND with 0x1, 0x2 /* 0x10 */ char *name; // string, passed to strlen/printf /* 0x18 */ void *data; // data pointer /* 0x20 */ size_t size; // size field /* 0x28 */ struct node *next; // linked list next pointer /* 0x30 */ struct node *prev; // linked list prev pointer /* 0x38 */ callback_fn handler; // callback function /* 0x40 */ void *user_data; // user data }; // Field access examples: // 0x401000: *(this + 0x08) += 1; // refcount++ // 0x401100: printf("%s", *(this + 0x10)); // print name