| category | binary |
| name | rev-struct |
| description | Reconstruct data structures by analyzing memory access patterns across functions |
rev-struct - Structure Recovery
Recover data structure definitions by analyzing memory access patterns in functions and their call chains.
Pre-check
Determine which IDA access method is available:
Option A — IDA Pro MCP (preferred if connected):
Check if the IDA Pro MCP server is connected (look for an active ida-pro or equivalent MCP connection). If connected, you can query IDA directly via MCP tools — no exported files needed. Proceed with the analysis using MCP.
Option B — IDA-NO-MCP exported data:
If MCP is not connected, check if IDA-NO-MCP exported data exists in the current directory:
- Check if
decompile/ directory exists
- Check if there are
.c files inside
If neither MCP nor exported data is available, prompt the user:
No IDA access method detected. Choose one of the following:
Option A — IDA Pro MCP (recommended):
Connect the IDA Pro MCP server so Claude can query IDA directly.
Option B — IDA-NO-MCP export:
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:
int __fastcall sub_401000(int a1, int a2)
{
}
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)
*(_DWORD *)(a1 + 8)
*(_QWORD *)(a1 + 0x20)
*(_BYTE *)(a1 + 4)
Array access:
*(a1 + 8 * i)
a1[i]
Nested structures:
*(*a1 + 0x10)
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);
sub_401000(&v2);
sub_401000(malloc(64));
-
Operations before/after the call:
v1 = malloc(0x40);
*v1 = 0;
*(v1 + 8) = callback;
sub_401000(v1);
-
Collect more offset accesses
Step 4: Traverse Callees for Analysis
Read each callee function and analyze:
-
How parameters are used:
int callee(void *a1) {
return *(a1 + 0x18);
}
-
Passed to other functions:
another_func(a1 + 0x20);
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/printf → string pointer
- 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
struct suggested_name {
void *vtable;
int refcount;
int flags;
char *name;
void *data;
size_t size;
struct node *next;
struct node *prev;
callback_fn handler;
void *user_data;
};