如何生成标注基本块汇编起止地址的控制流图(CFG)
可行实现方案
方案1:使用LLVM + opt工具生成带地址的CFG(编译阶段生成推荐)
- 第一步:用clang编译生成带调试信息和LLVM IR的目标文件
执行命令:clang -g -c -emit-llvm myfile.c -o myfile.bc - 第二步:使用opt工具生成带汇编地址映射的CFG
执行命令:opt -dot-cfg -cfg-embed-asm -cfg-embed-addr myfile.bc -o /dev/null
生成的.dot文件会自动标注每个基本块对应的汇编起始/结束地址,你可以用dot命令转成png/pdf格式:dot -Tpng cfg.main.dot -o cfg_main.png
注意:需要提前安装llvm套件和graphviz工具,对应软件可直接通过系统包管理器安装。
方案2:GCC编译+objdump反汇编+脚本提取映射
如果必须使用GCC工具链,可以用以下流程实现:
- 第一步:用gcc编译生成带调试信息的可执行文件,关闭链接优化:
执行命令:gcc -g -O0 -fno-plt myfile.c -o myfile - 第二步:用objdump输出带行号和地址的反汇编结果:
执行命令:objdump -dS myfile > myfile.disasm - 第三步:用gcc生成原始CFG的dot文件:
执行命令:gcc -fdump-tree-cfg-graph myfile.c,生成myfile.c.XXXt.cfg.dot格式的原始CFG文件 - 第四步:写简单脚本遍历dot文件里的基本块代码,匹配反汇编文件里的地址区间,手动写入基本块的标签中即可。
方案3:使用二进制分析工具直接从可执行文件生成
如果只有编译好的二进制文件,可以用以下工具直接生成带地址的CFG:
子方案3.1 使用angr二进制分析框架
- 安装angr后执行以下示例代码即可导出带地址的CFG:
import angr proj = angr.Project("myfile", auto_load_libs=False) cfg = proj.analyses.CFGFast() # 导出dot格式,每个节点自带地址范围标注 with open("cfg.dot", "w") as f: f.write(cfg.graph.to_dot())
生成的dot文件中每个基本块节点默认标注了起始地址和块大小,可直接计算出结束地址。
子方案3.2 使用逆向工具(IDA Pro/Ghidra)
- 把二进制文件拖入IDA或Ghidra,等待自动分析完成后,右键对应函数选择「生成控制流图」,导出的图中每个基本块自动标注汇编起始、结束地址,无需额外处理。
内容的提问来源于stack exchange,提问作者Chen
相关产品推荐
相关产品推荐

