注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

风雨夜归人

专业收集资料,个人爱好!

 
 
 

日志

 
 

逆向_第五课  

2010-03-14 20:56:38|  分类: 逆向 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
   全局变量作用于整个程序,一直都存在这个我们稍微了解任何一门编程语言都知道,他放在全局变量的内存区;而局部变量则是存在于函数的堆栈区,当函数调用结束后便消失.在大多数程序中,常数一般放在全局变量中,如一些注册版标记 测试版标记等.
    在大多数情况下,在汇编代码中识别全局变量比其他结构要容易的多.全局变量通常位于数据块(.data)的一个固定地址上,当程序需要访问全局变量时,一般会用一个固定的硬编码的地址直接对内存寻址.比如说这样:mov eax,dword ptr [4084c0h] ;直接调用全局变量,其中4084c0h是全局变量的地址. 
    全局变量可以被同一个文件中所有的函数修改,某个函数改变了全局变量的值,就能影响到其他函数,相当于各个函数间的传递通道.因此就可以利用全局变量传递参数 传递函数返回值等.全局变量在程序的全部执行过程中都占用内存单元,而不像局部变量需要时才开辟空间.
    来看一个利用全局变量传递参数的实例,具体代码如下:
int z; //全局变量z
int add (int x,int y);
int main(void)
{
int a=5,b=6;
z=7;
add (a,b);
return 0;
}
int add(int x,int y)
{
return (x+y+z);
}
    将其编译成EXE然后反汇编后,代码就是下面这种样子了:
psuh ebp
mov ebp,esp
sub esp,00000008
mov [ebp-04],00000005 ;[ebp-04]是局部变量,放参数1
mov [ebp-08],00000006 ;[ebp-08]是局部变量,放参数2
mov dword ptr [004084C0],07 ;对全局变量[004084C0]初始化
mov eax,dword ptr [ebp-08]
psuh eax
mov ecx,dword ptr [ebp-04]
push ecx
call 00401034
add esp,000008
xor eax,eax
mov esp,ebp
pop ebp
ret


;add (x,y)函数的代码
push ebp
mov ebp,esp
mov eax,dword ptr [ebp+08] ;[ebp+08]为参数1
add eax,dword ptr [ebp+0c] ;[ebp+0c]为参数2
add eax,dword ptr [004084C0] ;调用了全局变量[004084c0]
pop ebp
ret


全局变量4084C0h所在的区段是.data区块,这个区块的属性是可读可写.
    这种对内存直接寻址的硬编码方式,比较容易识别出这是一个全局变量.一般编译器会将全局变量放到可读写的区块里,如果放到只读区块里,那么这是一个常量.另外,与全局变量类似的是静态变量,都可以按直接方式寻址等,所不同的是,静态变量作用范围是有限的,仅在定义这些函数内有效.
    然后是数组
    数组是相同数据类型的元素的集合.它们在内存中按照顺序连续存放在一起.汇编状态下访问数组一般是基址加上某变量来实现的.看实例:
int main(void)
{
static int a[3]={0x11,0x22,0x33};
int i,s=0,b[3];
for (i=0;i<3;i++)
{
s=s+a;
b=s;
}
for (i=0,i<3;i+=)
{
printf("%d\n",b);
}
return 0;
}
编译完毕后,反汇编代码如下:
sub esp,0c ;为局部变量分配内存,用来存放b
xor ecx,ecx ;s=0
xor eax,eax ;i=0
push esi
push edi
@@:
mov edi,dword ptr [eax+407030] ;407030只想数组a[],即数组的基址
add eax,4 ;访问数组的索引
add ecx,edi ;s=s+a
cmp eax,0c
mov dword ptr [esp+eax+4],ecx ;b=s
jl @F
lea esi,dword ptr[esp+8]
mov edi,3 ;计数器
@@:
mov eax,dword pttr [esi] ;esi指向b[]数组
push eax
push 40703c
call 00401050 ;printf ("%d\n",b)
add esp,8
add esi,4 ;指向数组下一元素
dec edi
jnz @F
    数组在内存中可以存在于堆栈 数据段以及动态内存中.我这次说的数组a[]就保存在.data段中,其寻址可以用"基址+偏移量" 来实现.
mov eax,[407030h+eax]
|     |
        基址 偏移量
    这种间接寻址一般出现在给一些数组或结构赋值情况下,其寻址形式一般式[基址+n],其中基址可以是常量也可以是寄存器,为定值.随着n值的不同,就可对结构中相应单元赋值了.
    b[]数组放在堆栈中,这些堆栈是编译时刻进行分配的.数组在声明时可以直接计算偏移地址,针对数组成员寻址是采用实际的偏移量完成的.
  评论这张
 
阅读(450)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017