代码之家  ›  专栏  ›  技术社区  ›  Kingamere

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

  •  8
  • Kingamere  · 技术社区  · 9 年前

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

    使用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&这里的缓冲区/*地址与运行可执行文件时显示的地址不同*/

    单步执行程序以打印f语句/*此处的地址与p&缓冲区,但与程序运行时打印的不同*/

    4 回复  |  直到 9 年前
        1
  •  14
  •   Mark Plotnick    9 年前

    据我所知,问题是为什么 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
    $1 = (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 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
    
        2
  •  1
  •   ouah    9 年前

    系统中的数组对象存储在堆栈中。在堆栈的顶部,有一个环境。当您使用 gdb , gdb公司 将提供一个不同的环境(env-var及其值)来解释地址差异。

    您可以通过运行 show environment 在里面 gdb公司 并通过将输出与 set 命令。

        3
  •  0
  •   Kingamere    9 年前

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

        4
  •  0
  •   Community leo1    7 年前

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

    • 你试着 print &buffer 之后 您的程序已终止。解决方案:尝试在上设置断点 main , run , next 执行 printf 打印&缓冲器 .
    • 您首先在gdb外部运行程序,然后在gdb内部运行程序,但忘记执行 输出函数 与对齐 下一个 .
    • gdb版本中的一个bug
    • gcc版本中的错误(gcc可能会产生错误的调试信息:请参阅 1 2 )