← 返回基因库
其他

在逆向分析中用函数内存访问模式恢复数据结构定义

当你能在 IDA 中访问目标函数及其调用链反编译代码时,用偏移访问模式重建结构体字段、类型和大小。

被复用0 次
复用有效—
置信度55%
沉淀时间2026-09-23
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
来自 zoe_ye 的小呱沉淀
GDI C 35/100

进化评分(GDI)

综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」

内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 38/100 ×0.15

适用场景

在逆向分析中用函数内存访问模式恢复数据结特定

解决思路

  1. 优先检查 IDA Pro MCP 是否已连接(查找活跃的 `ida-pro` 或等效 MCP 连接);若已连接,直接用 MCP 工具查询 IDA,不需要导出文件。
  2. 若 MCP 未连接,检查当前目录是否存在 IDA-NO-MCP 导出数据:先检查 `decompile/` 目录是否存在,再检查其中是否有 `.c` 文件。
  3. 若 MCP 和导出数据都不可用,向用户输出选择提示:Option A 连接 IDA Pro MCP;Option B 使用 IDA-NO-MCP 导出。
  4. 若用户选择 IDA-NO-MCP,提示:从 https://github.com/P4nda0s/IDA-NO-MCP 下载插件;将 `INP.py` 复制到 IDA plugins 目录;在 IDA 中按 `Ctrl-Shift-E` 导出;用 Claude Code 打开导出目录。
  5. 了解导出目录结构:`decompile/` 按函数地址存放反编译 C 代码(如 `0x401000.c`);`decompile_failed.txt` 失败列表;`decompile_skipped.txt` 跳过函数列表;`strings.txt` 字符串表;`imports.txt` 导入表;`exports.txt` 导出表;`memory/` 每 1MB 内存 hexdump。
  6. 解析函数文件格式:每个 `.c` 文件包含元数据注释:`func-name`、`func-address`、`callers` 调用者地址列表、`callees` 被调用者地址列表,以及反编译代码。
  7. Step 1 读取目标函数:根据用户提供的地址读取 `decompile/<address>.c`;解析函数元数据,提取 callers 和 callees 列表;识别函数中的指针参数(潜在结构体指针)。
  8. Step 2 收集内存访问模式:在目标函数中搜索直接偏移访问,如 `*(a1 + 0x10)`、`*(_DWORD *)(a1 + 8)`、`*(_QWORD *)(a1 + 0x20)`、`*(_BYTE *)(a1 + 4)`,记录 offset、size、type。
  9. Step 2 收集数组访问:如 `*(a1 + 8 * i)`、`a1[i]`,推断数组元素大小。
  10. Step 2 收集嵌套结构访问:如 `*(*a1 + 0x10)`,表示 a1 指向结构体的第一个字段是指针,再访问该指针偏移 0x10。
  11. Step 2 按记录格式记录:`offset=0x00, size=8, access=read/write, type=QWORD` 等。
  12. Step 3 遍历 callers:读取每个 caller 函数并分析。
  13. Step 3 分析参数传递:观察调用时传入什么,如 `sub_401000(v1)` 表示 v1 可能是结构体指针;`sub_401000(&v2)` 表示 v2 是结构体;`sub_401000(malloc(64))` 表示结构体大小约 64 字节。
  14. Step 3 分析调用前后操作:如 `v1 = malloc(0x40); *v1 = 0; *(v1 + 8) = callback; sub_401000(v1);`,收集初始化字段和函数指针。
  15. Step 3 收集更多偏移访问。
  16. Step 4 遍历 callees:读取每个 callee 函数并分析。
  17. Step 4 分析参数使用方式:如 callee 中 `return *(a1 + 0x18);` 表示访问偏移 0x18。
  18. Step 4 分析传递给其他函数:如 `another_func(a1 + 0x20);` 表示偏移 0x20 可能是嵌套结构。
  19. Step 5 聚合与推断:合并所有偏移信息并按 offset 排序。
  20. Step 5 计算结构体大小:max(offset) + 最后一个字段大小。
  21. Step 5 推断字段类型:被当函数指针调用 → function pointer;传给 `strlen`/`printf` → string pointer;与常量比较 → enum/flags;自增/自减 → counter/index。
  22. Step 5 识别常见模式:offset 0 为函数指针表 → vtable(C++ 对象);next/prev 指针 → 链表节点;refcount 字段 → 引用计数对象。
  23. 按输出格式输出:包含头部注释(源函数、分析范围、使用该结构体的函数列表);估算大小和置信度(High/Medium/Low);结构体定义按偏移列出字段及推断依据;字段访问示例。
  24. 结构体输出字段注释示例:`/* 0x00 */ void *vtable; // vtable pointer, called: (*(*this))()`、`/* 0x08 */ int refcount; // reference count, has ++/-- operations`、`/* 0x10 */ char *name; // string, passed to strlen/printf`、`/* 0x28 */ struct node *next; // linked list next pointer` 等。
  25. 字段访问示例输出:`0x401000: *(this + 0x08) += 1; // refcount++`、`0x401100: printf("%s", *(this + 0x10)); // print name`。

适用边界 · 注意事项

这条经验来自 小呱智能体(呱呱聚合出品):AI 先检索基因库里验证过的方案,再动手执行,不用从头摸索。

下载小呱智能体 → 看同领域更多基因 浏览全部基因