CTP/OSCE – Explotando el infame VULNSERVER funcion (LTER – SEH Overflow )

INTRODUCCIÓN

Hola a todos, en este artículo vamos a resolver la explotación del binario  VULNSERVER, Específicamente la función LTER para aquellos que estén animados a presentar su examen de OSCE de offensive Security, creo que le puede servir este artículo, quien no, pues aprende acá y ahora conmigo, la idea primordial es explicar los pasos fundamentales de explotación y como descubrir dicha vulnerabilidad desde cero, adicional, superar la cantidad de obstáculos que se nos presentarán. Pueden encontrar el material usado para este artículo en el siguiente link.

 ¿A QUÉ NOS ENFRENTAMOS?

En esta publicación en particular vamos a tratar el tema de recreación de la sobre escritura de SEH (Structure Exception Handler), usaremos saltos negativos, stack pivot y encodearemos a mano nuestras cargas útiles o payloads luchando con los badchars, para poder ejecutar código remoto.

LO QUE NECESITAMOS

Para resolver este software necesitamos de las siguientes herramientas:

  • Immunity Debugger y/o Ida Free
  • Un editor de código (SublimeText/PycharmCommunity/VisualStudioCode)
  • El binario VULNSERVER
  • boofuzz
  • Burpsuite Community
  • Windows 10 PRO N o XP SP3

Vamos a dividir esta explotación en dos fases:

FASE REVERSING: En esta fase haremos un análisis estático al binario donde reversaremos la función LTER y encontraremos el fallo solo reversando.

FASE DINAMICA: En esta fase haremos uso de software como boofuzz para realizar fuzzing sobre el binario y descubrir el fallo de forma dinámica.

ANÁLISIS ESTÁTICO

Para esta fase voy hacer uso de la herramienta IDA, puede ser la versión Free o PRO, igual el análisis estático funciona igual en cualquier versión, lo hago con esta herramienta por que es más comoda para mi gusto, ustedes pueden usar la que mejor se ajuste a su necesidad.

REVERSANDO Y ENCONTRANDO EL FALLO

Lo primero será abrir nuestro binario VULNSERVER desde IDA.

Lo primero que haremos será buscar las strings del binario y ver si encontramos palabras relacionadas a LTER.

Damos doble click sobre la primera string LTER en .rdata:00404477, buscamos sus referencias presionando X sobre la palabra LTER luego de haber presionado doble click, de la siguiente forma.

Vamos a la referencia que nos muestra el ida y llegamos a la siguiente zona.

int strncmp ( const char * str1, const char * str2, size_t num );

_str1: Cadena C para comprar
_str2: Cadena C para comparar
_num: Número máximo de caracteres para comparar ( size_t es un tipo integral sin signo.)

Parametros funcion _strncmp


Lo primero que logramos observar es el uso de la función _strncmp la cual
compara caracteres de dos cadenas, compara hasta _num caracteres de la cadena C _str1 con los de la cadena C _str2. Esta función comienza a comparar el primer carácter de cada cadena. Si son iguales entre sí, continúa con los siguientes pares hasta que los caracteres difieran, hasta que se llegue a un carácter nulo de terminación o hasta que los caracteres numéricos coincidan en ambas cadenas, lo que ocurra primero.

Luego de pasar estas comparaciones vienen unas inicializaciones de buffer dinámicas en memoria con malloc, de 0x1000 y luego llena los bloques de reservados con memset.

Si seguimos traceando vemos algo interesante y es que va a leer nuestro buffer posición por posición y lo va comparando nuestros datos con 0.

Esta comparación tiene algo importante y es que si no es mayor o igual a 0, se va activar la bandera SF la cual será usada por el siguiente código, tomando el valor que contiene la posición del buffer en ese momento y lo resta con 0x7f.

Una vez terminada de hacer todas esas jugadas, encontramos una última comparación donde en la posición de nuestro buffer compara con 0x2e o «.».

