全局变量引发的故事

仿真平台:VS2008

一:全局变量引发的故事

#include "stdafx.h"

int gi;
int _tmain(int argc, _TCHAR* argv[])
{
	gi=12;
	return 0;
}
查看其对应的汇编
#include "stdafx.h"

int gi;
int _tmain(int argc, _TCHAR* argv[])
{
00411370 55               push        ebp  
00411371 8B EC            mov         ebp,esp 
00411373 81 EC C0 00 00 00 sub         esp,0C0h 
00411379 53               push        ebx  
0041137A 56               push        esi  
0041137B 57               push        edi  
0041137C 8D BD 40 FF FF FF lea         edi,[ebp+FFFFFF40h] 
00411382 B9 30 00 00 00   mov         ecx,30h 
00411387 B8 CC CC CC CC   mov         eax,0CCCCCCCCh 
0041138C F3 AB            rep stos    dword ptr es:[edi] 
	gi=12;
0041138E C7 05 40 71 41 00 0C 00 00 00 mov         dword ptr ds:[00417140h],0Ch 
	return 0;
00411398 33 C0            xor         eax,eax 
}

使用单步调试的方法设置断点,可知程序先执行 
int gi;
然后再进入主函数执行。
查看
gi=12;
对应的汇编

0041138E C7 05 40 71 41 00 0C 00 00 00 mov         dword ptr ds:[00417140h],0Ch 

一般:MOV DS:[地址值],存储值
看对应的语句可知   mov 对应机器码 c7 05     地址对应为00417140h   存储值为0ch          (小端机存储方式)
注: 小端机:整数逻辑上最低字节放在内存的最低地址,次低字节放在次低地址,即低地址放低字节,高地址放高字节
       大端机与之相反
为了证明地址00417040h的确被赋值了12,我们使用vs的内存查看功能


我们发现,的确12这个数是被赋值到了地址00417140h
既然我们发现指令只不过是一些字节的组合,那么我们自己来分配一段内存,将mov指令的机器码填入,在把EIP的值指向该地址
看下面一段程序:

int i, gi;
void * address;
void main()
{	  		
		_asm {
			mov address, offset _lb1;
			jmp address;
			}
		i = 2;
		_lb1:
		gi = 12;
}
其中,标签_lb1代表着一个地址,供EIP跳转
下一节讲讨论一下Windows下的内联汇编
现在,再看一个程序
  
#include<stdio.h>
#include<stdlib.h>
int gi;
int address;
void *buildCode()
{
	char*code=(char*)malloc(16);//mov+jmp两个指令一共16个字节
	char*pMov=code;//mov指令的地址开头
	char*pJmp=code+10;//jmp指令的地址开头
	char*pAddress;
	pMov[0]=0xc7;
	pMov[1]=0x05;//mov的二进制码为c705
	pAddress=pMov+2;//mov gi的地址,数据 此处为gi的地址指针
	*((int*)pAddress)=(int)&gi;//将gi的地址赋值到指定位置
    *((int*)(pAddress+4))=18;//将数据赋值到指定位置
	pJmp[0]=0xff;
	pJmp[1]=0x25;//jmp的二进制代码为ff25
	*((int*)(&pJmp[2]))=(int)&address;//jmp指令将要跳转的地址
	return code;//返回首地址
}
void main()
{	  		    
        void*code=buildCode();
		_asm{
        mov address,offset _lb1
		}
       gi=12;
	   printf("gi=%d\n",gi);
	   _asm jmp code//执行buildCode()
		gi=13;
 _lb1:
	   printf("g1=%d\n",gi);
	   getchar();
}
此代码的执行结果为:



看懂了吗?呵呵,还是比较简单的
我们再来看看对应的汇编代码
buildCode()函数对应的代码

