Sunteți pe pagina 1din 12

Stack Buffer Overflow

2 de febrero

2009
http://www.sinfocol.org Perverthso

Aprenda Stack Buffer Overflow como si estuviera en primero

Introduccin
Bueno, ante todo, saludar a todos mis amigos de las diferentes webs, este es un manual o tutorial que promet hacer hace mucho y por motivos de tiempo no lo pude hacer, pero aqu est. En esta oportunidad hablaremos de los Stack buffer overflows en el sistema operativo Windows y la elaboracin de un exploit.

Algunos Conceptos Bsicos


Ahora explicaremos algunos de los conceptos de los Stack Buffer Overflow necesarios para empezar ya que los dems conceptos los iremos viendo a medida que desarrollemos el tutorial. Stack todo programa lo que hace al compilar es traducir su cdigo a lenguaje ensamblador y este es el lenguaje el que traduce cada instruccin a lenguaje maquina que es lo que entiende nuestro procesador, ahora, un programa en ensamblado o cdigo ensamblador se divide en 3 partes: 1. Stack Segment. Segmento de Pila 2. Data Segment. Segmento de Datos 3. Code Segment. Segmento de Codigo Pero que es la Pila? La pila (stack) es una estructura tipo LIFO, Last In, First Out, ultimo en entrar, primero en salir. Piensen en una pila de libros, solo puedes aadir y quitar libros por la "cima" de la pila, por donde los aades. El libro de mas "abajo", ser el ultimo en salir, cuando se vace la pila. Si tratas de quitar uno del medio, se puede desmoronar. Bien, pues el SO (tanto Windows como Linux, como los Unix o los Macs) se basa en una pila para manejar las variables locales de un programa, los retornos (rets) de las llamadas a una funcin (calls), las estructuras de excepciones (SEH, en Windows), argumentos, variables de entorno. Por ejemplo, para llamar a una funcin cualquiera, que necesite dos argumentos, se mete primero el argumento 2 en la pila del sistema, luego el argumento 1, y luego se llama a la funcin. Si el sistema quiere hacer una suma (5+3), primero introduce el 2 argumento en la pila (el nmero tres), luego el 1 argumento (el nmero cinco) y luego llama a la funcin suma. Una "llamada" a una funcin o direccin de memoria, se hace con la instruccin de ensamblador Call.

Su sintaxis es la siguiente: Call direccin (llamar a la direccin) Call registro (llama a lo que contenga ese registro). El registro EIP recoge dicha direccin, y la siguiente instruccin a ejecutar esta en dicha direccin, hemos "saltado" a esa direccin. Pero antes, el sistema debe saber que hacer cuando termine la funcin, por donde debe seguir ejecutando el cdigo. Justo al ejecutar el call, se GUARDA la direccin de la siguiente instruccin en la pila. Esa instruccin se denomina normalmente RET o RET ADDRESS, direccin de "retorno" al programa principal (o a lo que sea). Entonces, el call se ejecuta, se guarda la direccin, coge los argumentos de la suma, se produce la suma y, como esta guardada la direccin por donde iba el programa, RETORNA a la direccin de memoria que haba guardada en la pila (el ret), es decir, a la direccin siguiente del call. Stack Buffer OverFlow: Como su nombre refiere, es el desbordamiento de la pila, quiere decir que cuando nosotros reservamos espacio en la memoria, sta tiene una longitud determinada, ya sea definida por el programa o por nosotros mismos, y al momento de ingresar mas datos de los permitidos se producir un desbordamiento o salida de datos fuera de los limites establecidos.

Manos A La Obra
Ahora para poder explicar mejor el stack buffer overflow, usaremos el programa llamado exploitme.exe, con el cual entenderemos mejor todos los conceptos. Descripcin del Exploitme El objetivo del siguiente exploitme es que a travs de los argumentos enviados, nos muestre un mensaje que nos diga muy bien, y nuestro objetivo ser ejecutar la calculadora de Windows, sobrescribiendo el retorno de la pila. Ahora abrimos el exploitme y vemos que es lo pasa:

4 Bueno nos manda un mensaje diciendo que lo intentemos otra vez , muy bien, ahora lo abrimos con ollydbg. Ollydbg: Es un desensamblador de ejecutables, esto es que interpreta el ejecutable en cdigo ensamblador. Con el podemos ver a nivel ensamblador lo que ocurre en el ejecutable, pero antes una breve explicacin del ollydbg

