POC – Badchar, método alternativo

¿Qué es un badchar?

Los badchars o caracteres inválidos o “malos” son caracteres que recibe el programa objetivo, y este los filtra y actúan como delimitadores o, mediante sus algoritmos internos, los elimina o los sustituye por otros valores, haciendo inservible nuestra shellcode.

La búsqueda de badchars es una parte crucial en la metodología de la creación de exploits, ya que, si estos no son localizados y evitados durante la generación del payload, lo convierten en inservible ya que este no se interpretaría correctamente en el sistema objetivo.

Veremos de una manera más gráfica la explicación en la parte del post de la generación del payload para el programa objetivo.

El método “Manual” alternativo

En este caso, tras ver la forma de localizarlos de una manera más automatizada con scripts en el post de mi mentor Carlos, este método que presento es una alternativa, siendo este más manual y artesanal, ya que es interpretando nosotros la búsqueda de esos caracteres. Este método, es casi infalible, es decir, está basado en la interpretación humana, no dependemos de scripts u otras herramientas que dado el caso puedan fallar por alguna razón, o no dispongamos de ellas. También señalar que es una manera de comprender como funcionan los scripts para la búsqueda de los badchars.

Explicación del método

Nos basamos en el uso de un payload que se compone de un pattern especial, solo que en lugar de ser como otros pattern completos que van desde 0x00 a 0Xff, esta reordenado en bloques de 4 Bytes para que al representarlo en el stack sea “legible” de izquierda a derecha (por lo general los sistemas objetivos usan el formato Little Endian, y los valores se escriben de derecha a izquierda), pudiendo así averiguar que valores faltan, están sustituidos o se corta el payload. ¿fácil no? Quedaría así el payload (está excluido el valor 0x00):

Si nos fijamos, el payload esta reordenado en bloques de 4Bytes, y es recomendable evitar los valores 0x00, 0x0A,0XFF (Por lo general son valores inválidos, es mejor evitarlos de primeras). Si usamos este payload en un script podremos ver su representación en el stack pudiendo leer los valores en una sucesión de izquierda a derecha y ver qué valor es el no concordante o ausente, con lo que sabremos que valores no son admitidos por el programa objetivo.

POC – Easy RM to MP3 Converter

Objetivo: Easy RM to mp3 converter v2.7.3.700 en Windows XP SP2

Herramientas: Immunity Debugger, mona.py, Sublime Text 3

Vamos a utilizar este programa para probar nuestro método. Lo más importante es ser organizado y llevar todo bien estructurado. En un lado pondremos nuestro payload y en otro tendremos nuestro esquema del POC y el programa y debugger “Immunity debugger” con el software  Easy RM to mp3 cargado.

Ilustración de payload cargado

No me centraré en la búsqueda del valor y la distancia a para sobrescribir EIP ya que en esta entrada nos basamos en la búsqueda de los badchars.

Según los cálculos obtenidos con mona.py, para sobrescribir el valor de EIP debo de enviar un buffer de 26066. Previamente escribimos el esqueleto del script para ordenar los valores que recibirá el stack. Podemos usar como ejemplo el script de la imagen, el cual creará un archivo .m3u en el contendrá nuestro POC.

Ilustración ejemplo de como se ordena la pila “Stack”

Inmunity y script de Python

Ahora toca modificar nuestro payload, para añadir los valores hexadecimales ordenados en bloques de 4 Bytes, para que se nos muestre en la vista del Stack del Inmunity Debugger. Reordenaremos el script de la siguiente manera:

 

Ilustración Pila “Stack”

Stack tras el envío del buffer

Si nos fijamos en la imagen, vemos que el padding es correcto ya que ESP (línea azul gruesa), está apuntando al inicio del payload (los 8 bytes con el carácter 9) y continua con nuestra secuencia del payload. Como vemos el payload empieza bien, contabilizando de 0x01 a 0x08 pero en el siguiente bloque vemos que la secuencia se corta. Si nos fijamos faltaría el 0x09 y el 0x0a y después continua el 0x0b y 0x0c y a partir de ahí se corta. ¿y esto que quiere decir?

Pues que hemos topado con un carácter invalido, el cual corta la secuencia y no continúa leyendo el payload. Para identificarlo tenemos que recordar que la “lectura” es en formato Little endian, con lo que el stack se va llenando de derecha a izquierda con nuestro buffer:

Diagrama del stack una vez llenado

En este esquema vemos como el programa va leyendo el buffer, y este va cargando los caracteres en el stack. Como vemos lee el primero el 0x0c y el programa lo pone en el stack (a la derecha por el formato Little endian), y a continuación le sigue con 0x0b, pero cuando llega a 0x0a se corta, ya no lo agrega al stack, y como vemos corta el flujo y no continua tras ese carácter con lo que finaliza la lectura del buffer. Como vemos en este ejemplo, el carácter 0x0a es un badchar, y provoca un corte en el flujo de la lectura del buffer, con lo que deberemos obviarlo en el payload. Se puede dar el caso de sustitución, con lo que veríamos que el valor del buffer no concuerda con el valor almacenado en el stack:

Ejemplo de sustitución de badchars

Si copiamos el payload en otro documento, pero en este caso ordenado que es como seria la representación final del stack, nos fijamos que a partir del carácter 0x0a solo hay 0x00, que son como un relleno del stack que hace el programa objetivo, y a partir de ahí nuestro pre_buffer:

Ilustración envío de badchars

Tras este punto, solo nos queda sustituir el badchar 0x0a por otro valor o excluirlo del payload. Para no romper la estructura de ordenado del payload, sustituiremos el badchar por 0x99 que sabemos que es un valor válido y buscaremos el siguiente badchar. Modificamos la variable payload de nuestro script:

 

Ejecutamos y vemos el la alineación de la pila de la siguiente manera:

Ilustración de pila alineada

Stack tras excluir 0x0A

Si nos fijamos el payload continua la serie, y donde tenía que estar el valor 0x0A está el 0x99 como habíamos puesto en nuestro payload, con lo cual deducimos que 0x0A es un badchar, y tenemos que excluirlo del payload final. Seguimos buscando más badchars:

Ilustración de la pila con el payload ejecutado

Stack completo tras sustituir el badchar 0x0A

Como vemos en la imagen anterior, no hay mas cortes en el payload (vemos el fin del payload) y tampoco sustituciones (el pattern esta completo). Ahora solo nos queda crear un shellcode con msfvenom e incluirlo en nuestra POC, y sobrescribir EIP con una dirección a un JMP ESP o CALL ESP, pero eso lo veremos con más detenimiento.

Notas finales y script

Como todo es posible automatizar el proceso de búsqueda manual con scripts que generen el pattern. Os comparto el mío en Python (algo burdo pero funcional), añadiendo funciones como la de especificar badchars para generar de nuevo el patrón sin ellos, crear un padding de nops y un trailer de principio y final de payload. Toda sugerencia es bienvenida:

 

Contribución y Autor : Miguel Cobas Barcala

Guardar

Guardar

Guardar

Guardar

Guardar

Guardar

Guardar

Guardar

Menú