mcpField
D
data

data

github.com/allthingsida开发4951 次安装3 周前更新
代码仓库

关于 data

这是一项使用 SQL 查询 IDA 数据库中字符串、字节模式等原始数据的分析技能,帮助分析人员将命中项关联到代码引用,并将发现转交进一步分析或调试。

主要功能

  1. 01搜索已缓存的二进制字符串
  2. 02查找字节和操作码模式
  3. 03关联字符串引用与函数
  4. 04读取有界字节范围
  5. 05提供分析交接指引

适用场景

  1. 01在二进制文件中查找指标或常量
  2. 02定位引用特定字符串的函数
  3. 03高效搜索操作码模式
  4. 04将数据发现交由分诊或调试

安装

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

$npx skills add https://github.com/allthingsida/idasql-skills --skill data

安装后在 Claude Code 中输入/data确认已加载。

附带文件agents/openai.yaml

详细介绍


触发意图

在用户要求执行以下操作时使用此技能:

  • 快速搜索字符串/字节/模式
  • 将字符串证据映射到代码用法
  • 调查原始数据层面的指标(IOC、常量、签名)

转交给:

  • xrefs,从匹配的地址扩展关系
  • analysis,根据数据信号综合研判
  • debugger,在发现结果应驱动补丁/断点操作时使用

首先执行(热启动序列)

-- 1) Validate string availability
SELECT COUNT(*) AS strings FROM strings;

-- 2) Sample high-value strings
SELECT content, printf('0x%X', addr) AS addr
FROM strings
WHERE length >= 8
ORDER BY length DESC
LIMIT 40;

-- 3) If expected strings are missing, rebuild once
SELECT rebuild_strings();

解读指南:

  • 字符串通常是最快的行为线索;应立即转到 xrefs 获取执行上下文。
  • 搜索操作码/模式时,优先使用 byte_search 表,而不是扫描全部指令。

故障与恢复

  • 没有字符串或数量异常偏少:
    • 运行 rebuild_strings(),并使用 COUNT(*) FROM strings 验证。
  • 误报过多:
    • 提高特异性(使用 LIKE、类似正则表达式的模式收窄,以及模块/函数联接筛选条件)。
  • 字节模式搜索范围过广:
    • 限制范围,或将匹配的字节地址联接到 funcs。
  • 需要的是命名函数、标签、结构体或成员,而非字符串内容:
    • 使用 grep,不要使用 strings 或 byte_search。

交接模式

  1. data -> xrefs,将数据命中结果转换为代码路径/函数。
  2. data -> analysis,用于风险评分和活动级洞察。
  3. data -> debugger,用于设置可执行的补丁/监视点。

strings

在二进制文件中找到的字符串字面量。IDA 会维护一个可配置的缓存字符串列表。

列类型描述
addrINT字符串地址
lengthINT字符串长度
typeINT字符串类型(原始编码位)
type_nameTEXT类型名称:ascii、utf16、utf32
widthINT字符宽度(0=1 字节,1=2 字节,2=4 字节)
width_nameTEXT宽度名称:1-byte、2-byte、4-byte
layoutINT字符串布局(0=以 null 结尾,1-3=Pascal 格式)
layout_nameTEXT布局名称:termchr、pascal1、pascal2、pascal4
encodingINT编码索引(0=默认)
contentTEXT字符串内容(实际文本——不是 value 或 text)

字符串类型编码: IDA 将字符串类型存储为一个 32 位值:

  • 位 0-1:宽度(0=1B/ASCII,1=2B/UTF-16,2=4B/UTF-32)
  • 位 2-7:布局(0=TERMCHR,1=PASCAL1,2=PASCAL2,3=PASCAL4)
  • 位 8-15:term1(第一个终止字符)
  • 位 16-23:term2(第二个终止字符)
  • 位 24-31:编码索引
-- Find error messages
SELECT content, printf('0x%X', addr) as addr FROM strings WHERE content LIKE '%error%';

-- ASCII strings only
SELECT * FROM strings WHERE type_name = 'ascii';

-- UTF-16 strings (common in Windows)
SELECT * FROM strings WHERE type_name = 'utf16';

-- Count strings by type
SELECT type_name, layout_name, COUNT(*) as count
FROM strings GROUP BY type_name, layout_name ORDER BY count DESC;

重要: 对于新的分析(exe/dll),字符串会自动生成。对于现有数据库(i64/idb),字符串已保存。如果意外看到 0 个字符串,请运行一次 SELECT rebuild_strings() 以重建列表。请参阅下文的“字符串列表界面”部分。


