关于 ida-domain-scripting
ida-domain-scripting 是用于二进制分析与逆向工程的 Skill,可编写并运行自定义 IDAPython 脚本,通过 ida-domain 检查数据库;默认只读,保存修改前需确认。
主要功能
- 01编写自定义 IDAPython 分析脚本
- 02搜索函数与字符串
- 03分析交叉引用和字节模式
- 04检查伪代码与控制流
- 05默认以只读方式执行
适用场景
- 01枚举二进制文件中的函数
- 02查找调用者和字符串引用
- 03检查伪代码与控制流
- 04搜索字节模式
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ hexrayssa/ claude-marketplace --skill ida-domain-scripting安装后在 Claude Code 中输入/ida-domain-scripting确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
API_REFERENCE.mdpyproject.tomlrun.pysetup.py详细介绍
重要——路径解析:
此 skill 可安装在不同位置。执行任何命令之前,请根据加载此 SKILL.md 文件的位置确定 skill 目录,并在以下所有命令中使用该路径。将 $SKILL_DIR 替换为实际找到的路径。
常见安装路径:
- 项目专用:
<project>/.claude/skills/ida-domain-scripting - 手动全局安装:
~/.claude/skills/ida-domain-scripting
IDA Domain 脚本编写
通用二进制分析 skill。我会根据你提出的逆向工程任务编写自定义 IDAPython 代码,并通过通用执行器运行。
关键工作流程——请按顺序执行以下步骤:
-
在 /tmp 中创建带时间戳的工作目录——绝不要将脚本写入 skill 目录;请始终创建工作目录
/tmp/ida-domain-YYYYMMDD_HHMMSS_ffffff-<name>,使用微秒确保唯一性(例如:/tmp/ida-domain-20260109_143052_847291-list-functions)。 使用以下代码生成时间戳:datetime.now(). strftime ('%Y%m%d_%H%M%S_%f')。 下文将始终以 <work_dir> 指代此目录。 -
检查 API_REFERENCE.md 是否存在——始终确认 $SKILL_DIR/API_REFERENCE.md 存在。如果不存在,请告知用户运行 bootstrap。
-
从 skill 目录执行——始终运行:
cd $SKILL_DIR && uv run python run.py <work_dir>/script.py -f <binary> -
保存前先询问——修改数据库的脚本在使用
--save前必须获得用户明确确认。
工作原理
- 你描述想要分析或提取的内容。
- 我在
<work_dir>/script.py中编写自定义 IDA Domain API 代码(时间戳精确到微秒,以支持并行执行)。 - 我通过以下命令运行代码:
cd $SKILL_DIR && uv run python run.py <work_dir>/script.py -f <binary> - 实时显示结果。
- 脚本文件会由你的操作系统自动从 /tmp 中清理。
设置(首次使用)
cd $SKILL_DIR && uv run python setup.py
这会从 GitHub 克隆 ida-domain 并安装依赖项。只需执行一次。
使用特定版本:
uv run python setup.py --ref v0.1.0 # Specific release
uv run python setup.py --ref main # Bleeding edge
要求:
- uv 包管理器
- git
- IDA Pro 9.1+
- 指向 IDA 安装目录的 IDADIR 环境变量
执行模式
步骤 1:将分析脚本写入 <work_dir>
# <work_dir>/script.py
for func in db.functions:
name = db.functions.get_name(func)
print(f"{name}: 0x{func.start_ea:08X}")
步骤 2:从 skill 目录执行
cd $SKILL_DIR && uv run python run.py <work_dir>/script.py -f /path/to/binary
步骤 3:查看结果
脚本会自动添加 Database.open() 样板代码。可通过 db 变量访问所有实体。
常见模式
列出所有函数
# <work_dir>/script.py
for func in db.functions:
name = db.functions.get_name(func)
size = func.end_ea - func.start_ea
print(f"{name}: 0x{func.start_ea:08X} - 0x{func.end_ea:08X} ({size} bytes)")
按名称查找函数
# <work_dir>/script.py
func = db.functions.get_function_by_name("main")
if func:
print(f"Found main at 0x{func.start_ea:08X}")
# Get callers
callers = db.functions.get_callers(func)
print(f"Called by {len(callers)} functions:")
for caller in callers:
print(f" - {db.functions.get_name(caller)}")
else:
print("main not found")
搜索字符串
# <work_dir>/script.py
import re
# Find all strings
for s in db.strings:
print(f"0x{s.address:08X}: {s}")
# Find URLs
url_pattern = re.compile(r"https?://[\w./]+", re.IGNORECASE)
for s in db.strings:
try:
content = str(s)
if url_pattern.search(content):
print(f"URL found: {content}")
except:
pass
分析交叉引用
# <work_dir>/script.py
# Get xrefs TO an address
target = 0x00401000
print(f"References TO 0x{target:08X}:")
for xref in db.xrefs.to_ea(target):
print(f" From 0x{xref.from_ea:08X} (type: {xref.type.name})")
# Get xrefs FROM an address
print(f"References FROM 0x{target:08X}:")
for xref in db.xrefs.from_ea(target):
print(f" To 0x{xref.to_ea:08X} (type: {xref.type.name})")
反编译函数
# <work_dir>/script.py
func = db.functions.get_function_by_name("main")
if func:
try:
lines = db.functions.get_pseudocode(func)
print("\n".join(lines))
except RuntimeError as e:
print(f"Decompilation failed: {e}")
分析函数复杂度
# <work_dir>/script.py
complex_funcs = []
for func in db.functions:
flowchart = db.functions.get_flowchart(func)
if flowchart:
block_count = len(flowchart)
edge_count = sum(b.count_successors() for b in flowchart)
cyclomatic = edge_count - block_count + 2
if cyclomatic > 10:
name = db.functions.get_name(func)
complex_funcs.append((name, func.start_ea, cyclomatic))
complex_funcs.sort(key=lambda x: x[2], reverse=True)
print("Most complex functions:")
for name, addr, cc in complex_funcs[:10]:
print(f" {name}: complexity={cc} at 0x{addr:08X}")
搜索字节模式
# <work_dir>/script.py
# Search for NOP sled
pattern = b"\x90\x90\x90\x90"
results = db.bytes.find_binary_sequence(pattern)
for addr in results:
print(f"Found NOP sled at 0x{addr:08X}")
# Search for x64 function prologue
prologue = b"\x55\x48\x89\xE5" # push rbp; mov rbp, rsp
for addr in db.bytes.find_binary_sequence(prologue):
print(f"Prologue at 0x{addr:08X}")
导出为 JSON
# <work_dir>/script.py
import json
from pathlib import Path
functions = []
for func in db.functions:
name = db.functions.get_name(func)
functions.append({
"name": name,
"start": f"0x{func.start_ea:08X}",
"end": f"0x{func.end_ea:08X}",
"size": func.end_ea - func.start_ea,
})
output = {"module": db.module, "functions": functions}
Path("/tmp/functions.json").write_text(json.dumps(output, indent=2))
print(f"Exported {len(functions)} functions to /tmp/functions.json")
内联执行(简单任务)
对于快速的一次性任务,无需创建文件即可内联执行代码:
# Quick function count
cd $SKILL_DIR && uv run python run.py -c "print(f'Functions: {len(db.functions)}')" -f binary
# Get binary info
cd $SKILL_DIR && uv run python run.py -c "print(f'{db.module}: {db.architecture} {db.bitness}-bit')" -f binary
何时使用内联执行,何时使用文件:
- 内联执行:快速的一次性任务(统计函数数量、获取二进制信息、检查符号是否存在)
- 文件:复杂分析、多步骤任务,以及用户可能希望重新运行的任务
高级用法
如需查看完整的 IDA Domain API 文档,请参阅 API_REFERENCE.md:
- 数据库属性和元数据
- 函数枚举和分析
- 字符串检测和搜索
- 交叉引用查询
- 字节模式匹配
- 控制流分析
- 反编译(Hex-Rays)
- 类型信息
- 注释和名称
提示
- 默认只读——只有在需要保留修改时才使用
--save(并务必先询问用户!) - 超时——默认 30 分钟;长时间运行的分析请使用
--timeout 0 - 不包装模式——脚本已有
Database.open()时使用--no-wrap - 错误处理——反编译和字符串操作始终使用 try-except
- 检查 None——未找到时,
get_function_by_name()等函数会返回 None
故障排除
遇到错误时:
首先在 $SKILL_DIR/ida-domain/ida_domain/ 中搜索方法签名,检查 ida-domain 源代码。API 可能与文档或预期不一致。
未找到虚拟环境:
cd $SKILL_DIR && uv run python setup.py
IDA SDK 加载失败 / IDADIR 错误:
export IDADIR=/path/to/ida
脚本超时:
cd $SKILL_DIR && uv run python run.py --timeout 3600 ... # 1 hour
cd $SKILL_DIR && uv run python run.py --timeout 0 ... # No timeout
AttributeError: 'Xrefs' has no attribute 'get_xrefs_to':
请使用 db.xrefs.to_ea(addr),而不是 db.xrefs.get_xrefs_to(addr)
func_t 对象上的 AttributeError:
在 db.functions 上调用方法,而不是在 func 对象上调用:
# Wrong: func.get_callers()
# Right: db.functions.get_callers(func)
读取字符串时出现 UnicodeDecodeError:
for s in db.strings:
try:
content = str(s)
except:
continue # Skip problematic strings
使用示例
User: "How many functions are in this binary?"
Claude: I'll count the functions. Let me analyze the binary...
[Writes: <work_dir>/script.py]
[Runs: cd $SKILL_DIR && uv run python run.py <work_dir>/script.py -f binary]
[Output: Functions: 250]
The binary contains 250 functions.
User: "Find all functions that call malloc"
Claude: I'll find all callers of malloc...
[Writes: <work_dir>/script.py]
[Runs: cd $SKILL_DIR && uv run python run.py <work_dir>/script.py -f binary]
[Output: malloc called by 15 functions: sub_401000, sub_402000, ...]
Found 15 functions that call malloc:
- sub_401000 at 0x00401000
- sub_402000 at 0x00402000
...
User: "Decompile the main function and save it"
Claude: I'll decompile main and save the output...
[Writes: <work_dir>/script.py]
[Runs: cd $SKILL_DIR && uv run python run.py <work_dir>/script.py -f binary]
[Output: Saved to /tmp/main.c]
Done! The decompiled code is saved to /tmp/main.c