Monday, March 10, 2014

Looking at variables and examining memory locations in GNU GDB Debugger

We can look at various values on the stack. Let's first list the program in GDB. We do that by listing the 1st line of the code.

(gdb) list 1
1    #include <stdio.h>
2    #include <stdlib.h>
3   
4    int add(int x, int y)
5    {
6    /* Adder function*/
7        int z =10;
8        z = x + y;
9        return z;
10    }


Lets now set up a break point at line 8 where variable z will store the value of x and y.

 (gdb) break 8
Breakpoint 1 at 0x80484d9: file tst4.c, line 8.

Now we will run the program in GDB with command line arguments.

(gdb) run 10 30
Starting program: /home/user/GDB/tst4 10 30
demo
demo

Breakpoint 1, add (x=10, y=30) at tst4.c:8 (Our program reached the breakpoint)
8        z = x + y;

At this point lets print the values of the variables on the stack.

(gdb) print x
$1 = 10
(gdb) print y
$2 = 30
(gdb) print z
$3 = 10
  
 (gdb) info registers
eax            0xa    10  (You can also see the addition registers EAX (Z) is only holding value 10)
ecx            0xffffffff    -1
edx            0xb7fc18b8    -1208215368
ebx            0xb7fc0000    -1208221696
esp            0xbffff1f8    0xbffff1f8
ebp            0xbffff208    0xbffff208
esi            0x0    0
edi            0x0    0
eip            0x80484d9    0x80484d9 <add+13>
eflags         0x282    [ SF IF ]
cs             0x73    115
ss             0x7b    123
ds             0x7b    123
es             0x7b    123
fs             0x0    0
gs             0x33    51
(gdb) s

Notice Z is still holding the value assigned to it at the start of the function which was 10. We still have not stored the value of x and y into z. We now need to proceed to the next step of the program where the values of x and y will be stored in z. To proceed further we need to "step" into the program by issuing the "step" or the "s" command in GDB.



(gdb) step
9                  return z;
(gdb) print z
$4 = 40

Notice how when we now print the value of variable z it turns to the correct value of 40. And you can see the value of addition register EAX change to 40

(gdb) info registers
eax            0x28    40
ecx            0xffffffff    -1
edx            0xa    10
ebx            0xb7fc0000    -1208221696
esp            0xbffff1f8    0xbffff1f8
ebp            0xbffff208    0xbffff208
esi            0x0    0
edi            0x0    0
eip            0x80484e4    0x80484e4 <add+24>
eflags         0x216    [ PF AF IF ]
cs             0x73    115
ss             0x7b    123
ds             0x7b    123
es             0x7b    123
fs             0x0    0
gs             0x33    51


 We can also examine the individual registers at a particular break point and how to examine the memory. Let's now examine the registers by issuing the "info registers". Now re-running the program in the gdb


(gdb) run 10 23
Starting program: /home/user/GDB/tst4 10 23
demo
demo

Breakpoint 1, add (x=10, y=23) at tst4.c:8
8        z = x + y;
(gdb) info registers
eax            0xa    10
ecx            0xffffffff    -1
edx            0xb7fc18b8    -1208215368
ebx            0xb7fc0000    -1208221696
esp            0xbffff1f8    0xbffff1f8
ebp            0xbffff208    0xbffff208
esi            0x0    0
edi            0x0    0
eip            0x80484d9    0x80484d9 <add+13>
eflags         0x282    [ SF IF ]
cs             0x73    115
ss             0x7b    123
ds             0x7b    123
es             0x7b    123
fs             0x0    0
gs             0x33    51



Lets now examine the register pointing to the top of the stack which is the register ESP. We can examine the ESP register by using the examine  "x" command in GNU GDB debugger.

% x/10dw 0xbffff1f8  (This commands states examine 10 words and show the output in decimals)

(gdb) x/10dw 0xbffff1f8
0xbffff1f8:    -1073745336    -1208221696    0    10
0xbffff208:    -1073745224    134514017     10   23
0xbffff218:    0    -1208221696
(gdb) print x
$5 = 10
(gdb) print y
$6 = 23
(gdb) print z
$7 = 10

 As you can see above that the registers pointing to the top of the stack is pointing to the arguments 10 and 23 outlined in green above and the decimal number string in yellow is the return address. Now lets step thru the program and see some more registers.

