Cómo analizar código para escribir exploit

Crear un exploit se trata de controlar el flujo de ejecución de un programa. Esto se puede hacer manipulando los valores de las variables en el programa. Idealmente, un exploit ejecutaría sus propias instrucciones en el contexto del programa.

Entonces, ¿cómo se obtienen nuevas instrucciones para ejecutar en un programa? Primero, esas instrucciones deben estar en la memoria del programa explotado. Luego, el puntero de instrucciones (EIP en sistemas x86) debe apuntar a la ubicación de memoria de esas instrucciones. Además, la página de memoria en la que residen esas instrucciones debe tener permisos de ejecución (sin DEP).

Para que todo esto suceda, debe encontrar un lugar en el código que le permita manipular el puntero de instrucciones. Esto podría ser a través de medios legítimos o manipulaciones de cómo funciona el sistema subyacente (por ejemplo, desbordamientos de búfer basados ​​en pila).

Usted preguntó sobre el análisis de “código”, que estoy interpretando como código fuente o código binario. Tener el código fuente es definitivamente útil. Aunque algunos ingenieros inversos en realidad preferirían trabajar con el código binario, ya que en última instancia es lo que se explotará (vea el libro Inversión: secretos de ingenieros inversos). Tampoco tiene las restricciones del lenguaje de nivel superior.

Por lo tanto, necesita una comprensión profunda de cómo se ejecutan las instrucciones y luego cuestionar cada suposición que un programa está haciendo para ver que hay una forma de manipular las variables y los registros de la CPU que harán que el puntero de instrucciones vaya a algún lugar ventajoso para usted.

A2A

Tienes que entender el lenguaje a fondo, ya que no solo puedes leerlo sino saber cómo funciona bajo el capó. De esa manera, puede reconocer cuándo una implementación de código particular es insegura en comparación con una forma diferente. Por ejemplo, al ver que una llamada particular al SO no está validada, el SO ejecutará el comando tal cual en lugar de escapar automáticamente del comando para evitar un ataque.

Esto también ayuda cuando se trata de analizar los resultados del código. ¿La salida hace lo que esperaba que hiciera? Si no, ¿por qué? Saber esto le dirá cómo el sistema operativo maneja ciertas configuraciones de código y comandos. Con ese conocimiento, obtienes una comprensión de lo que sucederá cuando se den ciertos comandos; esto le ayuda a anticipar cómo funcionará el sistema operativo y, en última instancia, qué lo hará fallar.

Una vez que un sistema operativo falla, se encuentra en un estado inestable y, por lo tanto, es más probable que sea explotado de una manera que pueda controlar.

Si está preguntando sobre técnicas y trucos específicos, lo siento; El siguiente es solo un resumen de alto nivel:

  1. Tener una idea de lo que hace el código y cómo.
  2. Tenga una idea de las formas en que podría estar defectuoso / roto.
  3. Escriba las reglas apropiadas de fuzzer y déjelo correr (prueba de Fuzz).
  4. Use WinDBG o algo para analizar volcados de memoria del fuzzer.
  5. Intente averiguar cuáles son explotables, observando lo que la aplicación está haciendo para la entrada “incorrecta” en un depurador en vivo (por ejemplo, OllyDBG).

La versión “lucky noob”:

  1. Ingrese un grupo de “A” s.
  2. Observe el bloqueo de la aplicación con un fallo de segmentación, porque no hay instrucciones en la dirección 41414141 (sugerencia: 41 hex = A).
  3. Genere un patrón (había una herramienta para esto en el marco de Metasploit) y utilícelo en lugar de las “A”.
  4. Use el nuevo contenido del puntero de instrucciones para encontrar el desplazamiento en el patrón. Aquí es donde controlas la IP.

La última versión no debería suceder en ningún software semi-moderno, medio decente, pero quién sabe 🙂

Solo puede hacerlo con código de código abierto, pero hay herramientas.