assembly 获取缓冲区的结尾地址,而不是其开头地址

wpx232ag  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(149)

下面是一个例子:

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做准备...

p3rjfoxz

p3rjfoxz1#

正如你所看到的,我用gdb设置了一个断点。当我检查寄存器的内容时,我看到:

rax            0x7fffffffdc80
rbp            0x7fffffffdd80

因此,在我看来,缓冲区的地址是0x7fffffffdc80 (=0x7fffffffdd80-0x100)
假设%rax将要被加载到%rdi中,用作strcpy()的第一个参数,这似乎是正确的分析。
但是,当打印堆栈的内容时:x/4x我注意到[...]我的缓冲区的真实的地址是[不同的]我得出这个结论是因为我[在不同的位置发现了我的输入数据]
如果在程序停止在断点处时检查内存,则无法通过内容确定buf的存储,因为buf是在没有初始化程序的情况下声明的,并且断点位于strcpy()调用的 * 之前 *。从C语言的Angular 来看,buf的内容是不确定的。并且如果您使用调试器检查它的内存,那么没有特别的理由期待任何特定的内容。
如果你碰巧在堆栈内存中看到了你所识别的数据,这是无关紧要的,特别是当内存低于%rsp时,你可能会看到执行某个先前的函数时在堆栈上留下的垃圾。
如果你不相信,那么有很多方法可以验证,比如

  • 在声明中初始化buf,并使用它来识别其位置。例如,
char buf[256] = { 0xb, 0xf /*, the rest will be 0 */ };
  • buf的地址存储在指针中,并检查
char *bufp = buf;
  • 打印buf的地址
printf("%p\n", buf);

(从技术上讲,输出与机器地址的关系没有指定,但实际上,您可能会得到地址数值的十六进制转储)。

相关问题