作为逆向领域的关键部分,反编译技术在软件安全和维护方面扮演着非常重要的角色。反编译技术起源于上世纪60年代,只比编译技术晚10年。但反编译技术的成熟度远不如编译技术。反编译领域存在很多亟需解决的难题。数据流分析是其中最为困难的一点。以下是反编译器的典型架构。
本文简单讲讲什么是数据流分析。
在反编译器前端将机器码转换为中间代码后,它以中间代码为输入,分析寄存器和条件码进行下面的各种工作:死寄存器清除、死条件码清除、条件码传播、确定寄存器参数、函数返回寄存器、寄存器传播、函数参数、寄存器变量清除、数据传播、数据类型识别和数据类型传播。
数据流分析是目前为止反编译过程中最难解决的部分。其中,数据类型识别是最难解决的。
实施数据流分析的方法与编译器使用的方法类似,主要有以下两种:
1. 使用-定义链和定义-使用链。
2.静态单赋值形式(SSA: Static single-assignment form)
以如何正确区分一个变量是局部变量还是参数,进行介绍。每个子程序运行期都与一个堆栈关联着,堆栈是参数,局部变量和返回地址的集合。如图4-4所示,在堆栈中,参数表现子程序的一次特定调用的实际参数而在二进制文件中没有存储子程序形式参数的有关信息。栈标志(stack mark)标识调用者的返回地址,而调用者的堆栈指针bp是在堆栈框架里面各个偏移量的参照点。局部变量是子程序取得控制以后由它分配的空间。这个空间只对活动的子程序是可用的。
当堆栈指针bp被设置后,从框架指针的正偏移存储参数和栈标志,而负偏移存储局部变量。在intel体系中,堆栈从高内存向下往低内存增长。
以上方法能识别出大部分局部变量和参数,当也存在一定的局限性。如下图:
将会得出两个参数(第2行和6行)和一个局部变量(第12行)的错误结论。在第6行中,dword ptr[esp+0x24]本质上是一个局部变量,而不是一个参数。另外,第12行中的ecx的值将来之第7行(如红色箭头所示),而不是正确的第9行(绿色箭头所示)。这回导致错误的数据流分析结构。
下一篇,我们将深入分析造成以上问题的原因,以及相应的解决思路。
未完待续......