gdb showing different address than in code

Kingamere picture Kingamere · Sep 25, 2015 · Viewed 7.8k times · Source

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 */

Answer

Mark Plotnick picture Mark Plotnick · Sep 28, 2015

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