前言:昨天跑resym项目发现input是反编译后的伪c,但手上有20多个bin,不可能手动一个个用IDA分析然后用INP导出,于是让cursor结合INP写了一个自动化批处理的脚本,顺便学一下IDA无头模式
IDA9.0之前,无CLI使用主要依靠命令行,它可以批量反编译文件并导出(结合INP脚本)
关于IDA的命令行选项,参照Command line switches | Hex-Rays Docs
这里只列出批量反编译需要的参数
| 参数 |
全称 |
作用 |
-A |
Autonomous |
无头模式核心参数,不启动 GUI,自动应答所有对话框 |
-S<script> |
Script |
加载完成后执行指定 IDAPython 脚本(需调用 qexit()) |
-c |
Create |
强制创建新数据库,不复用已有 .idb/.i64 |
-L<logfile> |
Log |
输出日志到指定文件 |
-T<prefix> |
Temp |
指定临时文件前缀 |
-o<idbfile> |
Output |
指定输出数据库路径 |
无头模式 (Headless Mode) 指在不启动图形界面 (GUI) 的情况下运行 IDA,通过脚本自动完成分析、反编译、数据提取等任务。
| 场景 |
传统 GUI 模式的痛点 |
无头模式的优势 |
| 批量样本分析 |
需要手动逐个打开 |
脚本自动遍历处理 |
| CI/CD 集成 |
无法在服务器运行 |
命令行直接调用 |
| 数据集构建 |
效率极低 |
并行处理,可扩展 |
| 自动化流水线 |
需要人工交互 |
全程无人值守 |
9.0及之后,引入了IDALib,它将IDA的分析能力打包成Python库,可以在无CLI下调用 ida_* Python API
对于两种无头运行方式,适用于不同版本和场景:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| ┌─────────────────────────────────────────────────────────────────┐ │ 方案一:传统批处理模式 │ │ (所有 IDA 版本均支持) │ ├─────────────────────────────────────────────────────────────────┤ │ 命令行: ida64.exe -A -S"script.py" binary_file │ │ │ │ 原理: 启动 IDA 进程 → 加载二进制 → 执行脚本 → 退出 │ │ 环境: IDA 内置 Python (IDAPython),与系统 Python 隔离 │ └─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐ │ 方案二:IDALib 库模式 │ │ (IDA 9.0+ 专属) │ ├─────────────────────────────────────────────────────────────────┤ │ 代码: import idalib; idalib.open_database("binary") │ │ │ │ 原理: IDA 作为 Python 包,直接在脚本中调用 API │ │ 环境: 系统 Python,需安装 idalib 包 │ └─────────────────────────────────────────────────────────────────┘
|
| 特性 |
传统批处理模式 (-A -S) |
IDALib 库模式 |
| IDA 版本要求 |
所有版本 |
IDA 9.0+ |
| Python 环境 |
IDA 内置 (隔离) |
系统 Python |
| 调用方式 |
subprocess 进程调用 |
直接 import |
| 资源管理 |
进程退出自动释放 |
需手动关闭数据库 |
| 多任务处理 |
多进程天然隔离 |
需注意资源泄露 |
| 学习成本 |
低 |
中等 |
| 适用场景 |
通用、绿色版 IDA |
深度集成、服务化 |
命令行模式
针对命令行的使用,主要是结合Python+INP实现批量反编译并导出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| ┌──────────────────────────────────────────────────────────────────────┐ │ IDA 批处理执行流程 │ └──────────────────────────────────────────────────────────────────────┘
外部调用者 (Python/Shell) │ │ subprocess.run(["ida64.exe", "-A", "-Sscript.py", "binary"]) ▼ ┌──────────────────────────────────────────────────────────────────────┐ │ IDA 进程启动 │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ 1. 初始化 IDA 核心引擎 │ │ │ │ 2. 加载处理器模块 (pc.dll / arm.dll 等) │ │ │ │ 3. 加载类型库 (gnulnx_x64 等) │ │ │ └────────────────────────────────────────────────────────────────┘ │ │ ▼ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ 4. 加载二进制文件 │ │ │ │ - 解析文件格式 (ELF/PE/Mach-O) │ │ │ │ - 创建内存段 (segment) │ │ │ │ - 识别入口点 │ │ │ └────────────────────────────────────────────────────────────────┘ │ │ ▼ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ 5. 自动分析 (Auto Analysis) ⚠️ 关键阶段 │ │ │ │ - 递归反汇编 │ │ │ │ - 识别函数边界 │ │ │ │ - 构建交叉引用 │ │ │ │ - 类型传播 │ │ │ │ [此阶段可能需要数秒到数分钟] │ │ │ └────────────────────────────────────────────────────────────────┘ │ │ ▼ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ 6. 执行 -S 指定的脚本 │ │ │ │ ⚠️ 必须先调用 ida_auto.auto_wait() 等待分析完成 │ │ │ │ 然后才能正确获取函数列表、调用反编译器 │ │ │ └────────────────────────────────────────────────────────────────┘ │ │ ▼ │ │ ┌────────────────────────────────────────────────────────────────┐ │ │ │ 7. 脚本调用 ida_pro.qexit(0) 退出 IDA │ │ │ └────────────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────┘ │ ▼ 外部调用者收到进程返回码
|
模版脚本
示例IDAPython 批处理脚本模板(无CLI)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
""" IDA 批处理脚本模板 用法: ida64.exe -A -S"this_script.py" binary_file """
import os import ida_auto import ida_hexrays import ida_funcs import ida_nalt import idautils import idc
def main(): """主函数""" print("=" * 60) print("IDA Batch Script") print("=" * 60) print("[*] Waiting for auto-analysis...") ida_auto.auto_wait() print("[+] Auto-analysis completed") if not ida_hexrays.init_hexrays_plugin(): print("[!] Hex-Rays decompiler not available") has_hexrays = False else: print("[+] Hex-Rays initialized") has_hexrays = True input_path = ida_nalt.get_input_file_path() output_dir = os.path.join(os.path.dirname(input_path), "output") os.makedirs(output_dir, exist_ok=True) for func_ea in idautils.Functions(): func_name = idc.get_func_name(func_ea) print(f"[*] Processing: {func_name} @ {hex(func_ea)}") if has_hexrays: try: cfunc = ida_hexrays.decompile(func_ea) if cfunc: output_path = os.path.join(output_dir, f"{hex(func_ea)}.c") with open(output_path, 'w', encoding='utf-8') as f: f.write(str(cfunc)) except Exception as e: print(f" [!] Decompile failed: {e}") print("[+] Done!")
if __name__ == "__main__": main() import ida_pro ida_pro.qexit(0)
|
针对命令行版本,
IDA 提供了两种可执行文件:
| 可执行文件 |
说明 |
ida.exe / ida64.exe |
完整版,包含 GUI 库(-A 时不显示窗口) |
idat.exe / idat64.exe |
纯命令行版 (Text mode),无 GUI 依赖,更轻量 |
推荐:批处理场景优先使用 idat64,资源占用更少。
遇到的坑
- 使用命令行形式的IDA分析二进制文件时,要考虑到IDA分析需要时间,所以并不能在使用ida.exe打开二进制后直接跑IDAPython脚本,需要等待一段时间,IDA提供了api:
ida_auto.auto_wait()
1 2 3 4 5 6 7 8 9 10 11 12
| def main(): for func_ea in idautils.Functions(): decompile(func_ea)
def main(): import ida_auto ida_auto.auto_wait() for func_ea in idautils.Functions(): decompile(func_ea)
|
- 批处理模式下,脚本执行完必须主动退出 IDA,否则进程会挂起:
1 2 3
| import ida_pro ida_pro.qexit(0)
|
- 用的是绿色版IDA,外层Python与-S参数跟的脚本代码所运行的Python环境是隔离开的。
IDALib 库模式 (IDA 9.0+)
IDA 9.0 引入的 IDALib (IDA as a Library) 把 IDA 的分析能力封装成 Python 包,可以直接在系统 Python 中 import 使用,无需启动独立进程。
好处是可以在纯命令行环境下调用IDA的各种api,比如分析二进制文件、反编译、patch、导出数据库等,玩法更加多样。
环境配置
1 2 3 4 5 6 7 8 9
| cd "C:\Program Files\IDA Pro 9.0"
python -m pip install ./idalib/python
python py-activate-idalib.py
|


模版脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
import idapro
import idautils import idc import ida_hexrays
def main(): idapro.open_database("target_binary", True)
if not ida_hexrays.init_hexrays_plugin(): print("[-] Hex-Rays decompiler is not available") return
for func_ea in idautils.Functions(): func_name = idc.get_func_name(func_ea) print(f"\nFunction: {func_name} @ {hex(func_ea)}")
try: cfunc = ida_hexrays.decompile(func_ea) if cfunc: print(str(cfunc)) except ida_hexrays.DecompilationFailure: pass
idapro.close_database()
if __name__ == "__main__": main()
|
坑
- 在 IDALib 模式下,
idapro(或 ida)模块负责初始化 IDA 的核心运行时环境,因此必须作为脚本的第一个导入项。在它完成初始化之前,其它 ida_* 模块(如 idautils、ida_hexrays)都无法正常工作。
参考资料