前言:昨天跑resym项目发现input是反编译后的伪c,但手上有20多个bin,不可能手动一个个用IDA分析然后用INP导出,于是让cursor结合INP写了一个自动化批处理的脚本,顺便学一下IDA无头模式

IDA9.0之前,无CLI使用主要依靠命令行,它可以批量反编译文件并导出(结合INP脚本)

1
ida64.exe [选项] 二进制文件

关于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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
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()

# ⚠️ 关键:退出 IDA
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) # 参数 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
# 进入 IDA 安装目录
cd "C:\Program Files\IDA Pro 9.0"

# 安装 IDALib 对应的 Python 包(包名是 idapro)
python -m pip install ./idalib/python

# 激活 IDALib(绑定当前 IDA 安装)
python py-activate-idalib.py

image

image

模版脚本

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
#!/usr/bin/env python3
# ⚠️ 必须是第一个 import,用于初始化 IDA 运行时
import idapro

import idautils
import idc
import ida_hexrays

def main():
# 打开二进制或已有 IDB,True 表示执行自动分析
idapro.open_database("target_binary", True)

# 初始化 Hex-Rays(无头模式必须显式调用)
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​)都无法正常工作。

参考资料