Exploiting Basic Buffer Overflow in VulnServer (TRUN Command)

Bryan Leong (NobodyAtall)
11 min readMay 22, 2021

--

VulnServer is useful for beginner which wants to learn how to find buffer overflow vulnerabilities & develop their own exploit script that able to abuse the buffer overflow vulnerability. I hope my article can helps beginner understand well in how to perform basic stack based buffer overflow as I’ll try to include more details in this article which might be good for beginner.

Image of immunity debugger in finding buffer overflow vulnerabilities in binary.

What You Can Expect From The Article

In this article I’ll be covering on:

  • spiking to determine the specific command in the program that is vulnerable to buffer overflow
  • finding the correct offset to overwrite the EIP (Instruction Pointer)
  • checking for bad characters that will terminate the shellcode
  • using mona.py to find the modules that have the specific assembly instruction
  • develop exploit script to inject shellcode
  • spawning a reverse TCP shell using msfvenom generated shellcode

Information About VulnServer

From the VulnServer Git Repository, we can find out the information about this program.

  • VulnServer is a multithreaded Windows based TCP server that listens for client connections on port 9999 (by default) and allows the user to run a number of different commands that are vulnerable to various types of exploitable buffer overflows.
  • This software is intended mainly as a tool for learning how to find and exploit buffer overflow bugs, and each of the bugs it contains is subtly different from the others, requiring a slightly different approach to be taken when writing the exploit.
  • Though it does make an attempt to mimic a (simple) legitimate server program this software has no functional use beyond that of acting as an exploit target, and this software should not generally be run by anyone who is not using it as a learning tool.

Setting Up The Environment

Let’s get the environment setup first before we dive in to analyze the VulnServer program.

First, we start up the VulnServer program on our Windows machine & host the VulnServer program on port 9999.

In this article, I’ll be using Windows 7 x64 machine to host the VulnServer program.

Now go back to our Kali Linux (or your preferred pentesting OS) and try to connect to the VulnServer program that’s hosting on port 9999. If you’ve successfully hosted it, you’ll get the following result below.

Now go back to our Windows machine & attach the VulnServer program into Immunity Debugger to observe the registers & the stack.

It should looks like this after we’ve successfully attached the process into Immunity Debugger.

Finding Buffer Overflow Vulnerabilities

After we’ve done setting up the environment it’s time for us to start to find for vulnerabilities in the VulnServer binary. Let’s start with performing spiking on the VulnServer commands.

In normal testing, we will normally create spiking template file for every single commands to test it out. But in this article, we’ll be covering for TRUN command only.

1. Spiking (Determine whether it’s vulnerable to buffer overflow)

First, we create our spiking template file for TRUN command & save it as trun.spk.

Further breakdown on the spiking template functions:

  • s_readline : reading the binary banner
  • s_string : place the string in each iteration of spiking
  • s_string_variable : append the fuzzed string into the spike

Before we start the spiking process, let’s run our wireshark to capture the network packets for further analyze.

Now, we use generic_send_tcp command to perform spiking with the ‘trun.spk’ spiking template that we just created.

Notes: If the program in the Windows machine crashed it means that it’s vulnerable to buffer overflow.

So now we go back to the Immunity Debugger & we noticed that the VulnServer program just crashed!

1) The EAX are filled with the spiking strings that we set just now “TRUN /.:/AAAAAAA….”.
2) Which caused the EIP overflowed with AAAA too, due to the EIP of “0x41414141” is an invalid address that’s why the program crashed.
3) As you can see that the stack over here are filled with all the A’s, so it shows that this TRUN command are vulnerable to buffer overflow.

Then we check the below message in Immunity Debugger & we found that the program crashed due to accessing the address of 0x41414141 (“AAAA”) which is not a valid address.

Remember to terminate the generic_send_tcp from continuing sending spikes to VulnServer after we’ve found the buffer overflow vulnerabilities.

2) Finding the Sweet Point(offset) To Overwrite the EIP Address

Now let’s check the wireshark to find how many bytes that caused the VulnServer program to crashed.

Tips: We can apply this filter to filter up the VulnServer & our host machine communication packets.

Now let’s follow the 1st SYN packet TCP stream. If you notice that if the spikes & the VulnServer successfully complete their communication it’ll return ‘TRUN COMPLETE’ string.

Now let’s continue checking another TCP stream until we find the stream that doesn’t shows ‘TRUN COMPLETE’ string. On the 2nd TCP stream we notice that the ‘TRUN COMPLETE’ was missing which means that this is where the VulnServer crashed.

Under there it’ll shows that how many bytes that our spike sends to crash the VulnServer. Roughly it takes 5,013 bytes to caused the VulnServer to crash.

Now in order to find the correct padding size that we need to overwrite the EIP with our specified address, we can use metasploit pattern_create to create the patterns.

This is how the pattern looks like in the pattern.txt.

Now let’s write our python script to send the pattern that we created to find the correct position to inject the EIP address. Copy and paste the patterns from pattern.txt into the pattern variable in the script.

Tips: Remember to restart the VulnServer program everytimes you want to perform a new testing.

1) Debug > restart
2) click on the play button to continue running until the program status turn into running.

Now let’s execute the python script that we created.

Let’s check back the Immunity Debugger to see what is the pattern that end up in our EIP address.

Now let’s use pattern_offset to find the offset location. The matched offset will be 2003, so our padding should be 2003 before reaching the EIP address.

Now let’s edit our exploit again to make sure that we can overwrite the EIP with the specific address we want.

  • The EIP we’ll pack it up with <I (as the stack will be storing the address value reversely or we called it as little-endian format).
  • We append the junk bytes after the EIP address to find out the maximum bytes that we can use to inject our shellcode into the stack.

Now let’s run our exploit script & check the Immunity Debugger EIP address again & we’ve successfully injected our specific address “0xDEADBEEF” into the EIP address!

Let’s check and see how many extra bytes that we can inject our shellcode into the stack.

Right click on the ESP register & select follows in the stack.

Now double click on the current pointed stack frame, it should looks like this format.

Now scroll down until the end of the ‘B’ junk string & from the result we know that we have 0x3D8 of extra bytes that we can used for our shellcode.

We can convert the hex value into decimal using calculator. Our shellcode that we can inject must be smaller than 984 bytes.

3) Finding Bad Characters That Will Terminate Our Shellcode

Now let’s find out what are the bad characters that will terminate our shellcode. We can do that by generating (\x01-\xff) in python.

Notes: \x00 will be skipped as this is the null character which will terminate the shellcode.

Now let’s add it after our nop_sled (\x90). If you notice that I’ve added a nop_sled between the EIP address & the bad character, we need to give some space between the EIP address & the shellcode/bad character in order to successfully execute our shellcode.

Let’s execute the exploit script & observe the Immunity Debugger. Right click ESP register select follows in dump.

So here will be all the hex characters that we injected into the stack. Let’s check it in the dump. We need to check & see whether is there any bad characters that will caused the shellcode to terminate by reading the characters one by one.

Hint: There’s another way of reading it too by referring the last column. If you notice that if there’s no bad characters in it right, it will end up in this pattern (x8, x0) <x will be the hex number>.

So here it seems like there’s nothing happened in our bad character code as all the characters until \xFF appears in the dump. The only bad character will be \x00.

4) Finding ‘JMP ESP’ Instruction To Execute Shellcode in Stack

Now we need to find the ‘jmp esp’ address in order to let us jump into the stack address to execute our shellcode. We can use mona.py script to help us finding the correct modules that have ‘jmp esp’.

First, we need to use the modules command (!mona modules) to list all the modules that we can find our ‘jmp esp’. The modules that we need to use must have ASLR turn off, to prevent the ‘jmp esp’ address to be randomize after the program reboot.

Here it shows that the ‘essfunc.dll’ under VulnServer directory have everything turn off which is a good case for us.

Let’s check & see is there any ‘jmp esp’ instruction in the essfunc.dll. Here it shows that there’re 9 pointers of ‘jmp esp’ instruction inside the essfunc.dll.

Notes: Remember that ‘jmp esp’ instruction address must not contain \x00 bad character as it will terminate our shellcode too.

Let’s use the 0x625011afjmp esp’ instruction address.

Now let’s edit our exploit script again by changing the EIP address to the specific ‘jmp esp’ address.

Now let’s see what would happen in the Immunity Debugger.

If you notice that after our padding “A” it’ll be the EIP address right, so now it’s pointing to the ‘jmp esp’ instruction address in essfunc.dll. We can see it by right click > select follows in disassembler.

Now this instruction will tell the EIP address to jump into the address of our current ESP pointing to.

Which makes that our EIP to redirect us into the stack!

After the inc EDX (0x42) instruction has finished our EIP will end up at the address of 0x023DFDB8.

5) Time To Spawn a Shell!

So now it’s time for us to generate our shellcode to get a reverse shell, we can use msfvenom to generate the shellcode.

  • We generate the shellcode into hex format.
  • Remember to specify the bad character “\x00” to prevent it appears in our shellcode, as it will caused our shellcode to terminate.
  • 351 bytes for our shellcode payload size, we’ve enough of space to include that in the stack.

Content in shellcode.hex file.

Copy the shellcode from shellcode.hex into our exploit script.

The final exploit script will looks like this.

Now let’s try to run our exploit script & see we can spawn a shell & return it back to us or not. Start our netcat listener first.

Run our exploit script.

Voila! We’ve just received our reverse shell!

Interesting findings in Shodan

When I'm writing this article, I found that someone actually just run this VulnServer program in the public internet. That’s no good man, as we know that this program is very vulnerable, attacker might take the opportunity to takeover your machine remotely by executing malicious commands. So please for my readers, please run this VulnServer in your own secure network only. Don’t expose your machine vulnerable to the public.

Conclude

So that’s how we can develop our own buffer overflow exploit script from the beginning until the execution. I do hope this article can helps the beginners to understand more on the basics & flows on it.

The exploit script for VulnServer TRUN Command I’ll include it below.

--

--

Bryan Leong (NobodyAtall)
Bryan Leong (NobodyAtall)

Written by Bryan Leong (NobodyAtall)

A Bachelor of Computer Science student that’s passion in CyberSec & Pentesting.

No responses yet