Ojo que si no tenemos el 0x2e para comparar no podremos entrar a la función _Function3, que por ahora no hemos verificado y hasta el momento no hemos encontrado nada que nos ayude a desencadenar la posible explotación de VULNSERVER, así que podemos cumplir esta premisa para entrar a la función _Function3 y ver que hay en ella.
Esta función recibe como parámetro el buffer que el usuario ha enviado al binario, también debemos tener en cuenta que al inicio cuando se inicializaron los buffers con malloc en la función LTER su size era de 0x1000.

Podemos observar que recibimos como parámetro nuestro buffer que es la data que nosotros enviamos, y se hace una copia sin validar el size a nuestro buffer de destino inicializado al inicio de la función LTER con un size de 0x1000 y rellenado con 0.

RESUMEN ANÁLISIS ESTÁTICO

Hemos analizado de forma estática la vulnerabilidad y adicional, hemos comprendido algunas cosas que el software nos juega para poder hacer más complicada la explotación, como la restricción de caracteres.
Entonces para la explotación de este escenario que debemos tener en cuenta:

  • Debemos poner el «.» después del nombre de la función, para poder llegar a la función vulnerable.
  • Debemos usar en nuestro exploit caracteres <= a 0x7f o jugar con esta resta con el fin de poder evitar que se rompa nuestro exploit.

ANÁLISIS DINÁMICO

Para esta fase voy hacer uso de la herramienta IMMUNITY DEBUGGER, y una plantilla de boofuzz para realizar fuzzing (en el artículo anterior enseñamos como usarlo), ustedes pueden usar la que mejor se ajuste a su necesidad.

DEBUGGEANDO Y ENCONTRANDO EL FALLO

En esta fase lo primero será abrir nuestro binario en immunity debugger y ponerlo a correr, este servicio está corriendo en el puerto 9999.

Realizando fuzzing en la aplicación con boofuzz

Vamos a configurar nuestra plantilla con boofuzz para realizar fuzzing, pero antes veamos como poder interactuar con VULNSERVER, para eso me conecto al servicio y veo su funcionalidad, y pongo el wireshark a la escucha para ver su tráfico.

Vemos que la secuencia es conectarse, hacer una petición recibir su respuesta y se mantiene en ese ciclo, importante tener esto en cuenta con el fin de programar bien nuestra plantilla boofuz.

Lanzamos nuestro fuzzer.

Vamos a nuestro immunity debugger y nos encontramos con lo siguiente.

Vemos que nuestro programa se ha hecho trizas, nuesro fuffer ha hecho un buen trabajo y ha roto muchas cosas en VULNSERVER, sobreescribimos el SEH y nos muestra adicional en el stack la función strcpy que es la que al parecer ocasionó el problema, también vemos que el parámetro LTER lleva el punto como habiamos visto en el análisis estático, parece que el fuzzer se lo agrego automáticamnete, genial.

PROGRAMANDO NUESTRO EXPLOIT

Bueno, ya comprendimos la vulnerabilidad desde el vector estático y dinámico, ahora empieza la parte más divertida, que debemos tener en cuenta:

  • Nuestro exploit debe tener un punto después de nuestro llamado a la función LTER en VULNSERVER.
  • Debemos jugar con la restricción de datos >= a 0x7f la cual restará el dato por dicho valor, en nuetsras cargas útiles.
  • Debemos buscar un gadget POP – POP -RET .
  • Debemos programar nuestra shellcode y a ejecutar código.

Primero que todo vamos a buscar el offset donde podemos controlar SEH, para eso voy armar mi plantilla de exploit base, con un patrón único de 5000 caracteres, alfanumérico.

Lanzo mi exploit y obtenemos:

Sobreescribimos SEH como era de esperarse y obtenemos la siguiente string, 0x356f4534 que en ascci sería 4Eo5, chr(0x34) + chr(0x45) + chr(0x6f) + chr(0x35), buscamos en nuestro exploit esta string y hemos enviado 3558 bytes para sobreescribir SEH, de los cuales restamos 8 bytes para controlar SEH y NSEH, quedandonos las cuentas asi:

trash = 3550
trash += NSEH
trash += SEH
trash += «A» * 5000 -len(trash)