#include<stdio.h>
#include<stdlib.h>
int gi;
int address;
void *buildCode()
{
004113C0 55               push        ebp  
004113C1 8B EC            mov         ebp,esp 
004113C3 81 EC F0 00 00 00 sub         esp,0F0h 
004113C9 53               push        ebx  
004113CA 56               push        esi  
004113CB 57               push        edi  
004113CC 8D BD 10 FF FF FF lea         edi,[ebp+FFFFFF10h] 
004113D2 B9 3C 00 00 00   mov         ecx,3Ch 
004113D7 B8 CC CC CC CC   mov         eax,0CCCCCCCCh 
004113DC F3 AB            rep stos    dword ptr es:[edi] 
	char*code=(char*)malloc(16);//mov+jmp两个指令一共16个字节
004113DE 8B F4            mov         esi,esp 
004113E0 6A 10            push        10h  
004113E2 FF 15 CC 82 41 00 call        dword ptr ds:[004182CCh] 
004113E8 83 C4 04         add         esp,4 
004113EB 3B F4            cmp         esi,esp 
004113ED E8 53 FD FF FF   call        00411145 
004113F2 89 45 F8         mov         dword ptr [ebp-8],eax 
	char*pMov=code;//mov指令的地址开头
004113F5 8B 45 F8         mov         eax,dword ptr [ebp-8] 
004113F8 89 45 EC         mov         dword ptr [ebp-14h],eax 
	char*pJmp=code+10;//jmp指令的地址开头
004113FB 8B 45 F8         mov         eax,dword ptr [ebp-8] 
004113FE 83 C0 0A         add         eax,0Ah 
00411401 89 45 E0         mov         dword ptr [ebp-20h],eax 
	char*pAddress;
	pMov[0]=0xc7;
00411404 8B 45 EC         mov         eax,dword ptr [ebp-14h] 
00411407 C6 00 C7         mov         byte ptr [eax],0C7h 
	pMov[1]=0x05;//mov的二进制码为c705
0041140A 8B 45 EC         mov         eax,dword ptr [ebp-14h] 
0041140D C6 40 01 05      mov         byte ptr [eax+1],5 
	pAddress=pMov+2;//mov gi的地址,数据 此处为gi的地址指针
00411411 8B 45 EC         mov         eax,dword ptr [ebp-14h] 
00411414 83 C0 02         add         eax,2 
00411417 89 45 D4         mov         dword ptr [ebp-2Ch],eax 
	*((int*)pAddress)=(int)&gi;//将gi的地址赋值到指定位置
0041141A 8B 45 D4         mov         eax,dword ptr [ebp-2Ch] 
0041141D C7 00 6C 71 41 00 mov         dword ptr [eax],41716Ch 
    *((int*)(pAddress+4))=18;//将数据赋值到指定位置
00411423 8B 45 D4         mov         eax,dword ptr [ebp-2Ch] 
00411426 C7 40 04 12 00 00 00 mov         dword ptr [eax+4],12h 
	pJmp[0]=0xff;
0041142D 8B 45 E0         mov         eax,dword ptr [ebp-20h] 
00411430 C6 00 FF         mov         byte ptr [eax],0FFh 
	pJmp[1]=0x25;//jmp的二进制代码为ff25
00411433 8B 45 E0         mov         eax,dword ptr [ebp-20h] 
00411436 C6 40 01 25      mov         byte ptr [eax+1],25h 
	*((int*)(&pJmp[2]))=(int)&address;//jmp指令将要跳转的地址
0041143A 8B 45 E0         mov         eax,dword ptr [ebp-20h] 
0041143D C7 40 02 68 71 41 00 mov         dword ptr [eax+2],417168h 
	return code;//返回首地址
00411444 8B 45 F8         mov         eax,dword ptr [ebp-8] 
}
00411447 5F               pop         edi  
00411448 5E               pop         esi  
00411449 5B               pop         ebx  
0041144A 81 C4 F0 00 00 00 add         esp,0F0h 
00411450 3B EC            cmp         ebp,esp 
00411452 E8 EE FC FF FF   call        00411145 
00411457 8B E5            mov         esp,ebp 
00411459 5D               pop         ebp  
0041145A C3               ret              
主函数对应的代码

void main()
{	  		    
004114C0 55               push        ebp  
004114C1 8B EC            mov         ebp,esp 
004114C3 81 EC CC 00 00 00 sub         esp,0CCh 
004114C9 53               push        ebx  
004114CA 56               push        esi  
004114CB 57               push        edi  
004114CC 8D BD 34 FF FF FF lea         edi,[ebp+FFFFFF34h] 
004114D2 B9 33 00 00 00   mov         ecx,33h 
004114D7 B8 CC CC CC CC   mov         eax,0CCCCCCCCh 
004114DC F3 AB            rep stos    dword ptr es:[edi] 
        void*code=buildCode();
004114DE E8 A9 FB FF FF   call        0041108C 
004114E3 89 45 F8         mov         dword ptr [ebp-8],eax 
		_asm{
        mov address,offset _lb1
004114E6 C7 05 68 71 41 00 24 15 41 00 mov         dword ptr ds:[00417168h],411524h 
		}
       gi=12;
004114F0 C7 05 6C 71 41 00 0C 00 00 00 mov         dword ptr ds:[0041716Ch],0Ch 
	   printf("gi=%d\n",gi);
004114FA 8B F4            mov         esi,esp 
004114FC A1 6C 71 41 00   mov         eax,dword ptr ds:[0041716Ch] 
00411501 50               push        eax  
00411502 68 44 57 41 00   push        415744h 
00411507 FF 15 C0 82 41 00 call        dword ptr ds:[004182C0h] 
0041150D 83 C4 08         add         esp,8 
00411510 3B F4            cmp         esi,esp 
00411512 E8 2E FC FF FF   call        00411145 
	   _asm jmp code//执行buildCode()
00411517 FF 65 F8         jmp         dword ptr [ebp-8] 
		gi=13;
0041151A C7 05 6C 71 41 00 0D 00 00 00 mov         dword ptr ds:[0041716Ch],0Dh 
 _lb1:
	   printf("g1=%d\n",gi);
00411524 8B F4            mov         esi,esp 
00411526 A1 6C 71 41 00   mov         eax,dword ptr ds:[0041716Ch] 
0041152B 50               push        eax  
0041152C 68 3C 57 41 00   push        41573Ch 
00411531 FF 15 C0 82 41 00 call        dword ptr ds:[004182C0h] 
00411537 83 C4 08         add         esp,8 
0041153A 3B F4            cmp         esi,esp 
0041153C E8 04 FC FF FF   call        00411145 
	   getchar();
00411541 8B F4            mov         esi,esp 
00411543 FF 15 C4 82 41 00 call        dword ptr ds:[004182C4h] 
00411549 3B F4            cmp         esi,esp 
0041154B E8 F5 FB FF FF   call        00411145 
}

关于函数的压栈出栈以及对应的汇编代码,会在后面的文章里面提到,到时在回头看这些汇编代码,就很简单了~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值