字符串引用(显式联接模式)

直接使用 strings + xrefs + funcs。这是标准模式。

-- Find call sites/functions referencing error-like strings
SELECT
    s.content as string_value,
    printf('0x%X', x.from_addr) as ref_addr,
    (SELECT name FROM funcs WHERE x.from_addr >= addr AND x.from_addr < end_addr LIMIT 1) as func_name
FROM strings s
JOIN xrefs x ON x.to_addr = s.addr
WHERE s.content LIKE '%error%' OR s.content LIKE '%fail%'
ORDER BY func_name, ref_addr;

-- Functions with most string references
SELECT
    (SELECT name FROM funcs WHERE x.from_addr >= addr AND x.from_addr < end_addr LIMIT 1) as func_name,
    COUNT(*) as string_refs
FROM strings s
JOIN xrefs x ON x.to_addr = s.addr
GROUP BY func_name
ORDER BY string_refs DESC
LIMIT 10;

bytes 表——读取、修补和有界窗口

所有字节访问都通过 bytes 表进行。 隐藏的 start_addr 和 n 输入列成对用于有界读取;批量读取十六进制时使用 hex(blob_concat(value)),批量读取 BLOB 时使用 blob_concat(value)。

形式SQL
读取 1 个字节SELECT value FROM bytes WHERE addr = 0x401000
将 N 个字节读取为十六进制(大写,无空格)SELECT hex(blob_concat(value)) FROM (SELECT value FROM bytes WHERE start_addr = 0x401000 AND n = 16 ORDER BY addr)
将 N 个字节读取为 BLOBSELECT blob_concat(value) FROM (SELECT value FROM bytes WHERE start_addr = 0x401000 AND n = 16 ORDER BY addr)
读取一个范围SELECT value FROM bytes WHERE addr >= 0x401000 AND addr < 0x401010 ORDER BY addr

隐藏的 start_addr + n 列会请求从 X 开始的恰好 N 个连续字节。它们特意与可见的 addr 列区分开,这样针对 addr 的任何谓词(连接、复合 WHERE)都能由 SQLite 执行。读取有界窗口时不会跳过未映射的地址;映射区域之外的行会返回 get_byte() 在该处的结果。

blob_concat(value) 是一个内置聚合函数,可将行值拼接为一个 BLOB;hex() 是 SQLite 内置的 BLOB→十六进制辅助函数(大写)。

无界范围注意事项

WHERE addr > X 如果没有上界或 LIMIT,会从 X 开始遍历直到映像末尾的所有已映射字节——数百万行,耗时数秒。读取时始终配合以下条件之一:

  • WHERE start_addr = X AND n = N(有界读取形式)
  • AND addr < B(双边范围)
  • 外层 LIMIT N

该表没有单次调用上限;只要约束对有界,就支持任意大的窗口。

需要 IDA 项的大小/类型元数据时,请使用 heads。


二进制搜索表

对原始字节/操作码使用 byte_search。它要求 WHERE pattern = ...;matched_hex 是输出列,不是搜索输入。

列类型描述
addrINT匹配地址
matched_hexTEXT以十六进制文本呈现的匹配字节
matched_bytesBLOB原始字节形式的匹配字节
sizeINT匹配大小(字节)
patternHIDDEN TEXT必需的 IDA 字节模式输入
start_addrHIDDEN INT可选的包含式下界
end_addrHIDDEN INT可选的排除式上界
max_resultsHIDDEN INT可选的生成结果上限

模式语法(IDA 原生):

  • "48 8B 05" - 精确字节(十六进制,以空格分隔)
  • "48 ? 05" 或 "48 ?? 05" - ? = 任意字节通配符(仅限完整字节)
  • "(01 02 03)" - 可选项(匹配其中任意字节)

注意: 字节模式不支持半字节通配符和正则表达式。

示例:

-- Find all matches for a pattern
SELECT addr, matched_hex, size
FROM byte_search
WHERE pattern = '48 8B ? 00'
LIMIT 10;

-- First match only
SELECT printf('0x%llX', addr) AS addr
FROM byte_search
WHERE pattern = 'CC CC CC'
ORDER BY addr
LIMIT 1;

-- Search with alternatives
SELECT addr, matched_hex
FROM byte_search
WHERE pattern = 'E8 (01 02 03 04)'
LIMIT 20;

优化模式:查找使用特定指令的函数

若要高效回答“有多少个函数使用了 RDTSC 指令?”:

