mcpField
I
ida-domain-scripting

ida-domain-scripting

github.com/hexrayssa安全12255 次安装9 周前更新
代码仓库

关于 ida-domain-scripting

ida-domain-scripting 是用于二进制分析与逆向工程的 Skill,可编写并运行自定义 IDAPython 脚本,通过 ida-domain 检查数据库;默认只读,保存修改前需确认。

主要功能

  1. 01编写自定义 IDAPython 分析脚本
  2. 02搜索函数与字符串
  3. 03分析交叉引用和字节模式
  4. 04检查伪代码与控制流
  5. 05默认以只读方式执行

适用场景

  1. 01枚举二进制文件中的函数
  2. 02查找调用者和字符串引用
  3. 03检查伪代码与控制流
  4. 04搜索字节模式

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/hexrayssa/claude-marketplace --skill ida-domain-scripting

安装后在 Claude Code 中输入/ida-domain-scripting确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

API_REFERENCE.md
pyproject.toml
run.py
setup.py

详细介绍

重要——路径解析: 此 skill 可安装在不同位置。执行任何命令之前,请根据加载此 SKILL.md 文件的位置确定 skill 目录,并在以下所有命令中使用该路径。将 $SKILL_DIR 替换为实际找到的路径。

常见安装路径:

  • 项目专用:<project>/.claude/skills/ida-domain-scripting
  • 手动全局安装:~/.claude/skills/ida-domain-scripting

IDA Domain 脚本编写

通用二进制分析 skill。我会根据你提出的逆向工程任务编写自定义 IDAPython 代码,并通过通用执行器运行。

关键工作流程——请按顺序执行以下步骤:

  1. 在 /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> 指代此目录。

  2. 检查 API_REFERENCE.md 是否存在——始终确认 $SKILL_DIR/API_REFERENCE.md 存在。如果不存在,请告知用户运行 bootstrap。

  3. 从 skill 目录执行——始终运行: cd $SKILL_DIR && uv run python run.py <work_dir>/script.py -f <binary>

  4. 保存前先询问——修改数据库的脚本在使用 --save 前必须获得用户明确确认。

工作原理

  1. 你描述想要分析或提取的内容。
  2. 我在 <work_dir>/script.py 中编写自定义 IDA Domain API 代码(时间戳精确到微秒,以支持并行执行)。
  3. 我通过以下命令运行代码:cd $SKILL_DIR && uv run python run.py <work_dir>/script.py -f <binary>
  4. 实时显示结果。
  5. 脚本文件会由你的操作系统自动从 /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

评论

支持 Markdown