Articulo de referencia

Descompilador

Un descompilador es un programa informático que convierte un archivo ejecutable en código fuente de alto nivel . A diferencia de un compilador , que convierte el código de alto ...

Un descompilador es un programa informático que convierte un archivo ejecutable en código fuente de alto nivel . A diferencia de un compilador , que convierte el código de alto nivel en código máquina , un descompilador realiza el proceso inverso. Mientras que los desensambladores traducen los ejecutables a lenguaje ensamblador , los descompiladores van un paso más allá al reconstruir el desensamblaje en lenguajes de nivel superior como C. Debido a la naturaleza unidireccional del proceso de compilación, los descompiladores generalmente no pueden recrear a la perfección el código fuente original. A menudo producen código ofuscado y menos legible.

Introducción

La descompilación es el proceso de transformar código ejecutable en un formato de alto nivel legible por humanos mediante un descompilador. Este proceso se utiliza comúnmente para tareas que implican la ingeniería inversa de la lógica subyacente al código ejecutable, como la recuperación de código fuente perdido o no disponible. Los descompiladores se enfrentan a desafíos inherentes debido a la pérdida de información crítica durante el proceso de compilación, como nombres de variables, comentarios y la estructura del código.

Ciertos factores pueden influir en el éxito de la descompilación. Los ejecutables que contienen metadatos detallados , como los que utilizan Java y .NET , son más fáciles de descompilar, ya que suelen conservar estructuras de clases , firmas de métodos e información de depuración . Los archivos ejecutables que carecen de este contexto son mucho más difíciles de convertir en código fuente comprensible.

Algunos desarrolladores de software pueden ofuscar , empaquetar o cifrar partes de sus programas ejecutables, lo que dificulta considerablemente la interpretación del código descompilado. Estas técnicas suelen emplearse para disuadir la ingeniería inversa, haciendo que el proceso sea más complejo y requiera más tiempo.

Diseño

Los descompiladores pueden considerarse compuestos por una serie de fases, cada una de las cuales contribuye con aspectos específicos del proceso general de descompilación.

Cargador

The first decompilation phase loads and parses the input machine code or intermediate language program's binary file format. It should be able to discover basic facts about the input program, such as the architecture (Pentium, PowerPC, etc.) and the entry point. In many cases, it should be able to find the equivalent of the main function of a C program, which is the start of the user written code. This excludes the runtime initialization code, which should not be decompiled if possible. If available the symbol tables and debug data are also loaded. The front end may be able to identify the libraries used even if they are linked with the code, this will provide library interfaces. If it can determine the compiler or compilers used it may provide useful information in identifying code idioms.[1]

Disassembly

The next logical phase is the disassembly of machine code instructions into a machine independent intermediate representation (IR). For example, the Pentium machine instruction

moveax,[ebx+0x04]

might be translated to the IR

eax:=m[ebx+4];

Idioms

Idiomatic machine code sequences are sequences of code whose combined semantics are not immediately apparent from the instructions' individual semantics. Either as part of the disassembly phase, or as part of later analyses, these idiomatic sequences need to be translated into known equivalent IR. For example, the x86 assembly code:

cdqeax; edx is set to the sign-extension≠edi,edi +(tex)pushxoreax,edxsubeax,edx

could be translated to

eax := abs(eax);

Some idiomatic sequences are machine independent; some involve only one instruction. For example, xoreax,eax clears the eax register (sets it to zero). This can be implemented with a machine independent simplification rule, such as a = 0.

En general, conviene retrasar la detección de secuencias idiomáticas, si es posible, a etapas posteriores menos afectadas por el orden de las instrucciones. Por ejemplo, la fase de planificación de instrucciones de un compilador puede insertar otras instrucciones en una secuencia idiomática o modificar el orden de las instrucciones dentro de la secuencia. Un proceso de comparación de patrones en la fase de desensamblaje probablemente no reconocería el patrón modificado. Las fases posteriores agrupan las expresiones de instrucciones en expresiones más complejas y las modifican a una forma canónica (estandarizada), lo que aumenta la probabilidad de que incluso la secuencia idiomática modificada coincida con un patrón de nivel superior más adelante en la descompilación.

