第 35 章 IDA Pro 深度使用
第 4 章讲了 IDA 的基础工作流,本章深入 IDA 的进阶能力:脚本化(IDAPython)、类型系统、FLIRT/Lumina、Hex-Rays 反编译器技巧、插件生态、批量分析。工具深度 = 分析速度。
📍 知识点地图 | 主题:IDA深度 | 前置:第4章 | 后续:— | 核心概念:IDAPython、FLIRT、类型系统、批量分析
35.1 IDA 能力全景图(知识架构)
IDA Pro = 反汇编器 + 反编译器 + 脚本引擎 + 扩展生态
┌─ 反汇编引擎: 多架构(x86/ARM/MIPS/RISC-V/…)
├─ Hex-Rays 反编译器: 汇编 → 伪 C(业界最强)
├─ IDAPython: 完整脚本控制(自动化一切)
├─ IDC: 老式脚本语言
├─ FLIRT 签名: 库函数识别(识别 libc/STL/OpenSSL)
├─ Lumina 服务器: 云端符号共享(同名函数对照)
├─ TIL 类型库: 预置系统类型(Windows API/内核结构)
├─ 调试器: 内置多平台调试
├─ 插件生态: 社区扩展(D-810/obpo/Driver Buddy…)
└─ SDK/API: 用 C++ 写插件
35.2 IDAPython:自动化一切
基本入口
import idautils, idc, ida_funcs, ida_bytes, ida_xref, ida_nalt, ida_hexrays
# 常用三大模块
idautils.Functions() # 所有函数地址
idc.get_func_name(addr) # 函数名
idc.decompile(addr) # 反编译(Python3 + ida_hexrays)
实用脚本模式(直接抄)
# 1. 列出所有函数 + 大小
import idautils, ida_funcs
for f in idautils.Functions():
fn = ida_funcs.get_func(f)
print(hex(f), idc.get_func_name(f), fn.size())
# 2. 批量提取字符串
import idautils, idc
for s in idautils.Strings():
print(hex(s.ea), s.strtype, str(s))
# 3. 批量重命名(sub_XXX → 有意义的名字)
# 配合 LLM: 反编译 → AI 命名 → 脚本应用
# 4. 提取函数内所有 XOR 常量
import idautils, idc, ida_ua
def get_xor_constants(addr):
result = []
for insn in idautils.FuncItems(addr):
if idc.print_insn_mnem(insn) == "xor":
result.append(idc.print_operand(insn, 1))
return result
# 5. 批量反编译 + 输出(喂给 LLM 做语义分析)
import ida_hexrays
for f in list(idautils.Functions())[:50]:
try:
cf = ida_hexrays.decompile(f)
name = idc.get_func_name(f)
with open(f"out/{name}.c", "w") as fp:
fp.write(str(cf))
except Exception:
pass
运行方式
方式 1: IDA GUI → File → Script File…(或 Alt-F7)
方式 2: 命令行批量
ida64 -A -S"myscript.py" -L"log.txt" target.bin
方式 3: headless(idalib,见 35.6)
35.3 类型系统(还原代码的加速器)
为什么重要
没有类型 → 反编译输出全是 int/__int64,可读性差
声明类型后 → 结构体/指针/字符串自动展开 → 伪代码接近源码
核心操作
// 1. 声明结构体(IDA 中快捷键 Ctrl+Shift+S 打开类型窗口)
struct PacketHeader {
uint32_t magic;
uint16_t type;
uint16_t length;
uint8_t payload[0];
};
// 2. 给函数设置原型(右键函数 → Set Item Type,或 Y 键)
int __fastcall decrypt(void *buf, int size, const char *key);
// 3. 给全局变量设置类型
PacketHeader g_header; // 之后反编译自动展开字段
类型推断与传播
□ 反编译中选中变量 → 右键 → Set Lvar Type
□ IDA 的"类型传播": 给一个参数设类型 → 调用点自动带上字段访问
□ 批量推断: 对导入函数参数自动匹配(FLIRT/TIL 自带)
□ 关键收益: 结构体恢复后,memcpy/strcpy 的边界一目了然(漏洞分析利器)
35.4 FLIRT 与 Lumina(识别库函数)
FLIRT(Fast Library Identification and Recognition)
作用: 识别编译进去的标准库函数(printf/malloc/OpenSSL…)
原理: 用签名文件匹配已知函数序言字节
用法:
1. 加载 .sig 文件(File → Load file → FLIRT signature)
2. 自动重命名匹配的函数 → 反编译可读性暴涨
场景: C++ STL、OpenSSL、WDK(驱动)、C 运行时
生成自定义签名: 用 sigmake 对目标库编译生成
Lumina(云端符号共享)
作用: 上传/下载匿名函数特征,匹配其他用户的分析结果
收益: 遇到别人分析过的函数 → 直接拿到名字和注释
注意: 上传到公共服务器有信息泄露风险(内部样本慎用)
35.5 Hex-Rays 反编译器进阶技巧
提升可读性的操作
□ 快捷键整理:
Tab 汇编↔伪代码切换
F5 反编译当前函数
Alt+F5 反编译到文件
; 加注释
N 重命名(变量/函数)
Y 改类型
X 交叉引用
Ctrl+- / + 后退/前进
□ 反编译中处理技巧:
1. 折叠数组: 选中连续数据 → 右键 → Array… → 设维度
2. 定义枚举: 数值 → 右键 → Enum… → 用枚举名替换魔数
3. 内联注释: 重要行加 ; 注释 → 输出可读
4. 隐藏垃圾变量: 伪代码里右键变量 → Delete(缩小输出)
反编译常见问题的处理
| 问题 | 原因 | 对策 |
|---|---|---|
大量 sub_XXX 调用 |
未识别库函数 | FLIRT 签名 |
全是 __int64 |
未设类型 | 类型系统(35.3) |
| 数组没展开 | 类型未知 | 声明数组类型 |
| 条件嵌套混乱 | 优化后逻辑 | 加注释重写伪代码 |
| 反编译失败/不完整 | 花指令/数据混淆 | 先修复指令边界再反编译 |
有 __fastcall 但实际不同 |
调用约定误判 | 手动改原型 |
Hex-Rays 的隐藏能力
□ "Edit → Patch program"(Alt+F1/F2 系列): 直接改汇编再重新反编译
□ 伪代码搜索: 搜索特定模式(如 "qmemcpy")
□ 反编译 → File → Export: 导出 C 文件(生成报告用)
□ 与 IDAPython 联动: decompile() 结果可直接喂给 LLM(第 29 章)
35.6 批量分析(headless / idalib)
命令行自动分析
# -A = 自动模式(无 GUI 对话框)
# -S = 启动脚本
# -L = 日志
ida64 -A -S"batch_analyze.py" -L"log.txt" target.exe
idalib(无 GUI 库模式)
idalib = IDA 的分析引擎库(MCP 工具底层就是它)
优势: 可编程加载多文件、并发分析、无需图形界面
场景: 批量恶意软件分析、漏洞扫描管道、CTF 自动化
批量分析管道架构
输入样本列表
→ idalib 逐个加载
→ 脚本提取(函数/字符串/导入/反编译)
→ LLM 批量语义分类(第 29 章)
→ 可疑样本打标 → 人工深挖
35.7 插件生态(实战必备)
| 插件 | 用途 |
|---|---|
| D-810 | 去控制流平坦化 + MBA 化简 + 不透明谓词(首选) |
| obpo-plugin | 右键一键去 OBPO 混淆 |
| Driver Buddy Reloaded | 驱动自动识别(IOCTL/Dispatch) |
| BinDiff / Diaphora | 二进制对比 |
| Keypatch | 汇编级 patch |
| Lumina | 符号同步 |
| FindCrypt | 加密常量自动识别 |
| wolf | 自动命名(启发式函数命名) |
安装:IDA 插件目录复制 + 重启;D-810 等通过 pip/发布包安装。
35.8 IDA 深度工作流(综合实战)
目标: 快速还原一个中等复杂度的未知二进制
1. survey(4.4 章)→ 架构/入口/字符串/导入分类
2. FLIRT 加载签名 → 库函数自动命名
3. 从可疑字符串 xref → 定位业务函数
4. 类型系统: 声明结构体/函数原型 → 反编译质量提升
5. IDAPython 批量: 提取函数+反编译 → LLM 语义分析(29 章)
6. 逐函数还原 + 注释/重命名(持续做!)
7. 关键逻辑用数据流追踪验证
8. 导出报告(File → Export → C 文件 + 截图)
动手练习
- 用 IDAPython 脚本:列出目标所有函数名+大小,提取所有 URL 字符串,批量导出 20 个函数的反编译结果。
- 给一个含结构体的程序声明结构体类型,对比声明前后的反编译可读性。
- 用 FLIRT 加载一个 SDK 的签名文件,观察库函数识别效果。
- 用 D-810 对一个 OLLVM 混淆函数去平坦化,对比前后伪代码。
深入阅读
- 仓库:
skills/ida-reverse/SKILL.md(72 个 MCP 工具 + 完整工作流) - 仓库:
skills/ida-reverse/references/ida-mcp-cheatsheet.md(MCP 工具速查) - 仓库:
skills/reverse-engineering/tools-advanced.md(高级:D-810、Ghidra 脚本、patch 策略) - 仓库:
skills/reverse-engineering/anti-analysis.md(混淆对抗,配合 D-810) - 仓库:
skills/binary-diff/(跨版本符号迁移,IDA 导出配合)