Get the environment variable address

c gdb
11,630

Solution 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?

Solution 2

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.

Share:
11,630
David
Author by

David

Updated on July 18, 2022

Comments

  • David
    David almost 2 years

    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.

    • Ed Heal
      Ed Heal almost 9 years
      How do you know that the correct address is with gdb? Surely both are correct
    • Ed Heal
      Ed Heal almost 9 years
      Both are living in different environments.
    • David
      David almost 9 years
      @EdHeal If I search with the address obtained with the C function: (gdb) x/s 0xbffff752 0xbffff752: <Address 0xbffff752 out of bounds>
    • user3629249
      user3629249 almost 9 years
      the posted code does not even begin to compile. amongst other things, '#include <stdlib.h>' is needed for the system function; getenv(). Strongly suggest compiling with all warnings enabled. (for gcc, at a minimum use: '-Wall -Wextra -pedantid')
    • user3629249
      user3629249 almost 9 years
      on my system (ubuntu linux 14.04) the posted code, after adding missing #include, outputs: 0x7fff2280de16 and gdb outputs: 0x7fffffffe46a Amongst other things, these are different processes, each with its' own address space, so the 'effective' address of the same environment variable are different
    • David
      David almost 9 years
      @user3629249 Ok, thanks. I've added stdlib.h, but the address is the same.
    • alk
      alk almost 9 years
      @user3629249: Many C implementations will manage a missing prototype very well, if the function's implementation returns a value with a bitwidth of int.
    • David
      David almost 9 years
      @alk But in the printf I have "%p", no "%i". Is it not correct?
    • alk
      alk almost 9 years
      You probably are on a 32bit platform?
    • David
      David almost 9 years
      @alk Yes, on a 32-bit platform.
    • Mark Plotnick
      Mark Plotnick almost 9 years
      What method did you use to disable ASLR?
    • Roi
      Roi about 2 years
      Note that the length of the name of the program being executed seems to have an effect on the address of the environment variables.
  • user3629249
    user3629249 almost 9 years
    what does 'reentrant' have to do with the question?
  • David
    David almost 9 years
    mm, as you and @user3629249 says, the addresses are different because my program is running under gdb. I understand a debugger debug a process, but the process is independent (it's a "normal" process) and gdb only stop, modify, etc. it. What is exactly what happened? gdb doesn't add environment variables.
  • Miroslav Franc
    Miroslav Franc almost 9 years
    @David The thing that has happened is that when doing gdb ./program gdb is the parent of your process. If you want absolute independence you need to debug in the original environment and attach to the process via gdb -p $PID.
  • David
    David almost 9 years
    Ok, ok. Can I not run the program and create the process for attach after with gdb? As a normal debug with gdb, I want say. I want test that.
  • Miroslav Franc
    Miroslav Franc almost 9 years
    For a program that finishes too quickly the only way I can think of is to put getchar (); to cause it wait for you.
  • David
    David almost 9 years
    I added a getchar at the first line in main(). Ok, $ ./getenv prints 0xbffff752, and if I use "gdb -p myPID", (gdb) x/s 0xbffff750, 0xbffff750: "/bin/bash". getenv.c prints to 0xbffff752 and gdb to 0xbffff750. It's not the correct address anyway.
  • Miroslav Franc
    Miroslav Franc almost 9 years
    @David Which does not make much sense, since the addresses differ by 2 bytes. Sorry, I'm not entirely sure what, but you must be doing something wrong. It works for me.
  • Employed Russian
    Employed Russian almost 9 years
    @alk While the man page does say that, and some really ancient OSes did do that, no OS currently in use ever does. This answer is not the reason for observed behavior.
  • David
    David almost 9 years
    using a source in a book I bought, I obtain the correct addres. I don't see the logic. argv[1] must be "SHELL" and argv[2] is the name of the executable to debug. Source: ptr = getenv(argv[1]); ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;