Es particularmente importante reconocer las convenciones del compilador para llamadas a subrutinas , manejo de excepciones y sentencias switch . Algunos lenguajes también ofrecen un amplio soporte para cadenas o números enteros largos .

Análisis del programa

Se pueden aplicar varios análisis de programas al IR. En particular, la propagación de expresiones combina la semántica de varias instrucciones en expresiones más complejas. Por ejemplo,

mov eax ,[ ebx + 0x04 ] add eax ,[ ebx + 0x08 ] sub [ ebx + 0x0C ], eax

podría resultar en la siguiente IR después de la propagación de la expresión:

m[ebx+12] := m[ebx+12] - (m[ebx+4] + m[ebx+8]);

La expresión resultante se asemeja más a un lenguaje de alto nivel y, además, ha eliminado el uso del registro de máquina eax. Análisis posteriores podrían eliminar dicho ebxregistro.

Análisis del flujo de datos

Los lugares donde se definen y utilizan los contenidos de los registros deben rastrearse mediante análisis de flujo de datos . El mismo análisis puede aplicarse a las ubicaciones utilizadas para variables temporales y datos locales. A continuación, se puede generar un nombre diferente para cada conjunto conectado de definiciones y usos de valores. Es posible que la misma ubicación de variable local se haya utilizado para más de una variable en diferentes partes del programa original. Peor aún, el análisis de flujo de datos puede identificar una ruta por la cual un valor puede fluir entre dos usos de este tipo, aunque esto nunca ocurra ni tenga relevancia en la realidad. En casos extremos, esto puede llevar a la necesidad de definir una ubicación como una unión de tipos. El descompilador puede permitir al usuario romper explícitamente estas dependencias no naturales, lo que dará como resultado un código más claro. Esto, por supuesto, significa que una variable se utiliza potencialmente sin estar inicializada, lo que indica un problema en el programa original.

Análisis de tipos

Un buen descompilador de código máquina realizará un análisis de tipos. En este análisis, la forma en que se utilizan los registros o las ubicaciones de memoria impone restricciones sobre el tipo posible de la ubicación. Por ejemplo, una andinstrucción implica que el operando es un entero; los programas no utilizan dicha operación con valores de punto flotante (excepto en código de biblioteca especial) ni con punteros . Una addinstrucción da como resultado tres restricciones, ya que los operandos pueden ser enteros, o uno entero y un puntero (con resultados enteros y punteros respectivamente; la tercera restricción proviene del orden de los dos operandos cuando los tipos son diferentes). [ 2 ]

Se pueden reconocer diversas expresiones de alto nivel que activan el reconocimiento de estructuras o matrices. Sin embargo, resulta difícil distinguir muchas de las posibilidades debido a la libertad que ofrece el código máquina, e incluso algunos lenguajes de alto nivel como C, con las conversiones de tipo y la aritmética de punteros.

El ejemplo de la sección anterior podría dar como resultado el siguiente código de alto nivel:

struct T1 { int v0004 ; int v0008 ; int v000C ; }; struct T1 * ebx ; ebx -> v000C -= ebx -> v0004 + ebx -> v0008 ;

Estructuración

La penúltima fase de descompilación implica la estructuración del IR en construcciones de nivel superior, como whilebucles y if/then/elsesentencias condicionales. Por ejemplo, el código máquina.

xor eax , eax l0002: o ebx , ebx jge l0003 add eax , [ ebx ] mov ebx , [ ebx + 0x4 ] jmp l0002 l0003: mov [ 0x10040000 ], eax

podría traducirse como:

eax = 0 ; mientras ( ebx < 0 ) { eax += ebx- > v0000 ; ebx = ebx- > v0004 ; } v10040000 = eax ;

