手上只有 stripped 样本时,不要先问 REA“这个二进制是做什么的”。更稳的顺序是:先用 file、readelf -h 和 strings 把架构、入口地址和高频字符串交给 REA,再分三轮问入口候选、函数边界和直接调用关系,最后把每条结论拿回 objdump 或反汇编 GUI 核对。判断标准很简单:能指到具体地址、字节或符号的结论,先标假设;反汇编里对得上的,再标事实。
适用场景:只有 stripped 样本,没有符号表,想用 REA 先拿到第一轮入口和调用关系。操作动作:用 file/readelf/strings 喂可验证字段;按架构、入口、调用关系三轮提问,要求 REA 给出证据地址。验证方式:用 objdump -d 或反汇编 GUI 核对入口指令、栈帧、返回指令和 call 目标。风险边界:REA 输出的入口和调用关系默认只能当假设,核对前不要写进分析报告;加壳、混淆或间接跳转场景下,结论要整段降级为未知。
用 file、readelf 和 strings 先给 REA 一份事实
这一步的目的是避免模型凭文件名猜架构、格式和用途。文件名可以改,扩展名可以骗人,只有从文件本身读出的字段才适合作为会话输入。三条命令各自看不同的东西:file 看架构与位宽;readelf -h 看入口地址、机器类型和文件类型;strings 取高频可读串,用来提供字符串线索。
file ./sample
readelf -h ./sample
strings -a -n 6 ./sample | sort | uniq -c | sort -nr | head -n 40
file 输出里关注 ELF 64-bit、x86-64、ARM aarch64 这类架构字段,以及是否 stripped。readelf -h 输出里关注 Entry point address、Machine、Type,把入口地址原样记下来。strings 不要整份粘贴进会话,只贴经过计数排序后的高频串,以及包含 error、path、http、socket、license 这类与用途可能相关的串。贴的时候保留字符串文本和出现次数,不要贴地址,避免让模型把地址和字符串乱关联。只把可验证字段贴进会话,不整份粘贴命令输出,这样 REA 后面说“依据某条字符串”时,你能快速回查。
在会话里按架构、入口、调用关系分三轮提问
把“帮我找入口和调用关系”这种大问题拆成三轮能被证伪的小问题。每轮都要求 REA 说明依据来自哪段字节、哪个符号或哪条字符串。没有依据地址的回答,先当作假设。
第一轮问架构与启动入口。句式:当前样本是 x86-64 ELF,Entry point 为 0x…;请给出该架构下用户代码入口的常见识别特征,并指出样本中 Entry point 附近哪段字节符合这些特征,附字节偏移和反汇编片段。
第二轮问候选函数入口。句式:请列出候选 main 或用户代码入口地址,每条说明依据是调用指令、启动例程符号、字符串交叉引用还是栈帧模式;无法确定的候选请标为未知,不要强行给唯一答案。
第三轮问直接调用关系。句式:以候选入口 0x… 为起点,列出所有直接 call 目标地址;每条给出 call 指令所在地址和操作码字节;间接调用标 unknown 并给出跳转表或寄存器来源;展开一层即可,不要一次展开整张图。
笼统问法与可核对问法差别很大。笼统问法:“分析这个二进制并告诉我函数调用关系。”可核对问法:“以 0x401000 为起点,列出直接 call 目标;每条给出 call 指令地址;无法解析的标 unknown。”笼统问法只能得到像报告的文字,可核对问法能直接拿去反汇编里搜地址。
把 REA 给的入口和函数边界拿回反汇编器核对
REA 给的入口和函数边界必须拿回反汇编器核对。用 objdump -d 或反汇编 GUI 打开同一样本,先跳到它声称的入口地址,看指令是否与描述一致。核对入口地址处指令、函数首尾特征。具体比对点:入口处是否出现 push rbp; mov rbp, rsp 或 sub rsp, imm 这类栈帧建立指令;函数尾部是否有 leave; ret、add rsp, imm; ret 或 pop rbp; ret;ret 前后是否有 int3、nop 对齐填充。如果 REA 把某个地址说成函数入口,但该处只是数据或中间指令,就标记不一致。
objdump -d `--start-address`=0x401000 `--stop-address`=0x401200 ./sample
记录字段建议用一张对照表:REA 声称地址、反汇编实际地址、实际指令字节、函数首特征、函数尾特征、是否一致、差异说明、标注(事实/假设)。标注写法示例:事实——入口地址 0x401000 来自 readelf -h 的 Entry point address,且 objdump 该地址处为 push rbp; mov rbp, rsp;假设——REA 认为 0x401050 是 main,依据是启动例程传递的参数,尚未在反汇编中确认参数传递链;待验证——函数边界止于 0x4010f0,需确认 ret 后是否为对齐填充。
把调用关系整理成带证据的调用链清单
调用关系要整理成带证据的调用链清单,让每条关系都能指回具体的调用指令或交叉引用。表格字段至少包括:被调方、调用方、证据地址、证据类型、是否已核对、备注。证据地址写 call 指令所在地址或 xref 来源地址;证据类型写 call、jmp、数据引用或字符串引用;是否已核对只填“是”或“否”。
发现 REA 漏掉关系时,在反汇编里搜索 call 目标,补充到清单并标注“REA 未提供,人工补充”。发现 REA 凭空补出关系时,回到证据地址确认是否存在 call 或 xref;若不存在,标记“无证据,不采信”,并检查是否由间接调用、跳转表或数据引用误判导致。间接调用统一标 unknown,并记录跳转表地址或寄存器来源,不要为了让调用图完整而把 unknown 猜成具体函数。最终清单里,只有证据地址能和反汇编对应上的关系,才从假设升级为事实;其余保持未知或假设,等下一轮再查。