一、 反汇编部分 安装并使用Linux下的反汇编目标文件或者可执行文件的objdump工具。添加至环境变量方便编程时使用。 objdump-d命令解析PE文件生成反汇编结果文件; objdump-f命令得到PE文件头信息,找到程序入口点。
二、 文件字符处理 通过正则表达式筛选反汇编文本文件中有效字符,处理为字符数组。去除大量连续的int3中断指令,仅留下一个中断标记。
三、 分析call指令,生成函数列表 经分析,objdump反汇编文件中的call指令指向函数分为四种情况:
1、 静态链接:
1) Call指令所指向地址在文件中,且跳转位置正是函数体开头。
2) Call指令所指向地址在文件中,跳转地址指向ILT(ILT-Incremental Link Table静态函数跳转表),即jmp指令。此jmp指令跳转地址为函数体开头。
2、 动态链接:
1) Call指令所指向地址前有*号,地址不在文件中。
2) Call指令所指向地址在文件中,跳转地址指向ILT,即jmp指令。此jmp指令跳转向另一jmp指令,该jmp指令跳转地址前有*号,地址不在文件中。
属于动态链接的函数,可通过导入表找到其中部分函数的函数名。
分析后处理文件。遍历文件处理出的数组找到所有函数。
思路是将函数列表写成结构体数组。实现时以Python中的类形式存储call指令。类中包括call指令所在地址,跳转地址(即对应函数起始地址),函数结束地址,参数数量等信息。
四、 绘制函数调用关系图 (一) 结构: 对函数列表进行遍历,找到函数体内所有调用的子函数,将每个函数起始地址视为结点,原函数体为父结点,函数体内调用函数为子结点,父结点与子结点连边。遍历结束后,对于所有第一层结点,即无父结点的函数,将其连接至程序入口点。 (一) 绘制: 安装graphviz和pygraphviz库,使用dot语言绘制图。调整字体,结点形状,结点颜色,边颜色,最终生成函数调用关系树。
五、 分析函数局部变量和参数数量。
- 局部变量数量: Ebp寄存器为扩展基址指针寄存器。可存取堆栈中数据。反汇编代码中,形如movl $0x0,-0x4(%ebp) 的指令,即为函数中给局部变量赋初值的指令。通过分析函数体内形如movl $0x0,-0x4(%ebp)的指令数量,即可得函数体内局部变量数量。
- 参数数量: 在call指令前如有push指令,即为将向函数传递的参数入栈指令。因此,统计push指令次数,即可得函数参数数量。
六、 绘制函数内部控制流程图 程序实质上是由有限个顺序、分支和循环三种基本结构排列、嵌套而成。绘制流程图时,考虑绘出分支结构,循环结构,和函数内部调用函数。
1. 分支结构:
a) 简单的if-else:
条件判断与if语句内条件相反,即判断结果为false则跳转。
b) 多层嵌套if-else:
i. 对应debug版反汇编形态
在Debug版里,多层嵌套if-else只是简单重复单层if-else的结构。
ii. 对应release版反汇编形态
c) 复合条件的if判断
2. 循环结构:
a) Do-while循环
DO_TAG:
......
......
CMP XXX,XXX
JXX DO_TAG
b) While循环
WHILE_TAG:
CMP XXX,XXX
JXX WHILE_END_TAG
......
......
CMP XXX,XXX
JXX WHILE_TAG
WHILE_END_TAG:
c) For循环
FOR_START_TAG:
初始化块
JMP CMP_TAG
STEP_TAG:
步长块
CMP_TAG:
反条件判断
JXX FOR_END_TAG
……
……
JXX STEP_TAG
Release版:
(1、)当循环采用常量为判断条件时,相同逻辑的三种循环生成的代码完全相同。
(2、)当循环采用变量为判断条件时,相同逻辑的while与for生成的代码完全相同,而do-while则不同。
总结:循环最大的特点就是一个有条件判断的向上跳转。如果看到了一个判断分支的跳转是向上的,那么这必然就是一个循环。
3. 调用函数:
遍历绘制函数调用关系图时创建的函数列表,找到此函数内调用的所有函数。
(一) 流程结构:
原做法:
i. 预处理
将函数内所有分支/循环/调用函数处理为类对象,在python中实现结构体数组。每一元素视为一结点。
ii. 构建流程结构时,对结构体数组中每一元素,遍历一遍数组,找到父结点,连边。最后将无父结点的元素连向函数起始地址,无子结点的元素连向函数结尾(ret)。
实际应为:
无预处理。遍历一遍函数内语句,将jmp与jcc指令代表的所有控制结构,call指令代表的所有调用函数,入栈,记录地址。遍历至该结构结尾时,出栈并连边。
(二) 绘制: 设计字体,文字颜色,结点形状,结点颜色,边颜色,标注结构名称,标明参数数量和局部变量数量。
七、 使用js生成网页 调用viz.js,将每个dot文本文件传入model.html文件中,绘制图片并以网页形式呈现。