Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gdb showing different address than in code

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

like image 865
Kingamere Avatar asked Sep 24 '15 22:09

Kingamere


People also ask

What is offset in gdb?

- offset + offset. Specifies the line offset lines before or after the current line. For the list command, the current line is the last one printed; for the breakpoint commands, this is the line at which execution stopped in the currently selected stack frame (see Frames, for a description of stack frames.)

Can gdb change the value of the variable?

Use the set variable (gdb) and the assign (dbx) commands to change the value associated with a variable, memory address, or expression that is accessible according to the scope and visibility rules of the language. The expression can be any expression that is valid in the current context.

What does p do in gdb?

The usual way to examine data in your program is with the print command (abbreviated p ), or its synonym inspect . It evaluates and prints the value of an expression of the language your program is written in (see section Using GDB with Different Languages). exp is an expression (in the source language).

What is shellcode in buffer Overflow?

Shellcode is considered exploit code or exploit payload. Buffer overflows are the most popular way of injecting a shellcode1 because after the instructions of the called function are done executing, the executable code that the adversary placed on the stack will begin executing.


2 Answers

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
like image 189
Mark Plotnick Avatar answered Sep 28 '22 17:09

Mark Plotnick


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.

like image 41
ouah Avatar answered Sep 28 '22 17:09

ouah