Problem with addresses when testing exploits under gdb

Recently I've begun to try my hands in exploit writing. I've started with simple buffer overflow in executable without any kinds of protection like ASLR, DEP or stack cookies.

To check my exploit I used gdb and faced with such problem: my exploit worked well under gdb and didn't work without it. Without debugger exploit was failing with segfault so something was wrong with address of payload. I've started googling and found that Unix-like systems put argv and environment variables on stack before allocating local variables.

Solution

So, to achieve same stack addresses with and without gdb you need all environment variables and program arguments where the same.

Under gdb

  1. Run gdb with empty environment:
env - gdb ./exec
  1. After gdb started unset two environment variables it defines:
unset env LINES
unset env COLUMNS

Without gdb

  1. Run executable with empty environment.

  2. Run executable by providing absolute path to it. Because even if you start gdb from the directory where your executable is located it still uses absolute path to the executable as argv[0].

  3. Set PWD variable because even with empty environment gdb defines it.

So result command will be like this:

env - PWD=$PWD /absolute/path/to/exec

Test

I've written small test example to show you that solution works.

// test.c
// gcc -g exec.c -o exec

#include <stdio.h>

int main(int argc, char *argv[], char *envp[]) {
	int *rsp;

	printf("env: %p\narg: %p\nrsp: %p\n", envp, argv, &rsp);
	while (*envp != NULL) {
		printf("%s\n", *envp);
		++envp;
	}

	return 0;
}

Of course, before testing you need to disable ASLR by running:

sysctl kernel/randomize_va_space=0

Now let's check output of our exec program with and without gdb:

# Without gdb
root@kali:~/Hack/buffer-overflow: env - PWD=$PWD /root/Hack/buffer-overflow/exec
env: 0x7fffffffee38
arg: 0x7fffffffee28
rsp: 0x7fffffffed38
PWD=/root/Hack/buffer-overflow

# Under gdb
root@kali:~/Hack/buffer-overflow: env - gdb ./exec
Starting program: /root/Hack/buffer-overflow/exec
env: 0x7fffffffee38
arg: 0x7fffffffee28
rsp: 0x7fffffffed38
PWD=/root/Hack/buffer-overflow

You can see that all addresses are the same so your exploit will work in the same way.