Un desensamblador es un programa informático que traduce el lenguaje de máquina al lenguaje ensamblador , la operación inversa a la de un ensamblador . El desensamblado, la salida de un desensamblador, a menudo está formateado para que sea legible por humanos en lugar de ser adecuado para la entrada a un ensamblador, lo que lo convierte principalmente en una herramienta de ingeniería inversa . Los usos comunes de los desensambladores incluyen el análisis de la salida de los compiladores de lenguajes de programación de alto nivel y sus optimizaciones, la recuperación del código fuente de un programa cuya fuente original se perdió, el análisis de malware , la modificación de software (como el pirateo de ROM ) y el descifrado de software .
Un desensamblador se diferencia de un descompilador en que su objetivo es un lenguaje de alto nivel en lugar de un lenguaje ensamblador.
El código fuente del lenguaje ensamblador generalmente permite el uso de constantes y comentarios del programador . Por lo general , el ensamblador los elimina del código de máquina ensamblado. Si es así, un desensamblador que opere en el código de máquina produciría un desensamblado que carece de estas constantes y comentarios; la salida desensamblada se vuelve más difícil de interpretar para un humano que el código fuente original anotado. Algunos desensambladores proporcionan una función de comentarios de código incorporada donde la salida generada se enriquece con comentarios sobre las funciones API llamadas o los parámetros de las funciones llamadas. Algunos desensambladores hacen uso de la información de depuración simbólica presente en archivos de objetos como ELF . Por ejemplo, IDA permite al usuario humano crear símbolos mnemotécnicos para valores o regiones de código en una sesión interactiva: el conocimiento humano aplicado al proceso de desmontaje a menudo es paralelo a la creatividad humana en el proceso de escritura del código.
Es posible escribir un desensamblador que produzca código que, cuando se ensambla, produzca exactamente el binario original; sin embargo, a menudo existen diferencias. Esto plantea exigencias a la expresividad del ensamblador. Por ejemplo, un ensamblador x86 elige arbitrariamente entre dos códigos binarios para algo tan simple como . Si el código original utiliza la otra opción, el código original simplemente no se puede reproducir en ningún momento dado. Sin embargo, incluso cuando se produce un desmontaje totalmente correcto, persisten problemas si el programa requiere modificación. Por ejemplo, la misma instrucción de salto en lenguaje de máquina puede generarse mediante código ensamblador para saltar a una ubicación específica (por ejemplo, para ejecutar un código específico) o para saltar un número específico de bytes (por ejemplo, para saltar una rama no deseada). . Un desensamblador no puede saber lo que se pretende y puede usar cualquiera de las dos sintaxis para generar un desensamblado que reproduzca el binario original. Sin embargo, si un programador desea agregar instrucciones entre la instrucción de salto y su destino, es necesario comprender la operación del programa para determinar si el salto debe ser absoluto o relativo, es decir, si su destino debe permanecer en una ubicación fija o ser movido para omitir las instrucciones originales y agregadas.MOV AX,BX
Otro desafío es que no siempre es posible identificar qué partes del binario corresponden al código ejecutable y cuáles a los datos. Mientras que los formatos ejecutables comunes como ELF y PE dividen el binario en secciones ejecutables y de datos, otros formatos como los binarios planos no lo hacen, por lo que cualquier ubicación determinada en el binario puede contener instrucciones ejecutables o datos no ejecutables, lo que dificulta decidir si debe desmontarse como instrucciones o dejarse como datos. Dado que las CPU generalmente permiten saltos dinámicos calculados en tiempo de ejecución, no siempre es posible identificar todas las ubicaciones posibles en el binario a las que se puede saltar y, por lo tanto, contener instrucciones.
En arquitecturas de computadora con instrucciones de ancho variable , como en muchas arquitecturas de computadora con conjunto de instrucciones complejas (CISC) , puede ser válido más de un desmontaje.
Los desensambladores no manejan código que varía durante la ejecución.
El cifrado se puede utilizar en algunos programas informáticos, particularmente como parte de la gestión de derechos digitales para frustrar la ingeniería inversa y el craqueo . Esto plantea un desafío adicional al desensamblaje, ya que el código debe descifrarse antes de ser desensamblado.
Un desensamblador puede ser independiente o interactivo. Un desensamblador independiente, cuando se ejecuta, genera un archivo en lenguaje ensamblador que puede examinarse; uno interactivo muestra el efecto de cualquier cambio que el usuario realice de forma inmediata. Por ejemplo, es posible que el desensamblador inicialmente no sepa que una sección del programa es en realidad código y la trate como datos; si el usuario especifica que es código, el código desensamblado resultante se muestra inmediatamente, lo que le permite examinarlo y tomar medidas adicionales durante la misma ejecución.
Cualquier depurador interactivo incluirá alguna forma de ver el desmontaje del programa que se está depurando. A menudo, la misma herramienta de desmontaje se empaquetará como un desensamblador independiente distribuido junto con el depurador. Por ejemplo, objdump , parte de GNU Binutils , está relacionado con el depurador interactivo gdb . [1]
Se puede incorporar un desensamblador dinámico en la salida de un emulador o hipervisor para "rastrear", línea por línea, la ejecución en tiempo real de cualquier instrucción de máquina ejecutada. En este caso, además de las líneas que contienen el código de máquina desensamblado, se pueden mostrar los registros y/o cambios de datos (o cualquier otro cambio de " estado ", como códigos de condición) que cada instrucción individual provoca. al lado o debajo de la instrucción desmontada. Esto proporciona información de depuración extremadamente poderosa para la resolución definitiva del problema, aunque el tamaño del resultado resultante a veces puede ser bastante grande, especialmente si está activo durante la ejecución de un programa completo. OLIVER proporcionó estas características desde principios de la década de 1970 como parte de su oferta de productos de depuración CICS y ahora se encuentra incorporadas al producto XPEDITER de Compuware .
Un desensamblador de longitud , también conocido como motor desensamblador de longitud ( LDE ), es una herramienta que, dada una secuencia de bytes (instrucciones), genera el número de bytes tomados por la instrucción analizada. Los proyectos de código abierto notables para la arquitectura x86 incluyen ldisasm, [8] Tiny x86 length Disassembler [9] y Extended length Disassembler Engine para x86-64. [10]