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

全局变量作用于整个程序,一直都存在这个我们稍微了解任何一门编程语言都知道,他放在全局变量的内存区;而局部变量则是存在于函数的堆栈区,当函数调用结束后便消失.在大多数程序中,常数一般放在全局变量中,如一些注册版标记 测试版标记等.
    在大多数情况下,在汇编代码中识别全局变量比其他结构要容易的多.全局变量通常位于数据块(.data)的一个固定地址上,当程序需要访问全局变量时,一般会用一个固定的硬编码的地址直接对内存寻址.比如说这样:mov eax,dword ptr [4084c0h] ;直接调用全局变量,其中4084c0h是全局变量的地址.
    全局变量可以被同一个文件中所有的函数修改,某个函数改变了全局变量的值,就能影响到其他函数,相当于各个函数间的传递通道.因此就可以利用全局变量传递参数 传递函数返回值等.全局变量在程序的全部执行过程中都占用内存单元,而不像局部变量需要时才开辟空间.
    来看一个利用全局变量传递参数的实例,具体代码如下:

 

  1. int z; //全局变量z   
  2. int add (int x,int y);   
  3. int main(void)   
  4. {   
  5.     int a=5,b=6;   
  6.     z=7;   
  7.     add (a,b);   
  8.     return 0;   
  9. }   
  10. int add(int x,int y)   
  11. {   
  12.     return (x+y+z);   
  13. }  

 

将其编译成EXE然后反汇编后,代码就是下面这种样子了:

 

  1. psuh ebp   
  2. mov ebp,esp   
  3. sub esp,00000008   
  4. mov [ebp-04],00000005 ;[ebp-04]是局部变量,放参数1   
  5. mov [ebp-08],00000006 ;[ebp-08]是局部变量,放参数2   
  6. mov dword ptr [004084C0],07 ;对全局变量[004084C0]初始化   
  7. mov eax,dword ptr [ebp-08]   
  8. psuh eax   
  9. mov ecx,dword ptr [ebp-04]   
  10. push ecx   
  11. call 00401034   
  12. add esp,000008   
  13. xor eax,eax   
  14. mov esp,ebp   
  15. pop ebp   
  16. ret  

 

;add (x,y)函数的代码

 

  1. push ebp   
  2. mov ebp,esp   
  3. mov eax,dword ptr [ebp+08] ;[ebp+08]为参数1   
  4. add eax,dword ptr [ebp+0c] ;[ebp+0c]为参数2   
  5. add eax,dword ptr [004084C0] ;调用了全局变量[004084c0]   
  6. pop ebp   
  7. ret  

 

全局变量4084C0h所在的区段是.data区块,这个区块的属性是可读可写.
    这种对内存直接寻址的硬编码方式,比较容易识别出这是一个全局变量.一般编译器会将全局变量放到可读写的区块里,如果放到只读区块里,那么这是一个常量.另外,与全局变量类似的是静态变量,都可以按直接方式寻址等,所不同的是,静态变量作用范围是有限的,仅在定义这些函数内有效.
    然后是数组
    数组是相同数据类型的元素的集合.它们在内存中按照顺序连续存放在一起.汇编状态下访问数组一般是基址加上某变量来实现的.看实例:

 

  1. int main(void)   
  2. {   
  3.     static int a[3]={0x11,0x22,0x33};   
  4.     int i,s=0,b[3];   
  5.     for (i=0;i<3;i++)   
  6.    {   
  7.        s=s+a;   
  8.        b=s;   
  9.     }   
  10.     for (i=0,i<3;i+=)   
  11.    {   
  12.        printf("%d/n",b);   
  13.    }   
  14.    return 0;   
  15. }  

 

编译完毕后,反汇编代码如下:

 

  1. sub esp,0c ;为局部变量分配内存,用来存放b   
  2. xor ecx,ecx ;s=0   
  3. xor eax,eax ;i=0   
  4. push esi   
  5. push edi   
  6. @@:    
  7. mov edi,dword ptr [eax+407030] ;407030只想数组a[],即数组的基址   
  8. add eax,4 ;访问数组的索引   
  9. add ecx,edi ;s=s+a   
  10. cmp eax,0c   
  11. mov dword ptr [esp+eax+4],ecx ;b=s   
  12. jl @F   
  13. lea esi,dword ptr[esp+8]   
  14. mov edi,3 ;计数器   
  15. @@:    
  16. mov eax,dword pttr [esi] ;esi指向b[]数组   
  17. push eax   
  18. push 40703c   
  19. call 00401050 ;printf ("%d/n",b)   
  20. add esp,8   
  21. add esi,4 ;指向数组下一元素   
  22. dec edi   
  23. jnz @F  

 

数组在内存中可以存在于堆栈 数据段以及动态内存中.我这次说的数组a[]就保存在.data段中,其寻址可以用"基址+偏移量" 来实现.

mov eax,[407030h+eax]
                          |     |
                       基址 偏移量
这种间接寻址一般出现在给一些数组或结构赋值情况下,其寻址形式一般式[基址+n],其中基址可以是常量也可以是寄存器,为定值.随着n值的不同,就可对结构中相应单元赋值了.   
b[]数组放在堆栈中,这些堆栈是编译时刻进行分配的.数组在声明时可以直接计算偏移地址,针对数组成员寻址是采用实际的偏移量完成的.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值