我正在研究缓冲区溢出(在IA32架构上),并且想通过此示例程序来阐明一件事:
int main(int argc, char **argv) {
char array[512];
if(argc > 1)
strcpy(array, argv[1]);
}
在执行汇编代码期间,我遵循了ebp,esp寄存器更改:
函数main的汇编代码转储:
0x080483c4 <+0>: push ebp
0x080483c5 <+1>: mov ebp,esp
0x080483c7 <+3>: sub esp,0x208
0x080483cd <+9>: cmp DWORD PTR [ebp+0x8],0x1
0x080483d1 <+13>: jle 0x80483ed <main+41>
0x080483d3 <+15>: mov eax,DWORD PTR [ebp+0xc]
0x080483d6 <+18>: add eax,0x4
0x080483d9 <+21>: mov eax,DWORD PTR [eax]
0x080483db <+23>: mov DWORD PTR [esp+0x4],eax
0x080483df <+27>: lea eax,[ebp-0x200]
0x080483e5 <+33>: mov DWORD PTR [esp],eax
0x080483e8 <+36>: call 0x80482f4 <strcpy@plt>
0x080483ed <+41>: leave
0x080483ee <+42>: ret
esp,ebp寄存器值为:
program start
esp: 0xbffff24c
ebp: 0xbffff2c8
push ebp
esp: 0xbffff248
ebp: 0xbffff2c8
mov ebp,esp
esp: 0xbffff248
ebp: 0xbffff248
sub esp,0x208
esp: 0xbffff040
ebp: 0xbffff248
strcpy call (ebp is overwritten)
esp: 0xbffff250
ebp: 0x41414141
当我输入520个字符“ a”时,导致EBP,EIP溢出.内存看起来像这样:
Lower Memory Addresses
0xbffff070: 0xbffff078 0xbffff492 0xaaaaaaaa 0xaaaaaaaa
0xbffff080: 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa
0xbffff090: 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa
0xbffff0a0: 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa
0xbffff0b0: 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa
...
0xbffff270: 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa 0xaaaaaaaa
Higher Memory Addresses
我感兴趣的是:如果ESP指向地址0xbffff040,则为什么缓冲区从地址0xbffff078开始(当堆栈中保留了局部变量的位置-缓冲区时).该缓冲区应已保存在0xbffff040地址.有人可以解释为什么不是吗?
解决方法:
编译器决定同时为局部变量和传递给堆栈上strcpy()的参数分配空间.
sub esp,0x208 # 0x200 for array, 8 for 2 pointers
...
mov DWORD PTR [esp+0x4],eax # argv[1], not push
mov DWORD PTR [esp],eax # array
因此,该数组实际上位于esp 8(或编译器指的是ebp-0x200).
编辑:
esp在程序调用之间是不同的,尤其是取决于参数的数量. 0xbffff040或0xbffff070.
缓冲区位于0xbffff048,而不是0xbffff040.或为0xbffff078,而不是0xbffff070.询问调试器要检查的位置.
在内存转储中,缓冲区的值为0xaa(我猜这是调用之前未初始化的内存).在此之前,您可以看到传递给strcpy()的两个指针.