关于 idapython
idapython 技能说明如何通过 SQL 在 IDA 进程内执行 Python 代码或脚本,适合需要调用 IDA SDK、运行复杂分析或复用现有脚本的用户。它涵盖运行时开关、输出限制和隔离且可持续的 Python 命名空间。
主要功能
- 01通过 SQL 执行 Python 代码和文件
- 02按 sandbox 隔离并保留状态
- 03可选设置输出字节上限
- 04Python 异常作为 SQL 错误返回
适用场景
- 01调用 idasql 未提供的 IDA SDK API
- 02执行复杂算法或自定义模式匹配
- 03在 IDA 中自动操作界面
- 04复用现有 Python 脚本
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ allthingsida/ idasql-skills --skill idapython安装后在 Claude Code 中输入/idapython确认已加载。
附带文件agents/openai.yaml
详细介绍
Python 执行 SQL 函数
| 函数 | 描述 |
|---|---|
idapython_snippet(code[, sandbox]) | 执行 Python 代码片段并返回捕获的输出文本 |
idapython_file(path[, sandbox]) | 执行 Python 文件并返回捕获的输出文本 |
运行时保护
默认情况下会禁用 Python 执行。使用以下命令启用:
PRAGMA idasql.enable_idapython = 1;
默认情况下,捕获的 print 输出不设上限。若要限制可能失控或输出过多的代码片段(避免耗尽内存或响应容量),请设置可选的字节上限;设为 0 可恢复为不设上限:
PRAGMA idasql.idapython_output_max = 65536; -- cap captured output at 64 KiB
PRAGMA idasql.idapython_output_max = 0; -- unbounded (default)
如需确认 enable_idapython 和 idapython_output_max 的当前值(以及其他运行时控制项),请查询 SELECT * FROM runtime_settings WHERE scope = 'idasql'。这是一个只读发现视图,用于查看 PRAGMA idasql.* 接口。请参阅 connect 技能。
示例
SELECT idapython_snippet('print("hello from idapython")');
SELECT idapython_file('C:/temp/script.py');
SELECT idapython_snippet('counter = globals().get("counter", 0) + 1; print(counter)', 'alpha');
注意事项
- 默认禁用,直到启用 pragma
- Python 异常会作为 SQL 错误传递
sandbox会按沙箱键隔离并持久保存 Python 全局变量
两种 Python 上下文(重要)
- 主机端 Python 客户端(位于 IDA 之外):使用
requests.post(.../query, data=sql)通过 HTTP 发送 SQL。请求正文可以是一条语句,也可以是以分号分隔的脚本;每个响应都使用规范的results[]信封格式(单条语句的结果是包含一个元素的数组,请读取results[i].rows)。适用于循环、批量更新和自动化编排。请参阅connect技能中的 HTTP 客户端模式。 - 通过 SQL 使用 IDAPython(位于 IDA 内):需要在进程内直接调用 IDA SDK API 时,使用
idapython_snippet()/idapython_file()。
对比示例:
# Host-side Python (outside IDA): sends SQL over HTTP
import requests
requests.post("http://127.0.0.1:8080/query", data="SELECT COUNT(*) FROM funcs")
-- IDAPython (inside IDA): executes Python in IDA runtime
SELECT idapython_snippet('import idaapi; print(idaapi.get_kernel_version())');
沙箱行为
每个沙箱键都会创建一个隔离的 Python 命名空间:
- 在一个沙箱中设置的变量在另一个沙箱中不可见
- 相同的沙箱键会在多次调用间复用其命名空间(状态会在会话期间持久保存)
- 未提供沙箱键时,代码会在默认全局命名空间中运行
错误传递
Python 脚本引发异常时,该异常会作为 SQL 错误传递:
-- This will return an error: "NameError: name 'undefined_var' is not defined"
SELECT idapython_snippet('print(undefined_var)');
何时使用 IDAPython,何时使用 SQL
| 使用场景 | 最佳工具 | 原因 |
|---|---|---|
| 查询、筛选或聚合数据 | SQL | JOIN、CTE、GROUP BY、窗口函数——SQL 专为此类任务设计 |
| 跨表分析 | SQL | 使用 SQL 对 funcs、xrefs、strings、ctree 执行 JOIN 很自然 |
| 报告和计数 | SQL | COUNT、SUM、AVG、GROUP_CONCAT——无需 Python 循环 |
| 复杂算法 | IDAPython | 图算法、自定义模式匹配、机器学习流水线 |
| idasql 未提供的 IDA SDK API | IDAPython | 某些 IDA SDK 功能未作为 SQL 表或函数公开 |
| UI 自动化 | IDAPython | 打开视图、移动光标、触发 IDA 操作 |
| 现有脚本 | IDAPython | 无需改写为 SQL 即可复用现有 .py 脚本 |
**一般原则:**先从 SQL 入手。如果发现自己需要嵌套循环、递归算法,或 idasql 未公开的 IDA API,就使用 idapython_snippet() 作为桥接方式。
实际用例
运行自定义分析脚本
-- Enable Python execution first
PRAGMA idasql.enable_idapython = 1;
-- Run a script that collects custom metrics
SELECT idapython_snippet('
import idautils, idc
count = 0
for func_addr in idautils.Functions():
if idc.get_func_attr(func_addr, idc.FUNCATTR_FLAGS) & 0x4: # FUNC_LIB
count += 1
print(f"Library functions: {count}")
');
访问 idasql 未公开的 IDA SDK API
-- Example: get processor-specific register names
SELECT idapython_snippet('
import ida_idp
for i in range(ida_idp.ph_get_regnames().__len__()):
name = ida_idp.ph_get_regnames()[i]
if name:
print(f"{i}: {name}")
');
桥接模式:Python 生成 JSON,SQL 处理数据
需要借助 Python 的提取能力和 SQL 的分析能力时:
-- Python extracts data as JSON
SELECT idapython_snippet('
import json, idautils, idc
result = []
for addr in idautils.Functions():
flags = idc.get_func_attr(addr, idc.FUNCATTR_FLAGS)
if flags & 0x4: # FUNC_LIB
result.append({"addr": addr, "name": idc.get_func_name(addr)})
print(json.dumps(result))
');
-- Then process the JSON output in SQL using json_each()
-- (copy the output from above into the query)
另请参阅
- 请先查看相关的 SQL 技能(
disassembly、decompiler、types、data、xrefs、annotations、debugger)——仅当该任务没有对应的 SQL 接口时,再使用 IDAPython。 functions——SQL 函数目录;编写脚本前,请先确认是否已有标量函数或辅助函数可用。
评论
支持 Markdown