rev-struct

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

rev-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:
  1. Check if
    decompile/
    directory exists
  2. Check if there are
    .c
    files inside
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导出的数据:
  1. 检查是否存在
    decompile/
    目录
  2. 检查目录内是否存在
    .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 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)
./
├── 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
.c
file contains function metadata comments and decompiled code:
c
/*
 * 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...
}

每个
.c
文件包含函数元数据注释和反编译代码:
c
/*
 * 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:读取目标函数

  1. Based on the user-provided address, read
    decompile/<address>.c
  2. Parse function metadata, extract callers and callees lists
  3. Identify pointer parameters in the function (potential structure pointers)
  1. 根据用户提供的地址,读取
    decompile/<address>.c
  2. 解析函数元数据,提取调用方和被调用方列表
  3. 识别函数中的指针参数(潜在的结构体指针)

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 type
Array access:
c
*(a1 + 8 * i)          // array, element size 8 bytes
a1[i]                  // array access
Nested structures:
c
*(*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
...
在目标函数中搜索以下模式:
直接偏移访问:
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:
  1. 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
  2. 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);
  3. Collect more offset accesses
读取每个调用方函数并分析:
  1. 参数传递: 调用时传递了什么内容?
    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
  2. 调用前后的操作:
    c
    v1 = malloc(0x40);     // allocate 0x40 bytes
    *v1 = 0;               // offset 0x00 initialization
    *(v1 + 8) = callback;  // offset 0x08 is a function pointer
    sub_401000(v1);
  3. 收集更多偏移访问记录

Step 4: Traverse Callees for Analysis

步骤4:遍历被调用方分析

Read each callee function and analyze:
  1. How parameters are used:
    c
    // In callee
    int callee(void *a1) {
        return *(a1 + 0x18);  // accesses offset 0x18
    }
  2. Passed to other functions:
    c
    another_func(a1 + 0x20);  // offset 0x20 might be a nested struct
读取每个被调用方函数并分析:
  1. 参数的使用方式:
    c
    // In callee
    int callee(void *a1) {
        return *(a1 + 0x18);  // accesses offset 0x18
    }
  2. 传递给其他函数:
    c
    another_func(a1 + 0x20);  // offset 0x20 might be a nested struct

Step 5: Aggregate and Infer

步骤5:汇总与推断

  1. Merge all offset information, sort by offset
  2. Calculate struct size: max(offset) + last_field_size
  3. 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
  4. Identify common patterns:
    • Offset 0 is a function pointer table → vtable (C++ object)
    • next/prev pointers → linked list node
    • refcount field → reference counted object

  1. 合并所有偏移信息,按偏移排序
  2. 计算结构体大小:最大偏移值 + 最后一个字段的大小
  3. 推断字段类型:
    • 作为函数指针调用 → 函数指针
    • 传递给
      strlen
      /
      printf
      → 字符串指针
    • 与常量比较 → 枚举/标志位
    • 存在增减操作 → 计数器/索引
  4. 识别常见模式:
    • 偏移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 name
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指针,调用方式:(*(*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