David
David

Reputation: 91

Get the environment variable address

I have ASLR disabled. Well, I want obtain the address of the environment variable "SHELL", so I use the C function getenv().

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    char* ptr = getenv("SHELL");
    printf("%p\n", ptr);
}

The address obtained with getenv()

$ ./getenv
0xbffff752

The address obtained with gdb:

gdb> x/4000s $esp
...
(gdb) x/s 0xbffff710
0xbffff710:     "SHELL=/bin/bash"
(gdb) x/s 0xbffff716
0xbffff716:     "/bin/bash"

Why are the addresses different? As noted, I must say the correct address in the obtained with GDB.

Upvotes: 9

Views: 14279

Answers (4)

Shawn Cicoria
Shawn Cicoria

Reputation: 592

Both addresses are correct for their memory at that time in their process. It's usually the environment size as GDB adds couple items.

But what you can try is to "unset environment LINES" and I think "unset environment COLUMNS" -- and then your env should be the same as the shell that started it.

It's usually off by those two variables when either is launched, not at the same time, from the same shell with ASLR "OFF".

Also, compile with to turn off some protections as well if you're attempting buffer overflow exploits.

gcc -g -z execstack -fno-stack-protector -o main main.c

Upvotes: 0

Andrew Henle
Andrew Henle

Reputation: 1

Why the addresses are different?

Because one is run under gdb and one isn't. Running under a different environment results in a different environment. Literally.

What's the output of the printf() statement when running under gdb?

As note, I must say the correct address in the obtained with gdb.

What information is that statement based on?

Upvotes: 7

Miroslav Franc
Miroslav Franc

Reputation: 1352

The trouble is that your list of environment variables can differ when running under gdb and without it. And that is enough to cause the shift in address.

Somewhat shortened listing... (your program)

$ gdb ./a.out
(gdb) r
Starting program: /home/mfranc/a.out 
0x7fffffffdd37
(gdb) r
Starting program: /home/mfranc/a.out 
0x7fffffffdd37
(gdb) set environment a="hello world"
(gdb) r
Starting program: /home/mfranc/a.out 
0x7fffffffdd27
(gdb) r
Starting program: /home/mfranc/a.out 
0x7fffffffdd27
(gdb) unset environment a
(gdb) r
Starting program: /home/mfranc/a.out 
0x7fffffffdd37
(gdb) 

Generally you should debug in the original environment and attach to the process via gdb -p $PID. If you spawn process in a slightly different way and the environment will differ slightly you might see different addresses.

Upvotes: 2

alk
alk

Reputation: 70971

[For Linux]

From man 3 getenv() (italics by me):

The implementation of getenv() is not required to be reentrant. The string pointed to by the return value of getenv() may be statically allocated, and can be modified by a subsequent call to getenv().

This implies that the value queried may be copied and a reference to the copy is returned, so the address returned might differ from the address where the original env-var-tuple is stored.

Upvotes: 0

Related Questions