Creo que con la imagen se entiende gran parte del programa. Lo nico que se ve ah algo confuso es la session registros y flags, para nuestro estudio solo hablaremos de los registros, en pocas palabras los registros son donde se almacena las variables, datos, direcciones de las operaciones que se realizo en ese momento. Luego de esa breve explicacin del ollydbg, podemos empezar nuestro anlisis del exploitme para lo cual en el ollydbg le damos File>Open y seleccionamos el archivo ejecutable exploitme.exe, ahora en la sesin de cdigo ensamblador le damos clic derecho y escogemos la opcin como se muestra en la imagen.

Ahora buscamos el mensaje que nos mostr al momento de ejecutarlo intenta otra vez, una vez ubicado le damos doble clic y nos mandara al lugar donde se ejecuta dicho mensaje. Luego de esto vemos unos cdigos mas arriba, le ponemos un breakpoint con la tecla f2 en la direccin 00401321. Para poder enviarle datos como lo hicimos por consola, vamos a debug>Arguments Aparecer una caja de texto donde pondremos los argumentos, en mi caso AAAAAA. Unas 10 veces. Puara probar luego les pedir que reinicien el programa para lo cual le dan en el botn <<, para ejecutar presionamos la tecla f9 y el programa se detendr en la direccin 00401321 que es donde le dijimos que se detuviera. Muy bien, ahora empezamos a ejecutarlo lnea por lnea con la tecla f8 hasta que lleguemos al offset 00401329 00401329 |. C74424 04 004>MOV DWORD PTR SS:[ESP+4],exploitm.00404000 ; ||ASCII "bien;)" Lo que realiza el programa es enviar el dato ubicado en la direccion 00404000 al stack en este caso carga la frase bien ;) Luego, en la siguiente instruccin, mueve al stack lo que se encuentra ubicado en la direccin almacenada en EAX que en este caso es 0022FF60 00401331 |. 890424 MOV DWORD PTR SS:[ESP],EAX ; ||

La siguiente instruccin lo que hace es comparar los valores almacenados en las direcciones del stack. en Si nos fijamos en la sesin de memoria del ollydbg, la direccin 0022FF50 es el inicio de los datos que nosotros enviamos al programa. Podremos modificar los datos de la direccin 0022FF60, para poder hacerlo, tendramos que escribir una cadena de texto con longitud igual a la diferencia 0022FF60-0022FF50, lo cual en base hexadecimal nos da una longitud de 10h que en si equivalente decimal son 16 letras, las cuales son el nmero de caracteres para lograr llegar a dicha direccin, PERO si queremos sobrescribirla tendramos que sumarle cuatro (4) caracteres mas. Escribimos una cadena con 20 de longitud, y para darnos cuenta que es lo que pasa, escribimos primero 16 As y 4 Bs como hicimos al principio debug>Arguments (AAAAAAAAAAAAAAAABBBB) Y le damos f9 y se detiene en la direccin del breakpoint, luego le damos f8 hasta la siguiente instruccin: 00401334 |. E8 070F0000 CALL <JMP.&msvcrt.strcmp> ; |\strcmp

Donde llama a la API strcmp, la cual hace comparaciones entres dos direcciones de memoria. Fijmonos como queda el stack en dicho momento:

Y sorpresa! ahora comparara BBBB con bien ;), entonces pensamos un ratito y concluimos que nos mandar un mensaje correcto cuando las dos cadenas sean iguales, as que en vez de escribir BBBB colocamos bien ;) y veremos que pasa! Repetimos el mismo proceso, reemplazando el argumento por AAAAAAAAAAAAAAAAbien;), le damos aceptar y reiniciamos el ollydbg, luego f9 y de nuevo nos detenemos en el breakpoint, de nuevo le damos f8 hasta llegar a CALL <JMP.&msvcrt.strcmp> y de nuevo verificamos la pila para ver que pasa

Ahora el resultado del API ser exitosa, y nos mostrar el mensaje de que hemos pasado la prueba.

Segunda Parte
Como hacemos entonces para explotar el programa y ejecutar cdigo arbitrario? Empezamos a analizar la estructura de los programas en lenguaje ensamblador y vemos algo muy interesante los RETN

RETN - Regreso cercano, solo obtiene una palabra del stack, transfiere el control al offset almacenado en la palabra.
Ejecutamos de nuevo el programa hasta llegar al primer RETN y analicemos que pasa.

