gdb显示与代码不同的地址

时间:2015-09-24 22:01:53

标签: c pointers gcc gdb buffer-overflow

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

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

确切代码:

#include<stdio.h>

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 main

运行

这里的p&amp; buffer / *地址与我运行可执行文件* /

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

4 个答案:

答案 0 :(得分:8)

正如我所理解的那样,问题是,当从shell启动程序时,main中的局部变量的地址与从gdb启动时的地址不同。

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

mp@ubuntu:~$ cat s.c
#include<stdio.h>

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命令的输出与程序的地址概念相同,但它们与在shell中运行程序的时间不同。

(gdb) b 6
Breakpoint 1 at 0x804849c: file s.c, line 6.
(gdb) run
Starting program: /home/mp/s 
COLUMNS=80
PWD=/home/mp
LINES=42

Breakpoint 1, main (argc=1, argv=0xbffffed4) at s.c: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 environmentset 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

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

目前,我能想象的唯一理由是:

  • 在程序终止后,您尝试print &buffer 。解决方案:尝试在mainrunnext设置断点以执行printfprint &buffer
  • 您首先在gdb外部运行程序,然后在gdb中运行它但忘记使用printf执行next行。
  • 您的gdb版本中的错误
  • 您的gcc版本中的错误(gcc可能会产生错误的调试信息:请参阅12