-- Count unique functions containing RDTSC (opcode: 0F 31)
SELECT COUNT(DISTINCT f.addr) as count
FROM byte_search b
JOIN funcs f ON b.addr >= f.addr AND b.addr < f.end_addr
WHERE b.pattern = '0F 31';

-- List those functions with names
SELECT DISTINCT
    f.addr as func_addr,
    f.name as func_name
FROM byte_search b
JOIN funcs f ON b.addr >= f.addr AND b.addr < f.end_addr
WHERE b.pattern = '0F 31';

这比扫描所有反汇编行快得多,因为:

  • byte_search 使用 IDA 的原生二进制搜索
  • 包含关系连接使用紧凑的 funcs 表,而不是扫描每条指令

选择合适的搜索方式

  • 对函数、标签、结构体、枚举和成员等命名实体使用 grep。
  • 用户要搜索二进制中的字面字符串内容时,使用 strings。
  • 目标是原始字节或操作码模式时,使用 byte_search。

SQL 界面 — 字符串列表

IDA 会维护一个缓存字符串列表。使用 rebuild_strings() 检测并缓存字符串,使用 COUNT(*) FROM strings 获取当前数量,并使用 strings 进行行级分析。

界面描述
rebuild_strings()使用 ASCII + UTF-16 重建,最小长度为 5(默认值)
rebuild_strings(minlen)使用自定义最小长度重建
rebuild_strings(minlen, types)使用自定义长度和类型掩码重建
SELECT COUNT(*) FROM strings当前字符串列表数量(无需实例化行即可优化获取)

类型掩码值:

  • 1 = 仅 ASCII(STRTYPE_C)
  • 2 = 仅 UTF-16(STRTYPE_C_16)
  • 4 = 仅 UTF-32(STRTYPE_C_32)
  • 3 = ASCII + UTF-16(默认值)
  • 7 = 所有类型
-- Check current string count
SELECT COUNT(*) AS strings FROM strings;

-- Rebuild with defaults (ASCII + UTF-16, minlen 5)
SELECT rebuild_strings();

-- Rebuild with shorter minimum length
SELECT rebuild_strings(4);

-- Rebuild with specific types
SELECT rebuild_strings(5, 1);   -- ASCII only
SELECT rebuild_strings(5, 7);   -- All types (ASCII + UTF-16 + UTF-32)

-- Typical workflow: rebuild then query
SELECT rebuild_strings();
SELECT * FROM strings WHERE content LIKE '%error%';

重要 — Agent 处理字符串查询的行为: 当用户询问字符串(例如,“显示字符串”“这个二进制文件中有哪些字符串”)时:

  1. 首先运行 SELECT rebuild_strings(),确保已检测到字符串
  2. 然后查询 strings 表

rebuild_strings() 函数会使用合理的默认值(ASCII + UTF-16,最小长度为 5)配置 IDA 的字符串检测,并重建字符串列表。这样即使数据库之前未进行过字符串分析,用户也能获得结果。


性能规则

表/函数架构说明
COUNT(*) FROM strings缓存表计数路径O(1) 获取当前字符串列表数量
strings查询范围内每次扫描时从 IDA 的实时字符串列表实例化(不使用持久化的 vtable 缓存);速度快,因为 IDA 的 strlist 已构建完成。rebuild_strings() 会重新生成 IDA 底层的字符串列表
byte_search原生二进制搜索表远快于遍历 instructions 表
bytes WHERE addr = X点查找O(1);虚拟表索引
bytes WHERE start_addr = X AND n = N通过隐藏的 start_addr + n 进行有界读取O(N);虚拟表索引
bytes WHERE addr >= A AND addr < B范围扫描O(范围);虚拟表索引
bytes WHERE addr > X(无界)范围扫描避免使用 — 会遍历直到映像末尾的每个已映射字节;请使用有界形式

关键规则:

  • 在新数据库中首次查询字符串之前,或在可能创建新字符串的代码/数据更改之后,始终调用 rebuild_strings()。
  • byte_search 使用 IDA 的原生二进制搜索引擎;要“查找包含操作码 X 的函数”,应将匹配项按包含关系与 funcs 联接,而不是扫描 instructions 表。
  • strings 表是缓存字符串列表的快照。如果 IDA 的分析在首次查询后创建了新字符串,请再次调用 rebuild_strings()。
  • 将字符串与函数交叉引用时,strings + xrefs + funcs JOIN 模式是标准做法 — IDA 的 xref 索引让 JOIN 十分快速。

高级数据模式(CTE)

安全相关字符串分流

