decompiling - gui - ¿Cómo funciona la descompilación?
java decoder jd benow ca (2)
He escuchado el término "descompilar" un par de veces, y estoy empezando a sentir mucha curiosidad acerca de cómo funciona.
Tengo una idea muy general de cómo funciona; aplicar ingeniería inversa a una aplicación para ver qué funciones utiliza, pero no sé mucho más allá de eso.
También he escuchado el término " desensamblador ", ¿cuál es la diferencia entre un desensamblador y un descompilador?
Entonces, para resumir mi (s) pregunta (s): ¿En qué consiste exactamente el proceso de descompilación de algo? ¿Cómo se suele hacer? ¿Qué tan complicado / fácil es un proceso? ¿Puede producir el código exacto? ¿Y cuál es la diferencia entre un descompilador y un desensamblador?
Ilfak Guilfanov, el autor de Hex-Rays Decompiler , pronunció un discurso sobre el funcionamiento interno de su decompilador en una estafa, y aquí está el documento técnico y una presentation . Esto describe una buena descripción general de cuáles son todas las dificultades para construir un descompilador y cómo hacer que todo funcione.
Aparte de eso, hay algunos artículos bastante antiguos, por ejemplo, la tesis doctoral clásica de Cristina Cifuentes .
En cuanto a la complejidad, todas las cosas de "descompilación" dependen del lenguaje y el tiempo de ejecución del binario. Por ejemplo, descompilar .NET y Java se considera "hecho", ya que hay descompiladores libres disponibles, que tienen una tasa de éxito muy alta (producen la fuente original). Pero eso se debe a la naturaleza muy específica de las máquinas virtuales que utilizan estos tiempos de ejecución.
En cuanto a los lenguajes realmente compilados, como C, C ++, Obj-C, Delphi, Pascal, ... la tarea se vuelve mucho más complicada. Lea los documentos anteriores para más detalles.
¿Cuál es la diferencia entre un desensamblador y un descompilador?
Cuando tienes un programa binario (ejecutable, biblioteca de DLL, ...), consta de instrucciones del procesador. El lenguaje de estas instrucciones se llama ensamblado (o ensamblador). En un binario, estas instrucciones están codificadas en binario, de modo que el procesador puede ejecutarlas directamente. Un desensamblador toma este código binario y lo traduce en una representación de texto. Esta traducción suele ser de 1 a 1, lo que significa que una instrucción se muestra como una línea de texto. Esta tarea es compleja, pero sencilla, el programa solo necesita conocer todas las diferentes instrucciones y cómo se representan en un binario.
Por otro lado, un descompilador hace una tarea mucho más difícil. Toma el código binario o la salida del desensamblador (que es básicamente el mismo, porque es 1-a-1) y produce un código de alto nivel. Dejame mostrarte un ejemplo. Digamos que tenemos esta función C:
int twotimes(int a) {
return a * 2;
}
Cuando lo compila, el compilador primero genera un archivo de ensamblaje para esa función, podría verse algo como esto:
_twotimes:
SHL EAX, 1
RET
(La primera línea es solo una etiqueta y no una instrucción real, SHL
realiza una operación de desplazamiento hacia la izquierda, lo que hace una multiplicación rápida por dos, RET
significa que la función está hecha). En el resultado binario, se ve así:
08 6A CF 45 37 1A
(Lo inventé, no instrucciones reales binarias). Ahora sabes, que un desensamblador te lleva desde la forma binaria a la forma de ensamblaje. Un descompilador lo lleva desde el formulario de ensamblaje al código C (o algún otro lenguaje de nivel superior).
La descompilación es esencialmente lo contrario de compilar. Es decir, tomar el código objeto (binario) e intentar recrear el código fuente a partir de él.
La descompilación depende de los artefactos que se dejen en el código objeto que pueden usarse para determinar la estructura del código fuente.
Con C / C ++ no queda mucho para ayudar con el proceso de descompilación, por lo que es muy difícil. Sin embargo, con Java y C # y otros lenguajes que apuntan a máquinas virtuales, puede ser más fácil de descompilar porque el lenguaje deja muchos más consejos dentro del código objeto.