Vamos a modificar nuestro exploit con los cálculos que acabamos de hacer, haber si todo es correcto, enviaré mi fruta con 3550 más 4 bytes A’es y 4 bytes B’es, más el padding para completar 5000 y romper el SEH.

Lanzamos nuestro exploit y tenemos los resultados esperados…

Excelente!!!, ya tenemos el SEH controlado, busquemos nuetsro gadget pop – pop – ret, debemos tener en cuenta que nuestro gadget no debe tener valores mayores a 0x7f, ya que hará la resta sobre ese mismo valor, la opción en estos momentos es trabajar con valores alphanumeric, así que vamos a buscar nuestro gagdget, afortunadamente VULNSERVER mantiene una dll, (essfunc.dll) la cual no tiene ASLR ni protección de SEH, así que podemos usar esa dll para buscar nuestro gadget, yo usaré idasploiter o el mismo immunity debugger para buscar el gadget, con idasploiter pueden ver su uso desde acá.

Genial, tenemos un gadget que cumple con los requisitos, reemplazemos nuestro SEH con el valor de nuestro gagdget haber que sucede, ponemos un breakpoint en nuestro gadget, corremos el depurador y lanzamos nuevamente el exploit.

Una vez pasado la excepción, saltamos a nuestro NSEH que en este caso es 0x43434343.

Necesitamos más espacio para trabajar, 28 bytes no son suficientes para funcionar incluso sin restricciones de caracteres. Podemos dar un salto hacia atrás, con un par de modificaciones.
Para un salto normal hacia atrás, usaríamos los códigos de operación eb XX, donde XX es igual al número de bytes que queremos saltar, menos 1, restados de 255 y convertidos a hexadecimal. Entonces, si queremos retroceder 64 bytes, usaríamos c0, 128 bytes serían 80. No podemos usar ninguno de estos, pero si usamos FF, se convertirá a 80 cuando vulnserver.exe lo haga hex(0xff -0x7f), es una conversión alfanumérica. En lugar de usar eb para un salto corto, podemos usar 77 para un salto corto condicional. Este salto se basa en la bandera cero y la bandera de acarreo no está activada. Podemos asegurarnos de que estén configurados en cero poniendo una operación delante de ellos, como \ x42 que se traduce en INC EDX. Se necesitaría un conjunto de circunstancias muy poco probable para que INC EDX conduzca a la bandera de cero y se establezca la bandera de transporte.
Nuestro gadget se armaria asi:

0:  42                      inc    edx
1:  42                      inc    edx
2:  77 ff                   ja     0x3 => hex(0xff – 0x7f) = 0x80

Establecemos NSEH igual a «\x42\x42\x77\xff» y lo agregamos a la cadena de ataque. Si enviamos esta cadena y la seguimos en el depurador, luego damos el salto, llegamos a unos 127 bytes de código que podemos usar.

Podemos observar que la conversión que esperabamos de VULNSERVER al tomar 0xff y restarle 0x7f para tener 0x80 fue correcto.

Ahora que tenemos más espacio, podemos subcodificar valores. La codificación secundaria utiliza valores alfanuméricos e instrucciones SUB para colocar valores específicos que necesitamos en la pila.

El objetivo aquí es volver al principio del búfer para tener más de 3000 bytes para trabajar. Lo primero que debemos hacer es alinear la pila en nuestra área de búfer actual. Para hacer esto, aumentamos ESP en 0x1a48 para colocar ESP justo al final de nuestro búfer actual. Entonces, todo lo que empujemos a la pila se ejecutará. Para hacer esto, introducimos el valor de ESP en la pila, lo introducimos en EAX, lo ajustamos usando la codificación secundaria y luego introducimos el valor de EAX en la pila y lo introducimos en ESP. Ahora, nuestra pila se encuentra al final de nuestro segmento de búfer actual.

25 41 4d 4e 55          and    eax,0x554e4d41
25 35 32 31 2a          and    eax,0x2a313235
54                      push   esp
58                      pop    eax


