gdb显示的地址与代码中的地址不同

我试图实现缓冲区溢出攻击,我需要知道我试图溢出的缓冲区的地址。

使用GDB显示的地址与我在代码中执行此操作时的地址不同:

确切代码:

#include int main() { char buffer[20]; printf("%p\n", buffer); // 0xbffff320 return 0; } 

但是,如果我这样做在gdb中:

 p &buffer 

我得到: 0xbffff330

为什么会有差异,它会搞砸我的缓冲区溢出攻击?

我禁用了ALSR和堆栈防护。

谢谢。

编辑1:即使我单步执行gdb并遇到打印行,我也会得到0xbffff320作为地址

编辑2:

环境:在Windows 7上的虚拟框中运行Ubuntu Linux 9映像。

gdb版本:6.8-debian

使用GCC编译,如: gcc -g -fno-stack-protector filename.c立即执行: ./a.out地址打印:0xbffff320

然后在调试器中打开如下: gdb ./a.out然后输入b main然后run p &buffer

然后地址是0xbffff330

编辑3:

这是重现行为的gdb日志:

$ gdb ./a.out

b主要

这里的p&buffer / *地址与我运行的可执行文件时显示的不同* /

步骤通过程序到printf语句/ *地址这里和p和缓冲区相同但不同于程序运行时打印的内容* /

根据我的理解,问题是,当从shell启动程序时,与从gdb启动时, main局部变量的地址不同的原因。

这是一个显示差异的示例程序:

 mp@ubuntu:~$ cat sc #include int main(int argc, char **argv) { char buffer[20]; system("env"); printf("%s %p\n", argv[0], buffer); return 0; } 

我们将在干净的环境中运行它。 (我也禁用了ASLR)。

 mp@ubuntu:~$ env -i sh $ ./s PWD=/home/mp ./s 0xbffffe48 

 $ gdb ./s (gdb) run Starting program: /home/mp/s COLUMNS=80 PWD=/home/mp LINES=42 /home/mp/s 0xbffffe08 

gdb的print &buffer命令的print &buffer程序对地址的想法相同,但它们都与程序在shell中运行时不同。

 (gdb) b 6 Breakpoint 1 at 0x804849c: file sc, line 6. (gdb) run Starting program: /home/mp/s COLUMNS=80 PWD=/home/mp LINES=42 Breakpoint 1, main (argc=1, argv=0xbffffed4) at sc:6 6 printf("%s %p\n", argv[0], buffer); (gdb) p &buffer $1 = (char (*)[20]) 0xbffffe08 (gdb) n /home/mp/s 0xbffffe08 8 return 0; 

有一些因素导致了这种差异:

  • gdb使用绝对路径名调用程序,因此argv数组更大。
  • gdb设置(或在这种情况下,添加)两个环境变量。 这是在readline/shell.c:sh_set_lines_and_columns() 。 因此environ数组更大。

要从环境中删除这两个变量,可以使用unset environment ,或设置exec-wrapper来运行env -u ... 这样,gdb下的程序地址与在shell中运行时的地址相同(如果我们使用绝对路径名)。

 $ `pwd`/s PWD=/home/mp /home/mp/s 0xbffffe28 $ gdb `pwd`/s (gdb) set exec-wrapper env -u LINES -u COLUMNS (gdb) run Starting program: /home/mp/s PWD=/home/mp /home/mp/s 0xbffffe28 

系统中的数组对象存储在堆栈中。 在堆栈的顶部,除了其他之外,还有环境。 当您使用gdb运行程序时, gdb将提供不同的环境(env var及其值),这解释了地址差异。

您可以通过在gdb运行show environment并在shell中将输出与set命令进行比较来检查差异。

发现这是旧版GDB中的预期行为(我的版本是6.8-debian),如果你正确地构造了缓冲区溢出攻击,你可以解决这个问题并且它不会成为问题。

目前,我能想象的唯一原因是:

  • 程序终止你试图print &buffer 。 解决方案:尝试在mainrunnext执行printfprint &buffer上设置断点。
  • 你首先在gdb之外运行程序,然后在gdb中运行它,但忘了用next执行printf行。
  • 您的gdb版本中的错误
  • 您的gcc版本中的错误(gcc可能会产生不正确的调试信息:请参阅1和2 )