(gdb) x/10dw 0xbffff1f8
0xbffff1f8:    -1073745336    -1208221696    0    33
0xbffff208:    -1073745224    134514017    10    23
0xbffff218:    0    -1208221696
(gdb)
As you can now see that Z now holds the value of x + y as shown in yellow above. Now for second lets focus on the return address, which means we are currently in the add function and the program will return back to the main program.

Lets for sake of our example show the above command in hex so the return address can match.

 (gdb) x/10xw 0xbffff1f8
0xbffff1f8:    0xbffff248    0xb7fc0000    0x00000000    0x00000021
0xbffff208:    0xbffff2b8    0x08048561    0x0000000a    0x00000017
0xbffff218:    0x00000000    0xb7fc0000


The return address 0x08048561 points to location when add function returns back to the main function.

(gdb) disassemble main
Dump of assembler code for function main:
   0x080484e9 <+0>:    push   %ebp
   0x080484ea <+1>:    mov    %esp,%ebp
   0x080484ec <+3>:    and    $0xfffffff0,%esp
   0x080484ef <+6>:    sub    $0xa0,%esp
   0x080484f5 <+12>:    mov    0xc(%ebp),%eax
   0x080484f8 <+15>:    mov    %eax,0x1c(%esp)
   0x080484fc <+19>:    mov    %gs:0x14,%eax
   0x08048502 <+25>:    mov    %eax,0x9c(%esp)
   0x08048509 <+32>:    xor    %eax,%eax
   0x0804850b <+34>:    mov    0x1c(%esp),%eax
   0x0804850f <+38>:    add    $0x4,%eax
   0x08048512 <+41>:    mov    (%eax),%eax
   0x08048514 <+43>:    mov    %eax,(%esp)
   0x08048517 <+46>:    call   0x80483d0 <atoi@plt>
   0x0804851c <+51>:    mov    %eax,0x2c(%esp)
   0x08048520 <+55>:    mov    0x1c(%esp),%eax
   0x08048524 <+59>:    add    $0x8,%eax
   0x08048527 <+62>:    mov    (%eax),%eax
   0x08048529 <+64>:    mov    %eax,(%esp)
   0x0804852c <+67>:    call   0x80483d0 <atoi@plt>
   0x08048531 <+72>:    mov    %eax,0x30(%esp)
   0x08048535 <+76>:    lea    0x38(%esp),%eax
   0x08048539 <+80>:    mov    %eax,(%esp)
   0x0804853c <+83>:    call   0x8048380 <gets@plt>
   0x08048541 <+88>:    lea    0x38(%esp),%eax
   0x08048545 <+92>:    mov    %eax,(%esp)
   0x08048548 <+95>:    call   0x8048390 <puts@plt>
   0x0804854d <+100>:    mov    0x30(%esp),%eax
   0x08048551 <+104>:    mov    %eax,0x4(%esp)
   0x08048555 <+108>:    mov    0x2c(%esp),%eax
   0x08048559 <+112>:    mov    %eax,(%esp)
   0x0804855c <+115>:    call   0x80484cc <add>
   0x08048561 <+120>:    mov    %eax,0x34(%esp)
   0x08048565 <+124>:    mov    0x34(%esp),%eax
   0x08048569 <+128>:    mov    %eax,0xc(%esp)
   0x0804856d <+132>:    mov    0x30(%esp),%eax
   0x08048571 <+136>:    mov    %eax,0x8(%esp)
   0x08048575 <+140>:    mov    0x2c(%esp),%eax
   0x08048579 <+144>:    mov    %eax,0x4(%esp)
   0x0804857d <+148>:    movl   $0x8048638,(%esp)
   0x08048584 <+155>:    call   0x8048370 <printf@plt>
   0x08048589 <+160>:    movl   $0x0,(%esp)
   0x08048590 <+167>:    call   0x80483b0 <exit@plt>
End of assembler dump.

No comments:

Post a Comment