Capítulo 1: Aprende el Arte de la Ingeniería Inversa Manuel Rey Vilar http://masteracsi.ual.es/ Prefacio Es increíble, y más bien desconcertante, la cantidad de software que ejecutamos sin saber a ciencia cierta lo que hace. Compramos el software situados en las estanterías envueltos en plástico transparente. Ejecutamos utilidades de configuración que instalan numerosos archivos, cambian la configuración del sistema, borran o desactivan las versiones anteriores, y modifican archivos críticos del registro. Cada vez que accedemos a un sitio Web, se puede invocar o interactuar con docenas de programas y segmentos de código que son necesarios para conseguir el aspecto y el comportamiento deseado. Compramos CDs con cientos de juegos y utilidades o los descargamos como shareware. Descargamos actualizaciones e instalamos parches, confiando en que los vendedores están seguro de que los cambios son correctos y completos. Confiamos ciegamente que los últimos cambios aplicados al programa mantiene la compatibilidad con todo el resto de los programas en nuestro sistema. En definitiva confiamos en software que no entendemos y no conocemos del todo bien. La realidad es que el Software de hoy en día se ha vuelto tan complejo e interconectado que el desarrollador a menudo no conoce todas las características y repercusiones de lo que ha sido creado en una aplicación. Con frecuencia es demasiado caro y consume mucho tiempo probar todas las rutas de control de un programa y todos los grupos de opciones de usuario. Bajo este escenario aparece la ingeniería inversa como un conjunto de técnicas y herramientas para la comprensión de lo que realmente representa el software. Esto nos permite visualizar la estructura del software, sus modos de funcionamiento y las características que impulsan su comportamiento. Las técnicas de análisis y la aplicación de herramientas automatizadas para examinar el software, nos dan una forma razonable de ver y comprender la complejidad del software y para descubrir su verdad. http://masteracsi.ual.es/ Tanto la memoria de este trabajo como el software desarrollado se distribuyen bajo la licencia GNU GPL v3. La Licencia Pública General GNU (GNU GPL) es una licencia libre, sin derechos para software y otro tipo de trabajos. Las licencias para la mayoría del software y otros trabajos prácticos están destinadas a suprimir la libertad de compartir y modificar esos trabajos. Por el contrario, la Licencia Pública General GNU persigue garantizar su libertad para compartir y modificar todas las versiones de un programa--y asegurar que permanecerá como software libre para todos sus usuarios. Cuando hablamos de software libre, nos referimos a libertad, no a precio. Las Licencias Públicas Generales están destinadas a garantizar la libertad de distribuir copias de software libre (y cobrar por ello si quiere), a recibir el código fuente o poder conseguirlo si así lo desea, a modificar el software o usar parte del mismo en nuevos programas libres, y a saber que puede hacer estas cosas. Para obtener más información sobre las licencias y sus términos puede consultar: • http://www.gnu.org/licenses/gpl.html (Licencia original en inglés) • http://www.viti.es/gnu/licenses/gpl.html (Traducción de la licencia al castellano) ÍNDICE CAPÍTULO 1 LENGUAJE ENSAMBLADOR.......................................................................... CAPÍTULO 2 ARQUITECTURA X86 ...................................................................................... 2.1. La Pila ................................................................................................................................ 2.2. Los Registros ...................................................................................................................... 2.2.1. Generales..................................................................................................................... 2.2.2. De Base ....................................................................................................................... 2.2.3. De Indice ..................................................................................................................... 2.2.4. De Puntero .................................................................................................................. 2.2.5. De Segmento ............................................................................................................... 2.2.6. Flags ............................................................................................................................ 2.3. Las Instrucciones ................................................................................................................ 2.3.1. Instrucciones de la pila ............................................................................................... 2.3.2. Instrucciones de transferencia de datos ...................................................................... 2.3.3. Instrucciones aritméticas ............................................................................................ 2.3.4. Instrucciones lógicas ................................................................................................... 2.3.5. Instrucciones de comprobación y verificación ........................................................... 2.3.6. Instrucciones de salto .................................................................................................. 2.3.7. Instrucciones de subrutinas ......................................................................................... 2.3.8. Instrucciones de bucle................................................................................................. 2.3.9. Instrucciones de cadenas ............................................................................................. 2.3.10 . Instrucciones de Entrada / Salida .............................................................................. 2.3.11. Instrucciones de rotación y desplazamiento .............................................................. 2.3.12 . Instrucciones de conversión ...................................................................................... 2.3.13. Instrucciones de flags ................................................................................................ 2.3.14. Instrucciones de interrupción .................................................................................... 2.3.15. Instrucciones del procesador ..................................................................................... CAPÍTULO 3 INTRODUCCIÓN A LA INGENIERIA INVERSA ........................................ 3.1. ¿Qué es la Ingenieria Inversa? ........................................................................................... 3.2. Aplicaciones de la Ingeniería Inversa ................................................................................ 3.3. Conocimientos previos necesarios ..................................................................................... 3.4. Herramientas utilizadas en Ingenieria Inversa ................................................................... 3.4.1. Desensambladores ...................................................................................................... 3.4.2. Depuradores ................................................................................................................ 3.4.3. Editores Hexadecimales .............................................................................................. 3.4.4. PE y Editores de recursos ........................................................................................... 3.4.5. Herramientas de monitorización del sistema .............................................................. 3.4.6. Herramientas e información misceláneos ................................................................... CAPÍTULO 4 INTRODUCCIÓN A OLLYDBG ..................................................................... 4.1. ¿Qué es Ollydbg? ............................................................................................................... 4.2. Visión general .................................................................................................................... 4.2.1.Desensamblador ........................................................................................................... 4.2.2.Registros ...................................................................................................................... 4.2.3.La Pila (I) ..................................................................................................................... 4.2.4.Dump............................................................................................................................ 4.2.5.La barra de herramientas .............................................................................................. 4.2.6.El menú contextual ...................................................................................................... CAPÍTULO 5 OLLYDBG (I) .................................................................................................... 5.1. Cargando una aplicación .................................................................................................... 5.2. Ejecutando una aplicación .................................................................................................. 5.3. Ejecutando paso a paso ...................................................................................................... 5.4. Puntos de interrupción (Breakpoints) .................................................................................. 5.4.1.Software Breakpoints ................................................................................................... 5.4.2.Hardware Breakpoints ................................................................................................. 5.4.3.Memory Breakpoints ................................................................................................... 5.5. Utilizando el panel Dump .................................................................................................... CAPÍTULO 6 OLLYDBG (II) ................................................................................................... 6.1. ¿Qué son los DLL’s? .......................................................................................................... 6.2. ¿Cómo se usan los DLL’s? ................................................................................................ 6.3. La tabla de saltos ................................................................................................................ 6.4. Saltando dentro y fuera de los DLL’s ................................................................................ 6.5. La Pila (II) .......................................................................................................................... 6.6. Mostrando argumentos y variables locales ........................................................................ 6.7. Ollydbg Cheatsheet ............................................................................................................ CAPÍTULO 7 EJERCICIOS RESUELTOS ............................................................................ 7.1. Caso práctico 1: Buscando cadenas de texto ...................................................................... 7.2. Caso práctico 2: Parches .................................................................................................... 7.3. Caso práctico 3: Repasando conceptos .............................................................................. 7.4. Caso práctico 4: Resource Hacker ..................................................................................... 7.5. Caso práctico 5: Marco de Referencias .............................................................................. 7.6. Caso práctico 6: Intermodular Calls ................................................................................... 7.7. Caso práctico 7: Niveles de parcheo .................................................................................. 7.8. Caso práctico 8: Introducción al Nivel 2 (Noob) ............................................................... 7.9. Caso práctico 9: Ejemplo de Noob Avanzado ................................................................... 7.10. Caso práctico 10: Crackeando un programa real ............................................................... 7.11. Caso práctico 11: NAGS .................................................................................................... 7.11.1 Nag1.exe.................................................................................................................. 7.11.2 Nag2.exe.................................................................................................................. 7.12. Caso práctico 12: Usando el Call Stack ............................................................................. 7.13. Caso práctico 13: Los mensajes de las ventanas ................................................................ 7.14. Caso práctico 14: Auto-modificación del código............................................................... 7.15. Caso práctico 15: Fuerza bruta........................................................................................... 7.16. Caso práctico 16: Los binarios de Delphi .......................................................................... 7.16.1 DelphiCrackme.exe ................................................................................................. 7.16.2 exif2htm.exe ............................................................................................................ 7.17. Caso práctico 17: Periodos de prueba y Hardware Breakpoints ........................................ http://masteracsi.ual.es/ 7.18. Caso práctico 18: Generador de parches ............................................................................ 7.19. Caso práctico 19: Trabajando con binarios de Visual Basic (I) ......................................... 7.20. Caso práctico 20: Trabajando con binarios de Visual Basic (II) ....................................... 7.21. Caso práctico 21: Técnicas anti-depurador (anti-debugging) ............................................ CAPÍTULO 8 EJERCICIOS COMPLEMENTARIOS .......................................................... 8.1. Otra forma de poner un parche ............................................................................................ 8.2. Bypasear un archivo de claves ............................................................................................ 8.3. Bypasear un serial en Delphi ............................................................................................... 8.4. Cracking Driverfinder ......................................................................................................... 8.5. Desembalaje rápido de PECompact ................................................................................... 8.6. Crackme .NET ................................................................................................................... 8.7. Multi-Parche ....................................................................................................................... ANEXO I SISTEMAS DE NUMERACIÓN ............................................................................... I.I. Decimal ....................................................................................................................... I.II. Binario ........................................................................................................................ I.III Hexadecimal ............................................................................................................... I.IV. Octal............................................................................................................................ I.V. Conversión .................................................................................................................. I.VI. Identificación .............................................................................................................. ANEXO II SISTEMAS DE REPRESENTACIÓN .................................................................... II.I. Números negativos ..................................................................................................... II.II Coma (o punto) Flotante ............................................................................................. II.III. Formato BCD………..……………….…………………………………………… II.IV. Carateres ASCII - ANSI ............................................................................................. ANEXO III OPERACIONES LÓGICAS ................................................................................... III.I. And ............................................................................................................................. III.II. Or ................................................................................................................................ III.III. Xor .............................................................................................................................. III.IV.Not .............................................................................................................................. http://masteracsi.ual.es/ Capítulo 1 LENGUAJE ENSAMBLADOR Se define como un lenguaje de programación que se usa para dar directamente órdenes al ordenador. A diferencia de otros lenguajes, que usan el sistema operativo como intermediario para ejecutar las tareas (le dicen al sistema operativo que haga una cosa y este es quien se encarga de hacérselo saber al ordenador), el lenguaje de ensamblador (en inglés assembly) no usa intermediarios, sino que directamente le da las órdenes a la máquina. Evidentemente este lenguaje tiene varias ventajas e inconvenientes. Entre las ventajas tenemos que por supuesto, es más rápido y eficiente, más estable y requiere menos recursos. Las desventajas son sin embargo mucho mayores: para empezar está limitado a las órdenes que el ordenador traiga memorizadas en su placa base, nada más. Y requiere unos conocimientos técnicos muy avanzados, toda vez que cada CPU incluye órdenes distintas e incluso formas distintas de darle esas órdenes, variando según el modelo, el fabricante... etc... Es por ello, entre otras cosas, que no se ha impuesto en el mercado como lenguaje de programación para aplicaciones o juegos. Como se ve es un lenguaje de programación orientado a profesionales que trabajan con hardware, muy útil sobre todo para detectar fallos e incompatibilidades entre piezas del PC o chequear el estado de estas. Como ya dijimos el lenguaje ensamblador debe ser traducido a código máquina para funcionar, y por tanto requiere un ensamblador que lo traduzca a código binario (a ceros y unos). Pero es el lenguaje más cercano al propio código que usan los ordenadores. Es por ello que se dice que es un lenguaje de bajo nivel, debido a que está sólo un escalón por encima del código máquina, y solo permite ejecutar instrucciones sencillas. Los lenguajes de alto nivel son más elaborados y permiten realizar tareas múltiples y complejas con una sola orden, mientras que en el que nos ocupa una orden equivale a una instrucción directa. Existen como hemos visto muchas variantes del lenguaje ensamblador, de hecho una por cada tipo de arquitectura del CPU. Las primeras CPUs apenas tenían instrucciones y por tanto eran mucho más sencillas. En la actualidad están en boga los llamados ensambladores de alto nivel, que permiten instrucciones más complejas e incluso cadenas de instrucciones (macros). http://masteracsi.ual.es/
Description: