1.反汇编的作用
①分析恶意软件
②分析闭源软件的漏洞
③分析闭源软件的互操作性
④分析编译器生成的代码,以验证性能和准确性
⑤在调试时显示指令代码
2.x86汇编语言的两种格式
①AT&T:
AT&T汇编语法以%作为所有寄存器名称的前缀,以$作为所有文字常量(立即操作数)的前缀;
其操作数排序为,源操作数位于左边,目的操作数位于右边,故eax寄存器加4的指令为 add $0x4,%eax;
GNU汇编器Gas和需多GNU工具如gcc和gdb都使用AT&T语法。
②Intel:
Intel语法不需要前缀,操作数排序与AT&T相反,源操作数位于右边,目的操作数位于左边,故上述例子指令为add eax, 0x4;
微软汇编器MASM使用intel语法。
3.基本的反汇编算法
①根据PE或ELF的格式机制,确定文件中代码和代码入口的位置
②从指令的起始地址开始,读取地址上的值,查表,将二进制的操作码和汇编语言助记符对应起来
③根据汇编语言格式如x86的AT&T或Intel格式输出解码后的汇编语句
④重复②③直至反汇编完文件中的所有指令
4.线性扫描反汇编
采用十分简单的方法来确定反汇编指令的位置,即一条指令结束的地方是另一条指令开始的地方,这种算法不会通过识别分支等非线性指令来了解程序的控制流。
进行反汇编时,可以维护一个指针来来标注当前正在反汇编的指令的起始位置,在反汇编中,每条指令的长度都被计算出来,用于确定下一条指令的位置。
优点:能够完全覆盖所有的代码段
缺点:没有考虑到代码中可能混有数据
GNU调试器gdb,微软的Windbg和objdump的反汇编引擎均采用线性扫描算法
5.递归下降反汇编
该算法强调控制流的概念,控制流根据一条指令是否被另一条指令引用来决定是否对其进行反汇编,可以根据指令对CPU指令指针的影响对它们分类。
①顺序流指令:它将执行权传递给紧随其后的下一条指令。包括简单算术指令如add,寄存器与内存之间的传输指令如mov,栈操作指令如push,这些指令的反汇编过程将以线性扫描方式进行。
②条件分支指令:它提供两条可能的路径。如果条件为真,则跳转到分支上执行;如果条件为假,则继续线性执行。但是反汇编器并不能在静态条件下确定条件真假,所以会递归下降的遍历上述两条路径,将它们放到反汇编地址列表里,稍后再反汇编。
③无条件分支指令:它并不遵循线性流程,它的执行权会传递个一条指令,但不一定是下一条,所以递归下降反汇编器会尝试确定跳转的目标,将其地址加到反汇编地址列表里。但比如jump eax这条语句就没办法,因为eax的值没法在静态分析中确定。
④函数调用指令:与③相似,但函数调用结束后,将返回紧跟着调用指令的下一条指令,所以递归下降反汇编器将函数起始地址放入反汇编地址列表,而下一条指令则进行线性扫描。但也有可能出现异常,当在函数内修改了函数的返回地址时,就会发生错误。
⑤返回指令:它没有提供下一条指令的信息,如果程序正在运行,则可以从栈中取出指令继续执行,但反汇编器没有处理栈的能力,所以反汇编过程在这里会结束。然后反汇编器从反汇编地址列表里取出一条指令继续开始反汇编过程,这也是递归下降反汇编算法的由来。
优点:具有区分代码和数据的强大能力
缺点:无法处理间接代码路径,如利用指针表来查找目的地址的跳转或调用。