我正在尝试实现缓冲区溢出攻击,我需要知道我想要溢出的缓冲区的地址。
使用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;缓冲区相同但不同于程序运行时打印的内容* /答案 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;
有一些因素导致了这种差异:
readline/shell.c:sh_set_lines_and_columns()
中完成的。因此environ数组更大。要从环境中删除这两个变量,您可以使用unset environment或set 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)