2d 70 70 7c 7c          sub    eax,0x7c7c7070
2d 20 40 43 43          sub    eax,0x43434020
2d 28 35 40 40          sub    eax,0x40403528
50                       push   eax
5c                       pop    esp

Quedando los opcodes finales de la siguiente forma:

«\x25\x41\x4D\x4E\x55\x25\x35\x32\x31\x2A\x54\x58\x2D\x70\x70\x7C\x7C\x2D\x20\x40\x43\x43\x2D\x28\x35\x40\x40\x50\x5C»

Vamos a modificar nuestro exploit y veamos si se ejecutan exitosamente las instruciones dadas.

Genial, todo ha funcionado correctamente, ya tenemos apuntando nuestra pila, donde queremos.
Desde aquí, queremos saltar hacia atrás desde la ubicación de nuestra pila hasta el comienzo de nuestro búfer. Hacemos los cálculos y vemos que necesitamos retroceder 0xdb9, normalmente realizaríamos un salto cercano a FFFFF264, los códigos de operación se traducirían a E9 64F2FFFF debido a la restriccion de caracteres. Tendremos que escribir esto como dos instrucciones en la pila para tener en cuenta el número desigual de bytes, ya que solo podemos escribir 4 bytes a la vez. Debemos poner a cero el registro EAX antes de las instrucciones de subcodificación. Queremos subcodificar los valores 64F2FFFF y E9414141 y empujarlos a la pila en ese orden.

Si no saben como buscar los opcodes de un salto negativo como -0xdb9 pueden usar el assamble de immunity debugger y escribir por ejemplo jmp -0xdb9 y les aparecera algo asi.

Si no quieren encodear a mano, por que consideran que lo aprendieron o ya lo saben, les recomiendo este proyecto que es genial para usar codificación secundaria, llamado Slink, pueden ir a su proyecto en el siguiente enlace, mostraré el ejemplo de la codificación del salto negativo.

Armamos nuestro exploit y lo traceamos para ver si se cumple lo que hemos codificado.

Lo traceamos y obtenemos lo siguiente.

Ya estamos en el inicio de nuestro buffer y tenemos mucho espacio mas de 3000 bytes para cargar nuestra shellcode ahí, pero antes que nada, debemos alienar la pila y hacerla que apunte a nuestro inicio de shellcode por lo que haremos el mismo ejercicio.
para alinear la pila en mi caso, me he tirado una bolsonada y he restado 0xd80 de mi ESP, para no ir tan lejos, la vi fácil y me fui por ahí, pero no puedo colocar 0x80 por que VULNSERVER me lo restaría así que coloque 0xdff.

54                      push   esp
58                      pop    eax
66 2d ff 0d       sub    ax,0xdff
50                      push   eax
5c                      pop    esp

Genial ya tenemos la pila alineada y creo que es hora de usar metasploit para generar mi shellcode.


Antes de generarla debo comentarles que si usamos metasploit para generar una shellcode, así sea de tipo alphanumeric, siempre se va hacer uso de unas instrucciones que son caracteres malos para nuestro exploit, por suerte como tenemos apuntando ESP a nuestra shellcode podemos decirle a msfvenom que apunte a ese registro y ahí no usará las instrucciones con caracteres malos.

msfvenom -p windows/meterpreter/bind_tcp LPORT=4444 -f c EXITFUNC=seh BufferRegister=ESP -e x86/alpha_mixed

Finalmente nuestro exploit queda de la siguiente manera.

ejecutamos nuestro exploit, y vemos el resultado final…

CONCLUSIÓN

Finalmente hemos ejecutado código remoto sobre la aplicación, creo que el reto acá está en entender la codificación secundaria, luchar contra los caracteres malos y en alinear la pila, espero que hayan llegado conmigo hasta estas últimas palabras, este artículo estuvo un poco largo pero quizás muy completo, si te gusto el artículo, puedes compartirlo con tus amigos e invitarme un cafe desde aquí.

Agradezco a todos por seguir mis entradas y leer esto que comparto, abrazos.

happy hacking, Cracking and exploiting…
@sasaga92

Deja un comentario

Web construida con WordPress.com.

Subir ↑