下面是一个例子:
int hey(char *param_1)
{
char buf[256];
strcpy(buf,param_1);
printf("Hey ! %s\n",buf);
return 0;
}
此函数每次从main调用一次。此函数的程序集为:
0x0000555555555189 <+0>: endbr64
0x000055555555518d <+4>: push rbp
0x000055555555518e <+5>: mov rbp,rsp
0x0000555555555191 <+8>: sub rsp,0x110
0x0000555555555198 <+15>: mov QWORD PTR [rbp-0x108],rdi
0x000055555555519f <+22>: mov rdx,QWORD PTR [rbp-0x108]
0x00005555555551a6 <+29>: lea rax,[rbp-0x100]
=> 0x00005555555551ad <+36>: mov rsi,rdx
0x00005555555551b0 <+39>: mov rdi,rax
0x00005555555551b3 <+42>: call 0x555555555070 <strcpy@plt>
0x00005555555551b8 <+47>: lea rax,[rbp-0x100]
0x00005555555551bf <+54>: mov rsi,rax
0x00005555555551c2 <+57>: lea rdi,[rip+0xe3b] # 0x555555556004
0x00005555555551c9 <+64>: mov eax,0x0
0x00005555555551ce <+69>: call 0x555555555090 <printf@plt>
0x00005555555551d3 <+74>: mov eax,0x0
0x00005555555551d8 <+79>: leave
0x00005555555551d9 <+80>: ret
正如你所看到的,我用gdb设置了一个断点。当我检查寄存器的内容时,我看到:
rax 0x7fffffffdc80
rbp 0x7fffffffdd80
因此,在我看来,缓冲区的地址是0x7fffffffdc80 (=0x7fffffffdd80-0x100)
。
但是,当打印堆栈的内容时:x/4x我注意到0x7fffffffdc80
实际上不是我的缓冲区的地址,而是它的结束地址。我的缓冲区的真实的地址是0x7fffffffdc80 - 0x100 = 0x7fffffffdb80
。我得出这个结论是因为我用NOP,一个外壳代码和许多“A”填充了我的缓冲区。
(gdb) x/40x 0x7fffffffdb80
0x7fffffffdb80: 0x90909090 0x90909090 0x90909090 0x90909090
0x7fffffffdb90: 0xbb48c031 0x91969dd1 0xff978cd0 0x53dbf748
0x7fffffffdba0: 0x52995f54 0xb05e5457 0x41050f3b 0x41414141
0x7fffffffdbb0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdbc0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdbd0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdbe0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdbf0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdc00: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffdc10: 0x41414141 0x41414141 0x41414141 0x41414141
我不明白为什么?通常使用lea rax,[rbp-0x100]
时,我会将缓冲区开始的地址传递给rax,以便为strcpy
做准备...
1条答案
按热度按时间p3rjfoxz1#
正如你所看到的,我用gdb设置了一个断点。当我检查寄存器的内容时,我看到:
因此,在我看来,缓冲区的地址是
0x7fffffffdc80 (=0x7fffffffdd80-0x100)
。假设
%rax
将要被加载到%rdi
中,用作strcpy()
的第一个参数,这似乎是正确的分析。但是,当打印堆栈的内容时:x/4x我注意到[...]我的缓冲区的真实的地址是[不同的]我得出这个结论是因为我[在不同的位置发现了我的输入数据]
如果在程序停止在断点处时检查内存,则无法通过内容确定
buf
的存储,因为buf
是在没有初始化程序的情况下声明的,并且断点位于strcpy()
调用的 * 之前 *。从C语言的Angular 来看,buf
的内容是不确定的。并且如果您使用调试器检查它的内存,那么没有特别的理由期待任何特定的内容。如果你碰巧在堆栈内存中看到了你所识别的数据,这是无关紧要的,特别是当内存低于
%rsp
时,你可能会看到执行某个先前的函数时在堆栈上留下的垃圾。如果你不相信,那么有很多方法可以验证,比如
buf
,并使用它来识别其位置。例如,buf
的地址存储在指针中,并检查buf
的地址(从技术上讲,输出与机器地址的关系没有指定,但实际上,您可能会得到地址数值的十六进制转储)。