按安全相关性对字符串分类,以便快速评估威胁:

-- Categorize strings by security relevance
SELECT rebuild_strings();

WITH categorized AS (
    SELECT addr, content,
        CASE
            WHEN content LIKE '%password%' OR content LIKE '%passwd%' OR content LIKE '%secret%'
                THEN 'credential'
            WHEN content LIKE '%http://%' OR content LIKE '%https://%' OR content LIKE '%ftp://%'
                THEN 'url'
            WHEN content LIKE '%error%' OR content LIKE '%fail%' OR content LIKE '%exception%'
                THEN 'error'
            WHEN content LIKE '%debug%' OR content LIKE '%trace%' OR content LIKE '%assert%'
                THEN 'debug'
            WHEN content LIKE '%.exe%' OR content LIKE '%.dll%' OR content LIKE '%.sys%'
                THEN 'file_path'
            WHEN content LIKE '%HKEY_%' OR content LIKE '%SOFTWARE\\%'
                THEN 'registry'
            ELSE 'other'
        END AS category
    FROM strings
    WHERE length >= 5
)
SELECT category, COUNT(*) AS count,
       GROUP_CONCAT(SUBSTR(content, 1, 60), ' | ') AS samples
FROM categorized
WHERE category != 'other'
GROUP BY category
ORDER BY count DESC;
将字符串引用与函数大小结合进行可疑度评分

引用安全相关字符串且规模较大的函数是高优先级目标:

-- Suspicious functions: reference interesting strings AND are non-trivial
WITH interesting_strings AS (
    SELECT addr, content FROM strings
    WHERE content LIKE '%password%' OR content LIKE '%encrypt%'
       OR content LIKE '%decrypt%' OR content LIKE '%http%'
       OR content LIKE '%socket%' OR content LIKE '%connect%'
),
string_funcs AS (
    SELECT DISTINCT (SELECT addr FROM funcs WHERE x.from_addr >= addr AND x.from_addr < end_addr LIMIT 1) AS func_addr,
           s.content AS matched_string
    FROM interesting_strings s
    JOIN xrefs x ON x.to_addr = s.addr
    WHERE (SELECT addr FROM funcs WHERE x.from_addr >= addr AND x.from_addr < end_addr LIMIT 1) IS NOT NULL
)
SELECT (SELECT name FROM funcs WHERE sf.func_addr >= addr AND sf.func_addr < end_addr LIMIT 1) AS func_name,
       printf('0x%X', sf.func_addr) AS addr,
       f.size AS func_size,
       GROUP_CONCAT(sf.matched_string, ' | ') AS strings_referenced
FROM string_funcs sf
JOIN funcs f ON f.addr = sf.func_addr
GROUP BY sf.func_addr
ORDER BY f.size DESC
LIMIT 20;
查找同时引用加密相关字符串和网络相关字符串的函数

跨类别关联有助于识别数据外泄或 C2 通信:

-- Functions touching both crypto and network strings
WITH crypto_refs AS (
    SELECT DISTINCT (SELECT addr FROM funcs WHERE x.from_addr >= addr AND x.from_addr < end_addr LIMIT 1) AS func_addr
    FROM strings s JOIN xrefs x ON x.to_addr = s.addr
    WHERE s.content LIKE '%crypt%' OR s.content LIKE '%aes%'
       OR s.content LIKE '%cipher%' OR s.content LIKE '%hash%'
),
network_refs AS (
    SELECT DISTINCT (SELECT addr FROM funcs WHERE x.from_addr >= addr AND x.from_addr < end_addr LIMIT 1) AS func_addr
    FROM strings s JOIN xrefs x ON x.to_addr = s.addr
    WHERE s.content LIKE '%socket%' OR s.content LIKE '%connect%'
       OR s.content LIKE '%send%' OR s.content LIKE '%recv%'
       OR s.content LIKE '%http%'
)
SELECT (SELECT name FROM funcs WHERE c.func_addr >= addr AND c.func_addr < end_addr LIMIT 1) AS func_name,
       printf('0x%X', c.func_addr) AS addr
FROM crypto_refs c
JOIN network_refs n ON n.func_addr = c.func_addr;

另请参阅

  • disassembly — 字符串/字节在代码中的引用位置(针对操作数的读取)。
  • xrefs — 指向目标地址的数据引用;从数据命中项跳转到其使用者的标准途径。
  • debugger — 字节修补会使用 bytes 表;此技能负责读取形式。
  • analysis — 将字符串/导入项用作分流信号。

评论

支持 Markdown