Win 32 Bit Buffer Overflow Vulnerability — Vulnserver.exe Writeup
Hi All,
In this blog post, I will explain Windows 32 bit buffer overflow vulnerability that exists in vulnserver.exe.
Necessary Programs:
Immunity Debugger
Mona.py
Vulnserver.exe


Doing this manually is good but we need to automate this process.
Before further going, what is Immunity Debugger?
Immunity Debugger is a powerful way to write exploits, analyze malware, and reverse engineer binary files. It builds on a solid user interface with function graphing, the industry’s first heap analysis tool built specifically for heap creation, and a large and well supported Python API for easy extensibility.
We need to fuzz this application to be able to understand whether this app is vulnerable or not. We will do fuzz process with spike — a built-in tool in Kali Linux.
Below is the usage of spike.

First, we will fuzz STATS command.

s_readline() function reads the banner. In our case “Welcome to Vulnerable Server! Enter HELP for help”. Then, we can start to place our command, that is, STATS in this case. Once we are done specifying s_string() function, we will place the fuzzer function, namely, s_string_variable(“FUZZ”).
Before we start fuzzing process, we need to configure our debugger so that we can analyze the vulnerable application at CPU level.
- Start Immunity Debugger as administrator.
- Open vulnserver.exe as shown below.
- Once you open it, debugger sets a breakpoint at entry point of the program. Make the program run and you are good to go.


Now, we will start fuzzing STATS command with the objective of crashing the application.

No, the application did not crash. We can conclude that STATS command may not be vulnerable to memory corruption vulnerabilities such as buffer overflow.
Let’s jump to TRUN command.

Now, we will fuzz the application with trun.spk spike script.

The application immediately died. Analyze the Immunity Debugger to see what is going on with vulnerable application.
- We see that application adds /.:/ before taking argument from user.
- Since EIP is overwritten by AAAA, the application stopped running. In other words, access violation has occurred whiled executing AAAA.

What is more, we will investigate buffer size.

Basically, we have 2992 byte to play with on the buffer.

Now, we will write our own Python3 program to crash the application.


When we run the program, we replicated same crash. We successfully broke the program again. We are pretty sure that we can control EIP register. It is time to explore at which offset it is. How do we learn this information? It is not super hard to find out. Metasploit has a useful tool in order to create unique set of characters so that you can easily find out at which offset EIP is. Recall that our length is 2992 but for simplicity we will create it with a length of 3000.


We need to supply length.

In our fuzzer script, we need to place this unique pattern. Instead of sending all the A’s, we will send msf pattern.



Program crashed one more time but this time eip has 386F4337 value. We will try to locate the offset.


Our offset is 2003, meaning we need to send 2003 byte just before controlling the EIP. Furthermore, we will check whether we can fill EIP with BBBB. If so, we make sure that we succussfully locate the exact place of EIP.


Yes! We successfully manage to control EIP. EIP is fulled with 42, which is hexadecimal representation of B.
Now that we can control EIP, what should we do as the next step? Notice that ESP register is filled with C’s. The idea would be that we might place a shellcode (for instance, a reverse shell) in ESP and we can have the application point ESP through EIP, more specifically, through JMP ESP instruction and then start executing code in ESP. We now need to find JMP ESP instruction in the program. To be able to find ESP, we will take adventage of mona.py.

If you write “!mona” to immunity debugger, you see a list of commands that you can use within mona.py. In our case, we will use JMP command to find pointers that will allow us to jump to a register.
Command : !mona jmp -r esp

We choose “0x62501203” as address regarding jmp esp. Also, if you look at it in a detailed way, there is no ASLR, rebase, safeSEH, which are memory protection mechanism against exploits. One more important consideration is that you cannot directly write “0x62501203” as address to EIP. We have a small problem that needs to be addressed. The problem is that this is a memory address to the binary and it has to be in little endian format. We need to convert this memory address to little endian format. There are two different ways so as to achieve it. First, we can do it manually and write “\x03\x12\x50\x62”. The other way is that you can import struct library and use the pack function.


We will re-run our program again and set a breakpoint at “0x62501203” to see if the program jumps to ESP.

We set our breakpoint.


After you run the program, it will hit at breakpoint. Next, press F7 and it will take you to the ESP buffer area that is filled with C’s. We are able to successfully jump to ESP area. We are in good position. Here we have another problem that needs to be solved. Some programs might not execute all the code given inside the shellcode. We need to take bad characers out.


Once we send all the bytes, we analyze ESP dump. There is no bad character other than 0x00.

Once we arrange bad chars, we are moving into the shellcode and we should not place our shellcode just at the beginning of ESP. We need to place some NOPs so that there will be a slight transition and our exploit will be more reliable. I generally go with 16 bytes of NOP. Once we finish this operation, we must create our shellcode payload. We will use msfvenom to generate a shellcode.



To be able to listen to reverse shell, I set up msfconsole.

We have successfully managed to get a reverse shell from the target server. We are now executing codes remotely. We have Remote Code Execution (RCE) by taking the advantage of stack based buffer overflow vulnerability.
Thanks for reading.
Can ÖZKAN