变量的作用域指的是变量在源码中可以被访问到的范围。全局变量属于进程作用域,在整个进程中都可以访问到这个全局变量;静态变量属于文件作用域,在当前源码文件中可以访问;局部变量属于函数作用域,在函数内可以访问到;
运行环境:
- 操作系统: Windows 7家庭版
 
- 编译器:VC6 VS2013
 
变量识别
1 2 3 4 5 6 7 8 9 10 11 12 13
   | static int g_nTest = 0x8765093;
  int main(int argc, char* argv[]) { 	int n = 999; 	scanf("%d",&n); 	scanf("%d",&g_nTest); 	scanf("%d",&argc); 	printf("n = %d\n",n + argc); 	printf("g_nTest = %d\n",g_nTest + argc); 	printf("Hello World!\n"); 	return 0; }
   | 
 
全局变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
   | 00401010                          | 55                   | push ebp                                        | 00401011                          | 8BEC                 | mov ebp,esp                                     | 00401013                          | 83EC 44              | sub esp,44                                      | 00401016                          | 53                   | push ebx                                        | 00401017                          | 56                   | push esi                                        | 00401018                          | 57                   | push edi                                        | 00401019                          | 8D7D BC              | lea edi,dword ptr ss:[ebp-44]                   | 0040101C                          | B9 11000000          | mov ecx,11                                      | 00401021                          | B8 CCCCCCCC          | mov eax,CCCCCCCC                                | 00401026                          | F3:AB                | rep stosd                                       | 00401028                          | C745 FC E7030000     | mov dword ptr ss:[ebp-4],3E7                    |局部变量 0040102F                          | 8D45 FC              | lea eax,dword ptr ss:[ebp-4]                    | 00401032                          | 50                   | push eax                                        | 00401033                          | 68 48504200          | push test.425048                                | 425048:"%d" 00401038                          | E8 23010000          | call test.401160                                | printf 0040103D                          | 83C4 08              | add esp,8                                       | 00401040                          | 68 307A4200          | push test.427A30                                |全局变量 00401045                          | 68 48504200          | push test.425048                                | 425048:"%d" 0040104A                          | E8 11010000          | call test.401160                                | 0040104F                          | 83C4 08              | add esp,8                                       | 00401052                          | 8D4D 08              | lea ecx,dword ptr ss:[ebp+8]                    |参数访问 00401055                          | 51                   | push ecx                                        | 00401056                          | 68 48504200          | push test.425048                                | 425048:"%d" 0040105B                          | E8 00010000          | call test.401160                                | 00401060                          | 83C4 08              | add esp,8                                       | 00401063                          | 8B55 FC              | mov edx,dword ptr ss:[ebp-4]                    | edx:EntryPoint 00401066                          | 0355 08              | add edx,dword ptr ss:[ebp+8]                    | edx:EntryPoint 00401069                          | 52                   | push edx                                        | edx:EntryPoint 0040106A                          | 68 3C504200          | push test.42503C                                | 42503C:"n = %d\n" 0040106F                          | E8 6C000000          | call test.4010E0                                | 00401074                          | 83C4 08              | add esp,8                                       | 00401077                          | A1 307A4200          | mov eax,dword ptr ds:[427A30]                   | 0040107C                          | 0345 08              | add eax,dword ptr ss:[ebp+8]                    |
   | 
 
在IDA中识别 为这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   | .text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp) .text:00401000 _main           proc near               ; CODE XREF: start+AF↓p .text:00401000 .text:00401000 var_4           = dword ptr -4 .text:00401000 argc            = dword ptr  4 .text:00401000 argv            = dword ptr  8 .text:00401000 envp            = dword ptr  0Ch .text:00401000 .text:00401000                 push    ecx .text:00401001                 lea     eax, [esp+4+var_4] .text:00401005                 mov     [esp+4+var_4], 3E7h .text:0040100D                 push    eax .text:0040100E                 push    offset aD       ; "%d" .text:00401013                 call    _scanf .text:00401018                 push    offset dword_408030			;全局变量通过地址访问 .text:0040101D                 push    offset aD       ; "%d" .text:00401022                 call    _scanf .text:00401027                 lea     ecx, [esp+14h+argc] .text:0040102B                 push    ecx .text:0040102C                 push    offset aD       ; "%d" .text:00401031                 call    _scanf .text:00401036                 mov     edx, [esp+1Ch+argc] .text:0040103A                 mov     eax, [esp+1Ch+var_4] .text:0040103E                 add     eax, edx .text:00401040                 push    eax .text:00401041                 push    offset aND      ; "n = %d\n" .text:00401046                 call    sub_401080 .text:0040104B                 mov     ecx, dword_408030 .text:00401051                 mov     edx, [esp+24h+argc] .text:00401055                 add     ecx, edx .text:00401057                 push    ecx .text:00401058                 push    offset aGNtestD ; "g_nTest = %d\n" .text:0040105D                 call    sub_401080 .text:00401062                 push    offset aHelloWorld ; "Hello World!\n" .text:00401067                 call    sub_401080 .text:0040106C                 xor     eax, eax .text:0040106E                 add     esp, 30h .text:00401071                 retn .text:00401071 _main           endp .text:00401071
   | 
 
