简体   繁体   中英

Trying to understand example char_array2.c from “the art of exploitation”

OK so I am really trying to understand what's going on this example of "The art of exploitation" second edition. I am trying to see exactly what is going on with the example by closely following the output of GDB on the book. My greatest problem with this is the last part, I included the whole thing so that everyone can see what's going on. Granted I only have very(very) basic knowledge of assembly code. I do understand basic C. In the last part the author says that there is a minor difference in the second run of the program from the last one in the address that strcpy() points to and I just can't see it.

The program is simply

#include<stdio.h>
#include<string.h>

int main() {

  char str_a[20];
  strcpy(str_a, "Hello, world!\n");
  printf(str_a);
  }

After I compile it with the necessary options to be able to debug it I load it on GDB and include the following:

(gdb) break 6
Breakpoint 1 at 0x80483c4: file char_array2.c, line 6.
(gdb) break strcpy

Function "strcpy" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (strcpy) pending.
(gdb) break 8
Breakpoint 3 at 0x80483d7: file char_array2.c, line 8.
(gdb)

I have no problem with this, it is to my understanding that the debugger can only do this sort of things with user defined functions. I also know how to go around this problem with gcc options. I also know that when the program runs the strcpy breakpoint is resolved. Let me continue.

(gdb) run
Starting program: /home/reader/booksrc/char_array2
Breakpoint 4 at 0xb7f076f4
Pending breakpoint "strcpy" resolved

Breakpoint 1, main() at char_array2.c:7
7   strcpy(str_a, "Hello, world!\n");
(gdb) i r eip
eip 0x80483c4   0x80483c4 <main+16>
(gdb) x/5i $eip
0x80483c4   <main+16>:  mov    DWORD PTR [esp+4],0x80484c4
0x80483cc   <main+24>:  lea    eax,[ebp-40]
0x80483cf   <main+27>:  mov    DWORD PTR [esp],eax
0x80483d2   <main+30>:  call   0x80482c4 <strcpy@plt>
0x80483d7   <main+35>:  lea    eax,[ebp-40]
(gdb) continue
Continuing.


Breakpoint 4, 0xb7f076f4 in strcpy () from /lib/tls/i686/cmov/libc.so.6
(gdb) i r eip
eip    0xb7f076f4    0xb7f076f4 <strcpy+4>
(gdb) x/5i $eip
0xb7f076f4 <strcpy+4>:  mov   esi,DWORD PTR [ebp+8]
0xb7f076f7 <strcpy+7>:  mov   eax,DWORD PTR [ebp+12]
0xb7f076fa <strcpy+10>: mov   ecx,esi
0xb7f076fc <strcpy+12>: sub   ecx,eax
0xb7f076fe <strcpy+14>: mov   edx,eax
(gdb) continue
Continuing.

Breakpoint 3, main () at char_array2.c:8
8
printf(str_a);
(gdb) i r eip
eip    0x80483d7    0x80483d7 <main+35>
(gdb) x/5i $eip
0x80483d7 <main+35>:   lea    eax,[ebp-40]
0x80483da <main+38>:   mov    DWORD PTR [esp],eax
0x80483dd <main+41>:   call   0x80482d4 <printf@plt>
0x80483e2 <main+46>:   leave
0x80483e3 <main+47>:   ret
(gdb)

This is the second run of the program in which supposedly the address to strcpy is different from the other address.

(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)

Where is the difference? am I wrong for thinking that 0xb7f076f4 is the address of strcpy? On the second run if I am correct everything indicates that the address is 0xb7f076f4.

Also, what is ? I can't find the explanation for this anywhere earlier in the book. If someone could be kind enough to explain this from the top down to me I would appreciate it so much being that I don't know any expert in real life that could help me. I find the explanations to be vague, he explains variables and loops like if he was explaining it to a 5 year old, but leaves much of the assembly code for us to figure out by ourselves, I have not been very successful at this. Any help would be greatly appreciated.

Apparently gdb turns off ASLR for the debugged process to make (session-to-session) debugging easier.

From https://sourceware.org/gdb/current/onlinedocs/gdb/Starting.html

set disable-randomization
set disable-randomization on
    This option (enabled by default in GDB) will turn off the native 
    randomization of the virtual address space of the started program. 
    This option is useful for multiple debugging sessions to make the 
    execution better reproducible and memory addresses reusable across
    debugging sessions.

Set set disable-randomization off in gdb or in a .gdbinit file and try it again. Libc should now get loaded at a different address each time you run the binary.

Running watch -n 1 cat /proc/self/maps also is nice to see how the binary and the libraries are mapped at 'random' addresses.

As @Voo said in his comment above, the book probably refers to ASLR (Address Space Layout Randomization) which is a security feature. It changes how the address space is used for each execution so you can't rely on finding things always in the same place.

If you don't see it in gdb that means you have ASLR turned off. Either globally or locally in gdb . You can check the former using cat /proc/sys/kernel/randomize_va_space and the latter using show disable-randomization command at the gdb prompt.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM