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