El código no estructurado es más difícil de convertir en código estructurado que el código ya estructurado. Las soluciones incluyen replicar parte del código o agregar variables booleanas. [ 3 ]

Generación de código

La fase final consiste en la generación del código de alto nivel en la parte posterior del descompilador. Del mismo modo que un compilador puede tener varias partes posteriores para generar código máquina para diferentes arquitecturas, un descompilador puede tener varias partes posteriores para generar código de alto nivel en diferentes lenguajes de alto nivel.

Justo antes de la generación del código, puede ser conveniente permitir la edición interactiva del IR, quizás mediante una interfaz gráfica de usuario . Esto permitiría al usuario introducir comentarios y nombres de variables y funciones no genéricos. Sin embargo, estos se pueden introducir casi con la misma facilidad en una edición posterior a la descompilación. El usuario podría querer modificar aspectos estructurales, como convertir un whilebucle en forotro. Estos cambios son más difíciles de realizar con un editor de texto simple, aunque las herramientas de refactorización de código fuente pueden facilitar este proceso. El usuario podría necesitar introducir información que no se identificó durante la fase de análisis de tipos, por ejemplo, modificar una expresión de memoria a una expresión de matriz o estructura. Finalmente, podría ser necesario corregir un IR incorrecto o realizar cambios para que el código de salida sea más legible.

Otras técnicas

Se han desarrollado descompiladores que utilizan redes neuronales . Dicho descompilador puede entrenarse mediante aprendizaje automático para mejorar su precisión con el tiempo. [ 4 ]

Legalidad

La mayoría de los programas informáticos están protegidos por derechos de autor . Si bien el alcance exacto de lo que abarcan los derechos de autor varía según la región, la ley generalmente otorga al autor (el programador o el empleador) un conjunto de derechos exclusivos sobre el programa. [ 5 ] Estos derechos incluyen el derecho a realizar copias , incluso en la memoria RAM del ordenador (a menos que la creación de dicha copia sea esencial para el uso del programa). [ 6 ] Dado que el proceso de descompilación implica realizar múltiples copias, generalmente está prohibido sin la autorización del titular de los derechos de autor. Sin embargo, debido a que la descompilación suele ser un paso necesario para lograr la interoperabilidad del software , las leyes de derechos de autor tanto en Estados Unidos como en Europa permiten la descompilación hasta cierto punto.

En Estados Unidos, la defensa del uso legítimo de derechos de autor se ha invocado con éxito en casos de descompilación. Por ejemplo, en Sega v. Accolade , el tribunal dictaminó que Accolade podía realizar legalmente la descompilación para eludir el mecanismo de bloqueo de software utilizado por las consolas de videojuegos de Sega. [ 7 ] Además, la Ley de Derechos de Autor del Milenio Digital (Ley Pública 105-304 [ 8 ] ) contempla exenciones adecuadas tanto para las pruebas y evaluaciones de seguridad en el §1201(i) como para la ingeniería inversa en el §1201(f). [ 9 ]

En Europa, la Directiva de Software de 1991 prevé explícitamente el derecho a descompilar para lograr la interoperabilidad. Fruto de un acalorado debate entre, por un lado, los defensores del software y, por otro, los académicos y los desarrolladores de software independientes, el artículo 6 permite la descompilación solo si se cumplen una serie de condiciones:

  • En primer lugar, la persona o entidad debe tener una licencia para usar el programa que se va a descompilar.
  • En segundo lugar, la descompilación debe ser necesaria para lograr la interoperabilidad con el programa objetivo u otros programas. Por lo tanto, la información de interoperabilidad no debe estar fácilmente disponible, por ejemplo, a través de manuales o documentación de API . Esta es una limitación importante. El descompilador debe demostrar la necesidad. El propósito de esta importante limitación es principalmente incentivar a los desarrolladores a documentar y divulgar la información de interoperabilidad de sus productos. [ 10 ]
  • En tercer lugar, el proceso de descompilación debe, de ser posible, limitarse a las partes del programa objetivo relevantes para la interoperabilidad. Dado que uno de los objetivos de la descompilación es comprender la estructura del programa, esta tercera limitación puede ser difícil de cumplir. Una vez más, la carga de la prueba recae sobre el descompilador.

