您的位置:首页 > 其它

[教程]逆向反汇编第四课

2010-10-10 16:00 218 查看
在各个语言中有数据结构这个东东,它是计算机存储 组织数据的方式.逆向分析时,确定了数据结构后,算法就容易得到了.有时候事情当然也会反着来,根据特定的算法来判断数据结构.
先看局部变量的
局部变量十亿个函数内部定义的变量,只有在函数内才能使用,如计数器,临时变量等.使用局部变量带来的好处,使程序模块化封装变的可能.从汇编语言角度看,局部变量就是在堆栈中进行分配,函数执行完毕后释放这些堆栈,或者直接把局部变量放在寄存器中,我在视频中也告诉各位把寄存器可以理解为变量.
第一种方法是用堆栈存放局部变量
局部变量在程序中用"sub esp,8"语句为局部变量分配空间,用[ebp-xxxx]寻址调用这些变量,而参数调用相对于ebp偏移量是正的,即[ebp+xxxx],因此在逆向时比较容易区分开.编译器在优化模式时,则通过esp寄存器直接对局部变量与参数寻址了.当函数退出时,用'add esp,8'平衡堆栈,以释放局部变量所占据的内存.有些编译器,如Delphi通过给esp加一个负值来进行内存分配.另外,编译器可能会用"push reg"指令来取代"sub esp,4"指令,以节省几个字节.局部变量分配堆栈一般有三种形式:
1.
sub esp,n
.....
add esp,n
2.
add esp,-n
....
sub esp,-n
3.
push reg
.....
pop reg
看看第三种形式的实例"push reg"指令来取代"sub esp,4"指令的.
先看C的代码:

int add(int x,int y)
int main(void)
{
int a=5,b=6; //声明局部变量
add (a,b);
return 0;
}
int add(int x,int y)
{
int z; //声明局部变量
z=x+y;
return (z);
}


将他编译后反汇编.

00401000  /$  55            push    ebp
00401001  |.  8BEC          mov     ebp, esp
00401003  |.  83EC 08       sub     esp, 8                           ;  为局部变量分配内存
00401006  |.  C745 FC 05000>mov     dword ptr ss:[ebp-4], 5          ;  参数1放到局部变量[ebp-4]中
0040100D  |.  C745 F8 06000>mov     dword ptr ss:[ebp-8], 6          ;  参数2放到局部变量[ebp-8]中
00401014  |.  8B45 F8       mov     eax, dword ptr ss:[ebp-8]
00401017  |.  50            push    eax
00401018  |.  8B4D FC       mov     ecx, dword ptr ss:[ebp-4]
0040101B  |.  51            push    ecx
0040101C  |.  E8 09000000   call    local.0040102A
00401021  |.  83C4 08       add     esp, 8
00401024  |.  33C0          xor     eax, eax
00401026  |.  8BE5          mov     esp, ebp
00401028  |.  5D            pop     ebp
00401029  /.  C3            retn


;函数add (int x,int y)反汇编代码如下:

0040102A  /$  55            push    ebp
0040102B  |.  8BEC          mov     ebp, esp
0040102D  |.  51            push    ecx                              ;  为局部变量分配内存
0040102E  |.  8B45 08       mov     eax, dword ptr ss:[ebp+8]        ;  取参数1
00401031  |.  0345 0C       add     eax, dword ptr ss:[ebp+C]        ;  参数1+参数2
00401034  |.  8945 FC       mov     dword ptr ss:[ebp-4], eax        ;  将相加的结果放到局部变量[ebp-04]中
00401037  |.  8B45 FC       mov     eax, dword ptr ss:[ebp-4]        ;  将返回结果放到eax中
0040103A  |.  8BE5          mov     esp, ebp
0040103C  |.  5D            pop     ebp
0040103D  /.  C3            retn


在函数add()里不存在"sub esp,n"这样的指令,程序是通过一句"push ecx"指令来开辟一块堆栈空间的,然后用[ebp-04]来访问这块空间
局部变量的起始值是随即的,是其他函数执行完后留在堆栈中的垃圾数据,因此需要对其初始化.初始化局部变量有两种方法:一种是通过mov 指令为变量赋值,如"mov [ebp-04],5";另一种是使用Push 指令直接将值压入堆栈,如push 15.
第二种是利用寄存器
除了堆栈占用了2个寄存器外,编译器会利用剩下的6个通用寄存器尽可能有效地存放局部变量,这样可以产生最小的代码,提高效率.如果寄存器不够用,编译器将会将变量放到堆栈中.逆向分析时要注意局部变量的生存周期比较短,必须及时确定当前寄存器的变量是那个变量.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: