gdb 显示与代码中不同的地址
gdb showing different address than in code
我正在尝试实施缓冲区溢出攻击,我需要知道我试图溢出的缓冲区地址。
使用 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:
环境:Ubuntu Linux 9 图像 运行 在虚拟框中 windows 7.
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 &buffer 相同,但与程序 运行 时打印的内容不同 */
您系统中的数组对象存储在堆栈中。在堆栈的顶部,除其他外,还有环境。当您 运行 您的程序带有 gdb
时,gdb
将提供不同的环境(env var 及其值)来解释地址差异。
您可以通过 gdb
中的 运行ning show environment
和 shell 中的 set
命令比较输出来检查差异。
目前,我能想到的唯一原因是:
- 您试图
print &buffer
在 您的程序终止后。解决方法:尝试在main
、run
、next
上设置断点执行printf
、print &buffer
.
- 你首先 运行 你的程序在 gdb 之外,然后 运行 它在 gdb 内部但忘记执行
printf
行 next
.
- 您的 gdb 版本存在错误
- 您的 gcc 版本中存在错误(gcc 可能会产生不正确的调试信息:请参阅 1 and 2)
发现这是旧版本 GDB 中的预期行为(我的是 6.8-debian),如果您正确构建缓冲区溢出攻击,您可以解决此行为,这不会成为问题。
据我了解,问题是为什么 main
中的局部变量地址在程序从 shell 启动时与从 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
= (char (*)[20]) 0xbffffe08
(gdb) n
/home/mp/s 0xbffffe08
8 return 0;
造成差异的原因有以下几点:
- gdb 正在调用带有绝对路径名的程序,因此 argv 数组更大。
- gdb 设置(或在本例中添加)两个环境变量。这是在
readline/shell.c:sh_set_lines_and_columns()
中完成的。所以环境数组更大。
要从环境中删除这两个变量,您可以使用 unset environment, or 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
我正在尝试实施缓冲区溢出攻击,我需要知道我试图溢出的缓冲区地址。
使用 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:
环境:Ubuntu Linux 9 图像 运行 在虚拟框中 windows 7.
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 &buffer 相同,但与程序 运行 时打印的内容不同 */
您系统中的数组对象存储在堆栈中。在堆栈的顶部,除其他外,还有环境。当您 运行 您的程序带有 gdb
时,gdb
将提供不同的环境(env var 及其值)来解释地址差异。
您可以通过 gdb
中的 运行ning show environment
和 shell 中的 set
命令比较输出来检查差异。
目前,我能想到的唯一原因是:
- 您试图
print &buffer
在 您的程序终止后。解决方法:尝试在main
、run
、next
上设置断点执行printf
、print &buffer
. - 你首先 运行 你的程序在 gdb 之外,然后 运行 它在 gdb 内部但忘记执行
printf
行next
. - 您的 gdb 版本存在错误
- 您的 gcc 版本中存在错误(gcc 可能会产生不正确的调试信息:请参阅 1 and 2)
发现这是旧版本 GDB 中的预期行为(我的是 6.8-debian),如果您正确构建缓冲区溢出攻击,您可以解决此行为,这不会成为问题。
据我了解,问题是为什么 main
中的局部变量地址在程序从 shell 启动时与从 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
= (char (*)[20]) 0xbffffe08
(gdb) n
/home/mp/s 0xbffffe08
8 return 0;
造成差异的原因有以下几点:
- gdb 正在调用带有绝对路径名的程序,因此 argv 数组更大。
- gdb 设置(或在本例中添加)两个环境变量。这是在
readline/shell.c:sh_set_lines_and_columns()
中完成的。所以环境数组更大。
要从环境中删除这两个变量,您可以使用 unset environment, or 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