rev-struct
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineserev-struct - Structure Recovery
rev-struct - 结构体恢复
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 exists
decompile/ - 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首先验证当前目录下是否存在IDA-NO-MCP导出的数据:
- 检查是否存在目录
decompile/ - 检查目录内是否存在文件
.c
如果未找到,提示用户:
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 CodeExport 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)./
├── decompile/ # 反编译C代码目录
│ ├── 0x401000.c # 每个函数一个文件,以十六进制地址命名
│ ├── 0x401234.c
│ └── ...
├── decompile_failed.txt # 反编译失败列表
├── decompile_skipped.txt # 跳过的函数列表
├── strings.txt # 字符串表(地址、长度、类型、内容)
├── imports.txt # 导入表(地址:函数名)
├── exports.txt # 导出表(地址:函数名)
└── memory/ # 内存十六进制转储(1MB分块)Function File Format (decompile/*.c)
函数文件格式(decompile/*.c)
Each file contains function metadata comments and decompiled code:
.cc
/*
* 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...
}每个文件包含函数元数据注释和反编译代码:
.cc
/*
* func-name: sub_401000
* func-address: 0x401000
* callers: 0x402000, 0x403000 // 调用该函数的函数列表
* callees: 0x404000, 0x405000 // 该函数调用的函数列表
*/
int __fastcall sub_401000(int a1, int a2)
{
// Decompiled code...
}Structure Recovery Steps
结构体恢复步骤
Step 1: Read Target Function
步骤1:读取目标函数
- 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)
- 根据用户提供的地址,读取
decompile/<address>.c - 解析函数元数据,提取调用方和被调用方列表
- 识别函数中的指针参数(潜在的结构体指针)
Step 2: Collect Memory Access Patterns
步骤2:收集内存访问模式
Search for the following patterns in the target function:
Direct offset access:
c
*(a1 + 0x10) // offset 0x10
*(_DWORD *)(a1 + 8) // offset 0x8, DWORD type
*(_QWORD *)(a1 + 0x20) // offset 0x20, QWORD type
*(_BYTE *)(a1 + 4) // offset 0x4, BYTE typeArray access:
c
*(a1 + 8 * i) // array, element size 8 bytes
a1[i] // array accessNested structures:
c
*(*a1 + 0x10) // first field of struct pointed by a1 is a pointerRecord format:
offset=0x00, size=8, access=read/write, type=QWORD
offset=0x08, size=4, access=read, type=DWORD
...在目标函数中搜索以下模式:
直接偏移访问:
c
*(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数组访问:
c
*(a1 + 8 * i) // array, element size 8 bytes
a1[i] // array access嵌套结构体:
c
*(*a1 + 0x10) // first field of struct pointed by a1 is a pointer记录格式:
offset=0x00, size=8, access=read/write, type=QWORD
offset=0x08, size=4, access=read, type=DWORD
...Step 3: Traverse Callers for Analysis
步骤3:遍历调用方分析
Read each caller function and analyze:
-
Parameter passing: What is passed when calling?c
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:c
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
读取每个调用方函数并分析:
-
参数传递: 调用时传递了什么内容?c
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 -
调用前后的操作:c
v1 = malloc(0x40); // allocate 0x40 bytes *v1 = 0; // offset 0x00 initialization *(v1 + 8) = callback; // offset 0x08 is a function pointer sub_401000(v1); -
收集更多偏移访问记录
Step 4: Traverse Callees for Analysis
步骤4:遍历被调用方分析
Read each callee function and analyze:
-
How parameters are used:c
// In callee int callee(void *a1) { return *(a1 + 0x18); // accesses offset 0x18 } -
Passed to other functions:c
another_func(a1 + 0x20); // offset 0x20 might be a nested struct
读取每个被调用方函数并分析:
-
参数的使用方式:c
// In callee int callee(void *a1) { return *(a1 + 0x18); // accesses offset 0x18 } -
传递给其他函数:c
another_func(a1 + 0x20); // offset 0x20 might be a nested struct
Step 5: Aggregate and Infer
步骤5:汇总与推断
- 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
- 合并所有偏移信息,按偏移排序
- 计算结构体大小:最大偏移值 + 最后一个字段的大小
- 推断字段类型:
- 作为函数指针调用 → 函数指针
- 传递给/
strlen→ 字符串指针printf - 与常量比较 → 枚举/标志位
- 存在增减操作 → 计数器/索引
- 识别常见模式:
- 偏移0是函数指针表 → vtable(C++对象)
- 存在next/prev指针 → 链表节点
- 存在refcount字段 → 引用计数对象
Output Format
输出格式
c
/*
* 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 namec
/*
* 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指针,调用方式:(*(*this))()
/* 0x08 */ int refcount; // 引用计数,存在++/--操作
/* 0x0C */ int flags; // 标志位,与0x1、0x2做与运算
/* 0x10 */ char *name; // 字符串,传递给strlen/printf
/* 0x18 */ void *data; // 数据指针
/* 0x20 */ size_t size; // 大小字段
/* 0x28 */ struct node *next; // 链表next指针
/* 0x30 */ struct node *prev; // 链表prev指针
/* 0x38 */ callback_fn handler; // 回调函数
/* 0x40 */ void *user_data; // 用户数据
};
// Field access examples:
// 0x401000: *(this + 0x08) += 1; // refcount++
// 0x401100: printf("%s", *(this + 0x10)); // print name