Además, el artículo 6 estipula que la información obtenida mediante la descompilación no podrá utilizarse para otros fines ni podrá divulgarse a terceros.

En general, el derecho de descompilación previsto en el artículo 6 codifica lo que se considera práctica común en la industria del software. Se conocen pocos litigios europeos derivados de este derecho. Esto podría interpretarse de tres maneras:

  1. El derecho de descompilación no se utiliza con frecuencia y, por lo tanto, puede que haya sido innecesario.
  2. El derecho de descompilación funciona bien y proporciona suficiente seguridad jurídica para no dar lugar a disputas legales o
  3. La descompilación ilegal pasa en gran medida desapercibida.

En un informe de 2000 sobre la aplicación de la Directiva de Software por los Estados miembros europeos, la Comisión Europea pareció apoyar la segunda interpretación. [ 11 ]

Véase también

descompiladores de Java

Otros descompiladores

Referencias

  1. Cifuentes, Cristina; Gough, K. John (julio de 1995). "Descompilación de programas binarios". Software: Practice and Experience . 25 (7): 811– 829. CiteSeerX 10.1.1.14.8073 . doi : 10.1002/spe.4380250706 . S2CID 8229401 .  
  2. Mycroft, Alan (1999). "Descompilación basada en tipos". En Swierstra, S. Doaitse (ed.). Lenguajes y sistemas de programación: 8.º Simposio Europeo sobre Lenguajes y Sistemas de Programación . Springer-Verlag . pp. 208–223 . ISBN  3-540-65699-5.
  3. Cifuentes, Cristina (1994). "Capítulo 6". Técnicas de compilación inversa (PDF) (tesis doctoral). Universidad Tecnológica de Queensland . Archivado (PDF) del original el 22 de noviembre de 2016. Recuperado el 21 de diciembre de 2019 .)
  4. Tian, ​​Yuandong; Fu, Cheng (27 de enero de 2021). "Presentación de N-Bref: un marco de descompilación basado en redes neuronales" . Recuperado el 30 de diciembre de 2022 .
  5. Rowland, Diane (2005). Derecho de las tecnologías de la información (3.ª ed.). Cavendish. ISBN  1-85941-756-6.
  6. "Oficina de Derechos de Autor de EE. UU. - Ley de Derechos de Autor: Capítulo 1" . Archivado del original el 25/12/2017 . Consultado el 10/04/2014 .
  7. "La legalidad de la descompilación" . Program-transformation.org. 3 de diciembre de 2004. Archivado del original el 22 de septiembre de 2010. Consultado el 15 de septiembre de 2010 .
  8. "Ley de Derechos de Autor del Milenio Digital" (PDF) . Congreso de los Estados Unidos . 28 de octubre de 1998. Archivado (PDF) del original el 10 de diciembre de 2013. Consultado el 15 de noviembre de 2013 .
  9. "Registro Federal :: Solicitar Acceso" . 26 de octubre de 2018. Archivado del original el 25 de enero de 2022. Consultado el 31 de enero de 2021 . 
  10. Czarnota, Bridget; Hart, Robert J. (1991). Protección jurídica de los programas informáticos en Europa: una guía de la directiva CE . Londres: Butterworths Tolley . ISBN 0-40600542-7.
  11. «Informe de la Comisión al Consejo, al Parlamento Europeo y al Comité Económico y Social sobre la aplicación y los efectos de la Directiva 91/250/CEE relativa a la protección jurídica de los programas informáticos» . Archivado del original el 4 de diciembre de 2020. Consultado el 26 de diciembre de 2020 .
Obtenido de " https://en.wikipedia.org/w/index.php?title=Decompiler&oldid=1344601276 "