全局代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
   | 
 
  #include <iostream> int GetInt() { 	return 3; } int GetInt1() { 	return 4; } int GetInt2() { 	return 5; } int GetInt3() { 	return 6; } int GetInt4() { 	return 7; } static int g_nTest = GetInt(); static int g_nTest1 = GetInt1() + g_nTest; static int g_nTest2 = GetInt2() / 7; static int g_nTest3 = GetInt3() % -8; static int g_nTest4 = GetInt4(); int main(int argc, char* argv[]) { 	int n = 999; 	scanf("%d", &n); 	scanf("%d", &g_nTest); 	scanf("%d", &argc); 	printf("n = %d\n", n + argc); 	printf("g_nTest = %d\n", g_nTest + argc); 	printf("Hello World!\n"); 	return 0; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  | 
 
这里直接反汇编Release版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
   | start: .text:00401407 ; __unwind { // __SEH_prolog4 .text:00401407                 call    sub_4016AF .text:0040140C                 jmp     loc_401285 .text:0040140C ; } // starts at 401407 .text:0040140C start           endp ; sp-analysis failed
  ;进入loc_401285 .text:00401285 ; __unwind { // __SEH_prolog4 .text:00401285                 push    14h .text:00401287                 push    offset unk_402560 .text:0040128C                 call    __SEH_prolog4 .text:00401291                 push    1 .text:00401293                 call    sub_401487 .text:00401298                 pop     ecx .text:00401299                 test    al, al .text:0040129B                 jz      loc_4013F1 .text:004012A1                 xor     bl, bl .text:004012A3                 mov     [ebp-19h], bl .text:004012A6 ;   __try { // __except at loc_4013C0 .text:004012A6                 and     dword ptr [ebp-4], 0 .text:004012AA                 call    sub_401455 .text:004012AF                 mov     [ebp-24h], al .text:004012B2                 mov     eax, dword_403044 .text:004012B7                 xor     ecx, ecx .text:004012B9                 inc     ecx .text:004012BA                 cmp     eax, ecx .text:004012BC                 jz      loc_4013F1 .text:004012C2                 test    eax, eax .text:004012C4                 jnz     short loc_40130F .text:004012C6                 mov     dword_403044, ecx .text:004012CC                 push    offset unk_4020F8 .text:004012D1                 push    offset unk_4020EC .text:004012D6                 call    _initterm_e .text:004012DB                 pop     ecx .text:004012DC                 pop     ecx .text:004012DD                 test    eax, eax .text:004012DF                 jz      short loc_4012F2 .text:004012DF ;   } // starts at 4012A6 .text:004012E1                 mov     dword ptr [ebp-4], 0FFFFFFFEh .text:004012E8                 mov     eax, 0FFh .text:004012ED                 jmp     loc_4013E1 .text:004012F2 ; --------------------------------------------------------------------------- .text:004012F2 .text:004012F2 loc_4012F2:                             ; CODE XREF: start-128↑j .text:004012F2                 push    offset unk_4020E8 .text:004012F7                 push    offset unk_4020CC .text:004012FC                 call    _initterm .text:00401301                 pop     ecx .text:00401302                 pop     ecx .text:00401303                 mov     dword_403044, 2 .text:0040130D                 jmp     short loc_401314 .text:0040130F ; ---------------------------------------------------------------------------
  ;继续进入_initterm .rdata:004020D0                 dd offset sub_401273    ; set_newMode   库函数 .rdata:004020D4                 dd offset sub_401070	;这几个函数分别代表我们写的函数 .rdata:004020D8                 dd offset sub_401000 .rdata:004020DC                 dd offset sub_401020 .rdata:004020E0                 dd offset sub_401040 .rdata:004020E4                 dd offset sub_401060
   | 
 
静态局部变量
静态变量分为全局静态变量和局部静态变量,全局静态变量和全局变量类似,只是全局静态变量只能在本文件中使用;
局部静态便令比较特殊,它不会随作用域的结束而小时,并且在未进入作用域之前就已存在,其生命周期也和全局变量相同。局部静态变量会预先被当作全局变量处,而它的初始化部分只是在做赋值操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
   |  void ShowStatic(int nNumber) { 	static int g_snNumber = nNumber;		//定义局部静态变量,赋值为参数 	printf("%d\n",g_snNumber);				//打印静态变量 }
  int main(int argc, char* argv[]) { 	for (int i = 0; i < 5; i++) 	{			 		ShowStatic(i); 	} 	return 0; }
  00401020   push        ebp 00401021   mov         ebp,esp				;保存寄存器环境 00401023   sub         esp,40h				 00401026   push        ebx 00401027   push        esi 00401028   push        edi 00401029   lea         edi,[ebp-40h]		; 0040102C   mov         ecx,10h 00401031   mov         eax,0CCCCCCCCh 00401036   rep stos    dword ptr [edi] 9:        static int g_snNumber = nNumber; 00401038   xor         eax,eax				;清空EAX寄存器 0040103A   mov         al,[`ShowStatic'::`2'::$S1 (00427c4c)]	;取00427c4c处1字节送入al中 0040103F   and         eax,1				;将eax与数值1做与运算,eax最终结果只能是0或1 00401042   test        eax,eax				;比较eax,不等于0则跳转,跳转到0040105e处 00401044   jne         ShowStatic+3Eh (0040105e) 00401046   mov         cl,byte ptr [`ShowStatic'::`2'::$S1 (00427c4c)]		;将之前比较是否为0的地址放入cl中 0040104C   or          cl,1					;将cl与数值1做或运算,cl最低为将被置1,其他不变 0040104F   mov         byte ptr [`ShowStatic'::`2'::$S1 (00427c4c)],cl		;将cl值存入00427c4c中 00401055   mov         edx,dword ptr [ebp+8]	;参数存入edx中 00401058   mov         dword ptr [___decimal_point_length+0A9Ch (00427c48)],edx  ;edx赋值到00427c48,将局部静态变量赋值为EDX寄存器中保存的数据 10:       printf("%d\n",g_snNumber); 0040105E   mov         eax,[___decimal_point_length+0A9Ch (00427c48)]		;静态局部变量的访问,与全局变量一样 00401063   push        eax 00401064   push        offset string "%d\n" (0042201c) 00401069   call        printf (00401110) 0040106E   add         esp,8 11:   } 00401071   pop         edi 00401072   pop         esi 00401073   pop         ebx 00401074   add         esp,40h 00401077   cmp         ebp,esp 00401079   call        __chkesp (00401190) 0040107E   mov         esp,ebp 00401080   pop         ebp 00401081   ret
 
 
  | 
 
cl中存储的是局部变量的标志,这个标志占1字节,通过位运算,将标志中的一个数据置为1,以此判断局部静态变量是否被初始化过。

当有两个静态局部变量,它们会公用一个标记位的内存;

堆
堆在C/C++中使用malloc和new实现堆空间申请,返回的数据便是申请的对空间的地址;保存堆空间首地址的变量大小为4字节的指针类型,其访问方式按作用域来划分;
堆识别在于:堆标志(全FD)、签名、地址、内存中的真相
地址特性
判断依据就是使用调试器装载程序,记住栈地址和内存地址首地址,然后运行到代码;

堆反调试
1 2 3 4 5 6 7
   | //反调试代码 __asm {     mov eax, fs:[18]     mov eax, fs:[30]     mov [eax + 0x2], 0 }
   | 
 
- Peb+0x68的地方调试时值非0,运行时值为0,,为堆类型
 
1 2 3 4 5 6
   | __asm {     mov eax, fs:[18]     mov eax, fs:[30]     mov [eax + 0x68], 0 }
   |