我正在研究缓冲区溢出(在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
我感兴趣的是:为什么缓冲区从地址0xbffff078开始,如果ESP指向地址0xbffff040(当局部变量的位置 - 缓冲区 - 在堆栈上保留时)。缓冲区应保存在0xbffff040地址。任何人都可以解释为什么不是吗?
答案 0 :(得分:5)
编译器决定同时为局部变量和分配传递给堆栈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()
的两个指针。