Vemos el registro ESP, el cual contiene la direccin del stack 0022FF7C, vemos tambin que la pila en dicha direccin contiene una direccin del programa y al pulsar una vez ms f8, el programa saltar a la ubicacin 004011E7 almacenada en el stack. Reiniciamos el programa, y le pasamos el siguiente argumento: AAAAAAAAAAAAAAAABBBB Si observamos la pila, la direccin 0022FF50 es donde empieza a almacenarse los datos que nosotros ingresamos. Si no existe un adecuado control de los datos de entrada podemos poner una cadena muy larga y sobrescribiremos la direccin 0022FF7C que es donde se guarda el salto del RETN. Probemos, y para no poner datos a ciegas, hacemos como en la comparacin, restamos 0022FF7C-0022FF50 que es igual a 2C en base hexadecimal y su valor equivalente en decimal es 44, para llegar a la direccin del salto, llenaremos los datos con 44 Aes y como antes 4 Bes y veremos que pasa!

Primero que todo, el registro ESP sigue apuntando a la direccin de memoria 0022FF7C, podemos observar que en tal direccin los datos cambiaron, ahora ya no esta el valor anterior (004011e7) sino que ahora vale 42424242, y que al ejecutar el RETN ira a esa direccin, que no est apuntando a ninguna instruccin de ensamblador. Tal valor (42424242), fue el que nosotros colocamos, porque 42424242 equivale en ASCII a BBBB. Podemos luego controlar el salto del programa y redirigirlo a donde queramos!

10

Sabemos que los datos que metemos se guardan en la pila y como podemos ver en la ventana principal, el programa contiene unos OPCODES, el cual en ollydbg, lo podemos ver como cdigo hexadecimal de las instrucciones, entonces est claro que podemos generar un cdigo en hexadecimal (Conteniendo instrucciones de ensamblador), colocarlo como dato de entrada y hacer que el programa retorne a dicho cdigo para empezar a interpretarlo.

Armando un Exploit
Normalmente todo exploit consta de tres partes: 1. Cdigo Basura: Yo denomino as al cdigo con el cual logramos hacer que ocurra un error y por medio de este llegamos al RETN. En s, es rellenar la pila si fuera necesario para poder explotar el fallo. En este ejemplo seria las 44 Aes que colocamos para poder llegar al retorno. Este contenido puede ser aleatorio, ya que realmente no importa mucho su contenido. 2. Direccin de retorno: En esta parte es donde re direccionamos el programa para que empiece a ejecutar nuestra shellcode. 3. Shellcode: Son el conjunto de instrucciones que el procesador puede entender. Comnmente estn codeados en hexadecimal, ya que podemos representar fcilmente los OPCODES con esta forma de representacin de la informacin.

11

El registro ESP guarda la siguiente direccin despus de nuestra cadena de entrada. Usaremos dicha estructura para nuestro bien, buscamos una instruccin en el programa o en cualquiera de las DLL que usa, una instruccin que haga referencia al registro ESP, puede ser call ESP o jmp ESP Para cumplir con tal objetivo, usaremos el programa findjmp.exe de la siguiente forma:

El programa nos da el offset donde existe saltos hacia el contenido del registro ESP, pero aqu hay algo muy importante, ya que las direcciones de los saltos son diferentes para cada versin de Windows, es por esta razn que muchos exploits no son universales, porque queremos usarlo en un Windows para el cual no fue diseado, pero esto se soluciona cambiando esta direccin de salto, en nuestro caso, el exploit solo funciona para Sistemas Operativos Windows XP sp2 en espaol. Colocaremos la direccin de retorno al revs (ED1E957C), por la forma como el procesador Intel maneja las direcciones del lenguaje ensamblador (Little Endian). Ya tenemos la direccin del salto. Poniendo esa direccin haremos que nuestro programa salta a la que tiene almacenado ESP que en nuestro caso ser 0022FF80 y es desde esta direccin donde colocaremos nuestro shellcode. Para nuestra suerte es la siguiente lnea de cdigo, entonces solo tendremos que realizar el exploit de la siguiente forma: Cdigo Basura + Direccin de Retorno + Shellcode Como lo presenta el siguiente cdigo: Code = basura + salto + shellcode Win32api.WinExec(exploitme.exe +Code)

12

Y ejecutando el exploit, vemos que primero nos saca el mensaje de que intentemos otra cosa, e inmediatamente se ejecuta la Shell.

S-ar putea să vă placă și