gdb showing different address than in code

2020-02-26 10:02发布

问题:

I am trying to implement a buffer overflow attack and I need to know the address of my buffer that I am trying to overflow.

The address that is displayed using GDB is different than if I just did this in the code:

Exact code:

#include<stdio.h>

int main() {
   char buffer[20];
   printf("%p\n", buffer); // 0xbffff320

   return 0;
}

However, in gdb if I do:

p &buffer

I get: 0xbffff330

Why is there a difference and will it mess up my buffer overflow attack?

I have ALSR and stack guard disabled.

Thanks.

EDIT 1: Even when I step through gdb and it encounters the print line, I get 0xbffff320 as the address

EDIT 2:

Environment: Ubuntu Linux 9 image running in virtual box on windows 7.

The gdb version: 6.8-debian

Compiled using GCC such as: gcc -g -fno-stack-protector filename.c execute immediately: ./a.out address printed: 0xbffff320

Then open in debugger like this: gdb ./a.out then enter b main then run then p &buffer

Then address is 0xbffff330

Edit 3:

This is the gdb log to reproduce behavior:

$ gdb ./a.out

b main

run

p &buffer /* address here is different than what is shown if I run executable */

step through program to printf statement /* address here is same as p &buffer but different than what is printed when program is ran */

回答1:

The question, as I understand it, is why the address of a local variable in main is different when the program is started from the shell versus when it is started from gdb.

Here's a sample program to show the difference:

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;
}

We'll run it in a clean environment. (I also disabled 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

The output from gdb's print &buffer command is the same as the program's idea of the address, but they're both different from when the program was run in the 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;

There are a couple of things contributing to the difference:

  • gdb is invoking the program with an absolute pathname, so the argv array is bigger.
  • gdb sets (or in this case, adds) two environment variables. This is done in readline/shell.c:sh_set_lines_and_columns(). So the environ array is bigger.

To remove those two variables from the environment, you can use unset environment, or set exec-wrapper to run env -u .... That way, the program's addresses under gdb are the same as when it's run in the shell (if we use an absolute pathname).

$ `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:

Your array object in your system is stored in the stack. At the top of your stack there is, among other, the environment. When you run your program with gdb, gdb will provide a different environment (the env var and their value) which explains the addresses difference.

You can check the difference by running show environment in gdb and by comparing the output with set command in your shell.



回答3:

Found out that this is expected behavior in old versions of GDB (mine is 6.8-debian), and if you construct your buffer overflow attack properly you can work around this behavior and it won't be a problem.



回答4:

For the moment, the only reasons I can imagine are :

  • you tried to print &buffer after your program terminated. Solution: try setting a breakpoint on main, run, next to execute printf, and print &buffer.
  • you first ran your program outside gdb, then ran it inside gdb but forgot to execute the printf line with next.
  • a bug in your version of gdb
  • a bug in your version of gcc (gcc might produce incorrect debug info: see 1 and 2)