Win 32 Bit Buffer Overflow Vulnerability — Vulnserver.exe Writeup

Can Özkan
7 min readSep 23, 2022

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

Figure 1 : Connecting to vulnserver.exe
Figure 2 : Manually Fuzzing the Application

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.

Figure 3 : Usage of generic_send_tcp

First, we will fuzz STATS command.

Figure 4 : Spike fuzzer

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.
Figure 5 : Opening vulnserver.exe in Immunity Debugger
Figure 6 : Immunity Debugger Screen

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

Figure 7 : Fuzzing STATS Command with Our Spike Script

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.

Figure 8 : Source Code of trun.spk

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

Figure 9 : Fuzzing TRUN Command with 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.
Figure 10 : Memory Layout of Fuzzed Trun Command

What is more, we will investigate buffer size.

Figure 11 : Analyzing Buffer Size

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

Figure 12 : Converting Hex to Decimal

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

Figure 13 : Source Code of fuzz1.py
Figure 14 : Executing fuzz1.py

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.

Figure 15 : msf tools
Figure 16 : msf-pattern_create Usage

We need to supply length.

Figure 17 : 3000 Byte Length Unique Pattern

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

Figure 18 : Source Code of fuzz2.py
Figure 19 : Running fuzz2.py
Figure 20 : Locating Offset

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

Figure 21 : msf-pattern_offset Usage
Figure 22 : Locating 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.

Figure 23 : Source Code of fuzz3.py
Figure 24 : Controlling 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.

Figure 25 : Mono Commands

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

Figure 26 : List of JMP ESP Addresses

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.

Figure 27 : Function Definition
Figure 28 : Table for Endianness

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

Figure 29 : Source Code of fuzz4.py

We set our breakpoint.

Figure 30 : Going to JMP ESP Address
Figure 31 : Setting Breakpoint at JMP ESP Address

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.

Figure 32 : Going to ESP Area in Stack
Figure 33 : Code Snipped from fuzz5.py

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

Figure 34 : Analyzing Bad Characters in ESP Stack Dump

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.

Figure 35 : Generating a shellcode via msfvenom
Figure 36 : Code Snipped from fuzz6.py
Figure 37 : Configuring Metasploit for Listening to Reverse Shell Connection

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

Figure 38 : Getting a Reverse Shell from Target Application

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

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Can Özkan
Can Özkan

Written by Can Özkan

Security Researcher, Penetration Tester, and Reverse Engineer

No responses yet

Write a response