Ingeniería Inversa/Desensambladores
Esta página discutirá técnicas y software para desensamblar. Todo el software enumerado debería incluir un sitio de descarga (si es freeware/Código Abierto) o una homepage (si es de pago). No limitaremos este wikilibro solamente a herramientas libres, aunque pueden ser las mas populares para empezar con la ingeniería inversa. Si la lista de desensambladores se hace demasiado larga, puede ser movida al apéndice.
En próximas secciones, se cubrirá el proceso de desensamblaje, y una discusión mas profunda sobre desensambladores.
¿Qué es un desensamblador?
editarPara más información, véase el artículo «Desensamblador» en Wikipedia. |
Esencialmente, un desensamblador es exactamente lo contrario de un ensamblador. Tal como un ensamblador convierte código escrito en ensamblador en código máquina binario, un desensamblador invierte el proceso e intenta recrear el código en ensamblador partiendo del código máquina binario.
Dado que la mayoría de los lenguajes ensambladores tienen una correspondencia uno a uno con instrucciones máquina subyacentes, el proceso de desensamblado es relativamente sencillo, y un desensamblador básico puede a menudo ser implementado simplemente leyendo bytes, y efectuando una búsqueda en una tabla. Por supuesto, desensamblar tiene sus propios problemas y escollos, que serán cubiertos mas adelante en este capítulo.
Muchos desensambladores tienen la opción de producir instrucciones en lenguaje ensamblador usando la sintaxis de Intel, AT&T, u (ocasionalmente) HLA.
x86 Disassemblers
editarDesensambladores para Windows
editarPor conveniencia, separaremos lo desensambladores Windows en 2 categorias: Herramientas Comerciales (que cuestan dinero), y Herramientas Gratuitas (que son gratis y/o libres).
Herramientas Comerciales
editar- IDA Pro
- es un desensamblador profesional (léase: caro) extremadamente potente. La parte mala es su elevado precio. Por lo tanto, y aunque ciertamente merece su precio, este wikibook no considera IDA Pro específicamente porque su precio es exclusivista. Dos versiones gratuitas existen; mira abajo.
- PE Explorer
- es un desensamblador que "se centra en facilidad de uso, claridad y navegación". No es tan completo como IDA Pro, pero tiene un precio mas bajo.
- W32DASM
- W32DASM es un excelente desensamblador 16/32 bit para Windows.
Herramientas Gratuitas
editar- IDA 3.7
- Esta es una herramienta para DOS con GUI parecida a IDA Pro, pero considerablemente mas limitada. Puede desensamblar código para procesadores Z80, 6502, Intel 8051, Intel i860, y PDP-11, así como instrucciones x86 hasta el 486.
- IDA Pro Freeware 4.1
- Se comporta casi como IDA Pro, pero solo desensambla código para procesadores Intel x86, y solo funcions en Windows. Puede desensamblar instrucciones para aquellos procesadores disponibles a fecha de 2003.
- IDA Pro Freeware 4.3
- Mejor interfaz gráfico que la versión previa.
- BORG Disassembler
- BORG es un excelente desensamblador con interfaz gráfico para Win32.
- HT Editor
- Un desensamblador analizador para instrucciones x86. La última versión corre como un programa de interfaz gráfico de consola en Windows, pero hay versiones compiladas para Linux también.
- diStorm64
- diStorm es una librería de desensamblador de stream altamente optimizada para 80x86 y AMD64.
Desensambladores para Linux
editar- Bastard Disassembler
- Bastard es un potente y programable desensamblador para Linux y FreeBSD.
- ciasdis
- El nombre oficial de ciasdis es computer_intelligence_assembler_disassembler. Esta herramienta basada en Forth permite construir conocimiento sobre un cuerpo de código de manera interactiva e incremental. Es único en que todo el código desensamblado puede ser re-ensamblado exactamente al mismo código. Soporta 8080, 6809, 8086, 80386, Pentium I y DEC Alpha. Facilidades de scripting ayudan en al análisis de cabeceras de fichero Elf y MSDOS y hacen esta herramienta extensible. ciadsis para Pentium I está disponible como imagen binaria, las otras están en código fuente, cargables sobre lina Forth, disponible del mismo sitio.
- objdump
- viene de manera estándar, y es típicamente usada para inspección genérica de ficheros binarios. Presta atención a las opciones de relocation y dynamic symbol table.
- gdb
- viene de manera estándar, como depurador, pero es usado muy a menudo para desensamblar. Si tienes un bloque arbitrario de datos en hexadecimal que quieres desensamblar, simplemente introdúcelo (interactivamente) o compílalo en un programa como una cadena de texto así: char foo[] = {0x90, 0xcd, 0x80, 0x90, 0xcc, 0xf1, 0x90};
- lida linux interactive disassembler
- un desensamblador interactivo con algunas funciones especiales como un criptoanalizador. Muestra referencias a cadenas, hace análisis de flujo de código, y no depende de objdump. Usa la librería de desensamblage Bastard para descodificar instrucciones individuales.
- ldasm
- LDasm (Linux Disassembler) es un interfaz gráfico basado en Perl/Tk para objdump/binutils que intenta imitar el aspecto de W32Dasm. Busca referencias cruzadas (por ejemplo cadenas), convierte el código de GAS a un estilo parecido a MASM, traza programas y mucho mas. Viene con PTrace, un logger para flujo de procesos.
Desensambladores para no-x86
editar- ciasdis
- EL nombre oficial de ciasdis es computer_intelligence_assembler_disassembler. Esta herramienta basada en Forth permite construir conocimiento sobre un cuerpo de código de manera interactiva e incremental. Es único en que todo el código desensamblado puede ser re-ensamblado al mismo código exactamente. Soporta procesadores 8080, 6809, 8086, 80386, Pentium I y DEC Alpha. Facilidades de scripting ayudan en al análisis de cabeceras de fichero Elf y MSDOS y hacen esta herramienta extensible. Los desensambladores y ensambladores para no-Pentium solo están disponibles como código fuente, cargables sobre lina Forth, que está también disponible en el mismo sitio. Tendrás que estudiar el capítulo sobre ensamblador en el manual de lina, entonces puedes ser capaz de añadir un nuevo procesador.
Mac OS X
editar- gdb
- viene de manera estándar, como depurador, pero es usado muy a menudo para desensamblar. Si tienes un bloque de datos hexadecimales para desensamblar, introdúcelo (interactivamente) encima de otra cosa o compílalo en un programa como cadena de esta manera: char foo[] = {0x90, 0xcd, 0x80, 0x90, 0xcc, 0xf1, 0x90};
- Machonist
- Machonist es realmente más que un potente desensamblador. Contiene funciones para ejecutar el programa bajo GDB, grabar y cargar parches, añadir comentarios a un desensamblaje, parchear, hacer el de-mangling de los nombres de funciones C++, y mucho más. Es una aplicación con interfaz gráfica, así que los usuarios nuevos encontrarán más fácil acostumbrarse.
- otool
- otool es un analizador binario muy potente que contiene funciones para desensamblar el código de ejecutables.
- --I think it comes as part of the Apple Developer Tools, but I'm not sure. Sorry. --Macpunk 21:36, 7 January 2007 (UTC)
- ndisasm
- Desensamblador simple para x86, que simplemente desensambla un fichero binario sin conocimiento del formato objeto. Útil para desensamblar binarios de otras plataformas. Viene estándar con las Apple Developer Tools.
Problemas del desensamblador
editarSeparación de código y datos
editarPuesto que tanto instrucciones como datos están almacenados como datos binarios en un fichero ejecutable, una pregunta surge espontáneamente: ¿Como puede un desensamblador separar código de datos? ¿Es un byte en particular una variable, o parte de una instrucción?
El problema no sería tan difícil si los datos se limitaran a la sección .data del ejecutable (explicado en un capítulo posterior) y si el código ejecutable estuviese limitado también a la sección .code del ejecutable, pero a menudo este no es el caso. Los datos pueden estar insertados directamente en la sección de código (por ejemplo, las tablas de direcciones de salto), y código ejecutable puede estar almacenado en la sección de datos ( aunque sistemas nuevos evitarán esto por razones de seguridad).
Muchos desensambladores interactivos ofrecerán al usuario la opción de mostrar segmentos de código como código o datos, pero los desensambladores no interactivos harán esta separación automáticamente. Los desensambladores suelen proveer en la misma línea la instrucción y sus correspondientes datos en hexadecimal, para reducir la necesidad de hacer decisiones sobre la naturaleza del código. Algunos desensambladores (por ejemplo, ciasdis) te permiten especificar reglas sobre si desensamblar como datos o código e inventar nombres para la etiquetas, basándose en el contenido del objeto bajo escrutinio. Scriptaer tu propio "crawler" de esta manera es más eficiente; para programas grandes el desensamblaje interactivo puede ser difícil hasta el punto de no ser practicable.
El problema general de separar datos de código en ejecutables arbitrarios es equivalente al Halting Problem. Como consecuencia, no es posible escribir un desensamblador que separe correctamente datos de código para todos los programas de input. La ingeniería Inversa está llena de tales limitaciones teóricas, aunque por el teorema de Rice ( Rice's theorem ) todas las preguntas interesantes sobre propiedades de los programas son indecidibles (así que los compiladores y muchas otras herramientas que tratan con programas en cualquier manera también se encuentran con tales límites). En la práctica una combinación de análisis automático e interactivo con perseverancia puede manejar todos los programas excepto aquellos específicamente diseñados para frustrar la ingeniería inversa, como el uso de encriptación o el desencriptado de código justo antes de usarse, y mover código de un lado a otro en memoria.
Lost Information
editarMucha información se pierde al compilar el programa. Típicamente, para C-code los nombre de p.e. variables locales son perdidas irremediablemente. Los nombres de funciones, variables pueden estar presente en una imagen, sobre todo si se ha compilado con la opción de depuración, pero estas tablas de símbolos pueden ser eliminados por un proceso llamado stripping. An optimizing compiler may render C language constructs unrecognizable. Comments in the code are all discarded by the compiler. It will not be possible to determine the difference between code that was written in-place, code that was written as an inline function, and code that was written as a C-preprocessor macro. In many cases it will not be possible to determine lexicographical scope of functions or variables. If two files are compiled and linked together, file1.c and file2.c, the delineation between source files will disappear during the linking stage.
Questions
editarQuestion 1: Write a simple "Hello world!" (see K&R, chapt 1) program in any compiled language of your choice. Compile this code, and disassemble the resulting executable. Is the resulting assembly code longer or shorter than your original code?
Answers to Questions
editarAnswer 1: The disassembly code will be larger, much larger. My original code--written in C--was about 6 lines long. The resulting disassembly was over 20,000. This phenomenon will be discussed in later chapters about executable file structures.
Further reading
editar- Kernighan and Ritchie, "The C Programming Language", 2nd Edition, 1988, Prentice Hall.