Vulnserver TRUN: Beginner Windows Exploit Development and Reverse Engineering

BOF, Windows, OSCP, Pentesting

Intro #

This will be the first post of a series of Vulnserver-related posts. Vulnserver itself is “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” (stephenbradshaw, 2020)

Download link and related sources:
Github Repo
The Grey Corner Blog

Prerequisites #

p.s I’ll be using Python3

TRUN Exploitation #

Vulnserver has multiple functions that can be exploited and TRUN is one of it. Exploiting TRUN can be considered as one of the easiest since it does not require any bypasses or any advanced techniques.

To access this functionality, we need to send TRUN <argument> to the program by simply connecting to the running service on port 9999

Reversing TRUN #

To investigate what is being processed by the progam when user prompt TRUN command, we will do a little reverse engineering. In this case I will be using IDA. You can use any disassembler that you prefer.

TRUN in ida1

After tweaking it around, we can get a hang of what is going on inside this if statement.

TRUN in ida edited

Inside this if statement we can see that the program is allocating 3000 bytes of buffer with malloc and reset it by filling it with \x00s. The program then continue to check whether the argument of TRUN command contains 46d or .. If the input contains ., the program will copy the input to the allocated buffer (3000 bytes) and pass it to Function3().

TRUN in ida Function3()

Function3() is where things got a little bit exciting because it uses the vulnerable strcpy() function to copy the input to a new placeholder which roughly is only 2000bytes-ish (if i get it correctly). If the input passed to this function is actually longer than the designated destination, it will cause a buffer overflow in the stack.

Fuzzing to Verify Vulnerability #

To fuzz and verify the vulnerability we need to list out all the requirements that may produce the crash or the overflow.

  1. Input must contain .
  2. The length is more more than 2000 bytes and less than 3000 bytes (because the malloc only gives us 3000)

The impatient me quicky power up the IDA local windows debugger and set the breakpoint somewhere near the stcpy and run my custom fuzzing script for this particular case. (The script will be included later at the end of this post.)

TRUN in Fuzzing in IDA

After sending around 2098 bytes+ 1 byte of space (‘ ‘) and + 1 byte of dot ‘.’ (total 3000 bytes), it crashed and the EIP of the program is overwritten with the pattern created by the fuzzer (I use pwntools cyclic btw).

To make sure this works, reproduced the crash while attaching the program to immunity debugger which will be our main tool for this exploitation attempt.

TRUN Fuzzing in Immunity

Finding Offset #

It is easy to find the offset of this overflow since I already use a pattern creator from pwntools, cyclic.

In my case, the offset is 2005.
You can verify this offset value by trying to change the EIP value with simple value such as “BBBB” or “XXXX”. (will not included because I’m lazy)

Finding Badchars #

Bad characters are characters/bytes that will make our exploit not work. It’s called ‘bad’ for a reason. To find bad characters, We are using mona.py which is a powerfull python script that can be used inside immunity debugger. Here are the steps:

  1. Set mona working Directory
     Set to c:\mona\{filename} 
     !mona config -set workingfolder c:\mona\%p
    
  2. Generate array of possible characters
     Generate "\x01" to "\xff" to a file in working directory
     !mona bytearray -cpb "\x00"
    
  3. Send \x00 to \xff as part of payload to crash the program
    In this case Im sending "TRUN . " + pwn cylic 1990 + "\x01\x02\...\xff" using python script I wrote.

  4. Compare the generated file with the value we send to stack
     Find the address of our array in stack with 'Search for Binary String' then run
     !mona compare -f c:\location\bytearray.bin -a <address in stack>
    

TRUN find bad chars

If mona found no badchars, it will say so . . . .

Finding JMP ESP To Get Control Over Execution #

Jumping to ESP will grant us the ability to control what will be executed by the program. It will enable us to inject a shellcode in the stack and make the program execute it.

To do so, we can utilized mona.py again to find jmp esp address inside a DLL that we can use to redirect the program.

!mona jmp -r esp

Using the command above mona.py will list out all jmp esp available to use.

TRUN find jmp esp

In this case, I wil be using the first one, 0x625011af. To verify that we can access the address, we can set a breakpoint inside the debugger at that specific address and try to overwrite the EIP to that address using our exploit.

TRUN verify jmp esp

On the above image, the breakpoint have been hit and the program is being paused, which means we successfully access the jmp esp and now get control over the flow of the program to the stack.

Full Exploitation #

Mini Recap of What We Have So Far #

Payload Structure #

If you have followed this article through you should already have:
payload="TRUN . " + "A"*2005 + EIP + "C"*(3000-2005-11)

Generating Shellcode with MSFVenom #

You can google this part yourself, we just need to generate a payload (reverse shell or bind shell).

Adding Nopsled and Full Exploit Structure #

Nopsled is being used to adjust the stack so the shellcode will be executed properly. I personally always use 16 bytes of nopsleds because 16 is the magic number ;). So, at the end the full payload should look like this:
payload="TRUN . " + "A"*2005 + EIP + "\x90"*16 + <shellcodes generated>

Successful Exploitation #

suxes
Voila! We popped a shell!

Conclusion #

In this article we have learn how to actually exploit vulnerable windows x86 program with simple buffer overflow. If you are new, I know this seems too much to understand at one go but trust me, you’ll get it sooner or later. In the next article in this series, we will try to exploit a harder function from vulnserver. Stay tune!

Scripts and Exploit #

All final script can be found in this repo