security consultant, hacker, surfer
Let’s rock and roll. Below we have a C-program designed to accept and print command line arguments:
Convert2.c accepts a string intended to be printed and a string that is converted to an integer using the atoi() function. However, this program intentionally contains a mistake. Notice the block of code written to check the number of command line arguments is commented out. This will result in a segmentation fault when the program attempts to access memory it does not have access to:
We can explore this further with gdb:
Notice the “where” command seems to display a execution stack
Take a close look at this line:
GDB is telling us that argv (which is a pointer to a list of strings) is pointing to some address 0xbffff894. This is the beginning of the address of the first string in the list of strings. Let’s examine that memory:
Each of the three hexadecimal words represents a command line argument (actually a pointer to a command line argument). The first argument is always the name of the executable file (in this case just “a.out”) and the second argument in this case is “test”.
Since we have not supplied a third command line argument, we do not have access to the memory at address 0x00000000. When we try to access it in our source code with the line “count = atoi(argv);” we get a segmentation fault.
This example highlights (indirectly) one other gdb tool that we haven’t discussed yet — “bt.” If you look two screenshots up where the “where” command was executed in gdb you’ll see a stack. You can use the bt utility to displays the state of the execution stack at any point. Let’s use an example program to illustrate this:
Main() calls func1() which calls func2(). Our execution stack would look like:
Notice this is what the stack looks like after we run “bt.”:
The topmost frame is the one we are currently on. We can verify this by printing the value of n (in func2() this value should be 30):
p is short for “print”
We can also move from one frame to another — even if the current frame hasn’t finished executing:
We can also get information about each frame by running “info frame”:
Here we see that frame #2 which lives at 0x7fffffffe5a0 calls frame #1 which lives at 0x7fffffffe580.
This is how we can use the bt utility to examine the execution stack in gdb and hopefully use it as a tool to track down segmentation faults.