Hacking - The Art of Exploitation, 2nd Edition

(Romina) #1
Programming 41

The address in EIP at the middle breakpoint is different because the


code for the strcpy() function comes from a loaded library. In fact, the


debugger shows EIP for the middle breakpoint in the strcpy() function,


while EIP at the other two breakpoints is in the main() function. I’d like to


point out that EIP is able to travel from the main code to the strcpy() code


and back again. Each time a function is called, a record is kept on a data


structure simply called the stack. The stack lets EIP return through long


chains of function calls. In GDB, the bt command can be used to backtrace the


stack. In the output below, the stack backtrace is shown at each breakpoint.


(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/reader/booksrc/char_array2
Error in re-setting breakpoint 4:
Function "strcpy" not defined.


Breakpoint 1, main () at char_array2.c:7
7 strcpy(str_a, "Hello, world!\n");
(gdb) bt
#0 main () at char_array2.c:7
(gdb) cont
Continuing.


Breakpoint 4, 0xb7f076f4 in strcpy () from /lib/tls/i686/cmov/libc.so.6
(gdb) bt
#0 0xb7f076f4 in strcpy () from /lib/tls/i686/cmov/libc.so.6
#1 0x080483d7 in main () at char_array2.c:7
(gdb) cont
Continuing.


Breakpoint 3, main () at char_array2.c:8
8 printf(str_a);
(gdb) bt
#0 main () at char_array2.c:8
(gdb)


At the middle breakpoint, the backtrace of the stack shows its record of


the strcpy() call. Also, you may notice that the strcpy() function is at a slightly


different address during the second run. This is due to an exploit protection


method that is turned on by default in the Linux kernel since 2.6.11. We will


talk about this protection in more detail later.


0x262 Signed, Unsigned, Long, and Short


By default, numerical values in C are signed, which means they can be both


negative and positive. In contrast, unsigned values don’t allow negative num-


bers. Since it’s all just memory in the end, all numerical values must be stored


in binary, and unsigned values make the most sense in binary. A 32-bit


unsigned integer can contain values from 0 (all binary 0s) to 4,294,967,295


(all binary 1s). A 32-bit signed integer is still just 32 bits, which means it can

Free download pdf