stringtranslate.com

Descompilador

Un descompilador es un programa informático que traduce un archivo ejecutable a código fuente de alto nivel . Por lo tanto, hace lo contrario de un compilador típico , que traduce un lenguaje de alto nivel a un lenguaje de bajo nivel. Mientras que los desensambladores traducen un ejecutable a lenguaje ensamblador , los descompiladores van un paso más allá y traducen el código a un lenguaje de nivel superior como C o Java , lo que requiere técnicas más sofisticadas. Los descompiladores generalmente no pueden reconstruir perfectamente el código fuente original, por lo que con frecuencia producirán código ofuscado . No obstante, siguen siendo una herramienta importante en la ingeniería inversa del software informático .

Introducción

El término descompilador se aplica más comúnmente a un programa que traduce programas ejecutables (la salida de un compilador ) en código fuente en un lenguaje de nivel (relativamente) alto que, cuando se compila, producirá un ejecutable cuyo comportamiento es el mismo que el del programa ejecutable original. En comparación, un desensamblador traduce un programa ejecutable al lenguaje ensamblador (y un ensamblador podría usarse para ensamblarlo nuevamente en un programa ejecutable).

La descompilación es el acto de utilizar un descompilador, aunque el término también puede referirse a la salida de un descompilador. Puede utilizarse para la recuperación de código fuente perdido, y también es útil en algunos casos para la seguridad informática , la interoperabilidad y la corrección de errores . [1] El éxito de la descompilación depende de la cantidad de información presente en el código que se está descompilando y de la sofisticación del análisis realizado en él. Los formatos de bytecode utilizados por muchas máquinas virtuales (como la Máquina Virtual Java o el Common Language Runtime de .NET Framework ) a menudo incluyen metadatos extensos y características de alto nivel que hacen que la descompilación sea bastante factible. La aplicación de datos de depuración , es decir, símbolos de depuración, puede permitir reproducir los nombres originales de variables y estructuras e incluso los números de línea. El lenguaje de máquina sin dichos metadatos o datos de depuración es mucho más difícil de descompilar. [2]

Algunos compiladores y herramientas de poscompilación producen código ofuscado (es decir, intentan producir un resultado que es muy difícil de descompilar o que se descompila para generar un resultado confuso). Esto se hace para dificultar la ingeniería inversa del ejecutable.

Si bien los descompiladores se utilizan normalmente para (re)crear código fuente a partir de ejecutables binarios, también hay descompiladores para convertir archivos de datos binarios específicos en fuentes legibles y editables para humanos. [3] [4]

El nivel de éxito alcanzado por los descompiladores puede verse afectado por varios factores. Entre ellos se incluye el nivel de abstracción del lenguaje fuente; si el código objeto contiene información explícita sobre la estructura de clases, esto ayuda al proceso de descompilación. La información descriptiva, especialmente con detalles de nombres, también acelera el trabajo del compilador. Además, el código menos optimizado se descompila más rápido, ya que la optimización puede provocar una mayor desviación del código original. [5]

Diseño

Se puede pensar que los descompiladores están compuestos de una serie de fases, cada una de las cuales aporta aspectos específicos del proceso de descompilación general.

Cargador

La primera fase de descompilación carga y analiza el código de máquina de entrada o el formato de archivo binario del programa en lenguaje intermedio . Debería ser capaz de descubrir hechos básicos sobre el programa de entrada, como la arquitectura (Pentium, PowerPC, etc.) y el punto de entrada. En muchos casos, debería ser capaz de encontrar el equivalente de la función de un programa en C , que es el inicio del código escrito por el usuario . Esto excluye el código de inicialización en tiempo de ejecución, que no debería descompilarse si es posible. Si están disponibles, también se cargan las tablas de símbolos y los datos de depuración. El frontend puede ser capaz de identificar las bibliotecas utilizadas incluso si están vinculadas con el código, esto proporcionará interfaces de biblioteca. Si puede determinar el compilador o compiladores utilizados, puede proporcionar información útil para identificar modismos de código. [6]main

Desmontaje

La siguiente fase lógica es el desmontaje de las instrucciones de código de máquina en una representación intermedia independiente de la máquina (IR). Por ejemplo, la instrucción de máquina Pentium

movimiento eax , [ ebx + 0x04 ]  

Podría traducirse al IR

eax : = m [ ebx + 4 ] ;  

Modismos

Las secuencias de código de máquina idiomático son secuencias de código cuya semántica combinada no resulta evidente de inmediato a partir de la semántica individual de las instrucciones. Ya sea como parte de la fase de desensamblado o como parte de análisis posteriores, estas secuencias idiomáticas deben traducirse a un IR equivalente conocido. Por ejemplo, el código ensamblador x86 :

 cdq eax ; edx se establece en la extensión de signo ≠ edi, edi + (tex) push xor eax , edx sub eax , edx        

Podría traducirse a

eax := abs(eax);

Algunas secuencias idiomáticas son independientes de la máquina; otras implican solo una instrucción. Por ejemplo, borra el registro (lo pone a cero). Esto se puede implementar con una regla de simplificación independiente de la máquina, como .xor eax, eaxeaxa = 0

En general, es mejor retrasar la detección de secuencias idiomáticas, si es posible, hasta etapas posteriores que se vean menos afectadas por el orden de las instrucciones. Por ejemplo, la fase de programación de instrucciones de un compilador puede insertar otras instrucciones en una secuencia idiomática o cambiar el orden de las instrucciones en la secuencia. Un proceso de comparación de patrones en la fase de desensamblado probablemente no reconocería el patrón alterado. Las fases posteriores agrupan las expresiones de instrucciones en expresiones más complejas y las modifican hasta obtener una forma canónica (estandarizada), lo que hace más probable que incluso el modismo alterado coincida con un patrón de nivel superior más adelante en la descompilación.

Es particularmente importante reconocer los modismos del compilador para llamadas a subrutinas , manejo de excepciones y sentencias switch . Algunos lenguajes también tienen 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 ] agrega eax ,[ ebx + 0x08 ] sub [ ebx + 0x0C ], eax     

podría resultar en el 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 parece más a un lenguaje de alto nivel y también ha eliminado el uso del registro de máquina eax. Es posible que análisis posteriores eliminen el ebxregistro.

Análisis del flujo de datos

Los lugares donde se definen y utilizan los contenidos de los registros deben rastrearse mediante el análisis del flujo de datos . El mismo análisis se puede aplicar a las ubicaciones que se utilizan para datos temporales y locales. A continuación, se puede formar un nombre diferente para cada conjunto conectado de definiciones de valores y usos. 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, es posible que el análisis del flujo de datos identifique una ruta por la que un valor puede fluir entre dos de esos usos aunque en realidad nunca suceda o importe. Esto puede, en casos graves, llevar a la necesidad de definir una ubicación como una unión de tipos. El descompilador puede permitir al usuario romper explícitamente esas dependencias no naturales, lo que dará lugar a un código más claro. Por supuesto, esto significa que una variable se utiliza potencialmente sin inicializarse y, por lo tanto, indica un problema en el programa original. [ cita requerida ]

Análisis de tipos

Un buen descompilador de código de máquina realizará un análisis de tipos. En este caso, la forma en que se utilizan los registros o las ubicaciones de memoria da como resultado 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 en valores de punto flotante (excepto en código de biblioteca especial) o en punteros . Una addinstrucción da como resultado tres restricciones, ya que los operandos pueden ser ambos enteros, o un entero y un puntero (con resultados enteros y punteros respectivamente; la tercera restricción proviene del ordenamiento de los dos operandos cuando los tipos son diferentes). [7]

Se pueden reconocer diversas expresiones de alto nivel que activan el reconocimiento de estructuras o matrices. Sin embargo, es difícil distinguir muchas de las posibilidades, debido a la libertad que permite el código de máquina o incluso algunos lenguajes de alto nivel como C con las conversiones 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:

estructura T1 * ebx ; estructura T1 { entero v0004 ; entero v0008 ; entero v000C ; }; 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 de máquina

 xor eax , eax l0002: o ebx , ebx jge l0003 agregar 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 traducir a código estructurado que el código ya estructurado. Las soluciones incluyen replicar parte del código o agregar variables booleanas. [8]

Generación de código

La fase final es la generación del código de alto nivel en el back end del descompilador. Así como un compilador puede tener varios back end para generar código de máquina para diferentes arquitecturas, un descompilador puede tener varios back end para generar código de alto nivel en diferentes lenguajes de alto nivel.

Justo antes de la generación del código, puede ser deseable permitir una edición interactiva del IR, tal vez utilizando alguna forma de interfaz gráfica de usuario . Esto permitiría al usuario ingresar comentarios y nombres de variables y funciones no genéricos. Sin embargo, estos se ingresan casi con la misma facilidad en una edición posterior a la descompilación. El usuario puede querer cambiar aspectos estructurales, como convertir un whilebucle en un forbucle. Estos se modifican con menos facilidad con un editor de texto simple, aunque las herramientas de refactorización de código fuente pueden ayudar con este proceso. El usuario puede necesitar ingresar información que no se identificó durante la fase de análisis de tipo, por ejemplo, modificar una expresión de memoria a una expresión de matriz o estructura. Finalmente, puede ser necesario corregir un IR incorrecto o realizar cambios para hacer que el código de salida sea más legible.

Otras técnicas

Se han desarrollado descompiladores que utilizan redes neuronales . Estos descompiladores pueden entrenarse mediante aprendizaje automático para mejorar su precisión con el tiempo. [9]

Legalidad

La mayoría de los programas informáticos están cubiertos por leyes de derechos de autor . Aunque el alcance preciso de lo que está cubierto por los derechos de autor difiere de una región a otra, la ley de derechos de autor generalmente proporciona al autor (el programador o los programadores o el empleador) una colección de derechos exclusivos sobre el programa. [10] Estos derechos incluyen el derecho a hacer copias, incluidas copias realizadas en la memoria RAM del ordenador (a menos que la creación de dicha copia sea esencial para utilizar el programa). [11] Dado que el proceso de descompilación implica hacer múltiples copias de este tipo, generalmente está prohibido sin la autorización del titular de los derechos de autor. Sin embargo, debido a que la descompilación es a menudo un paso necesario para lograr la interoperabilidad del software , las leyes de derechos de autor tanto en los Estados Unidos como en Europa permiten la descompilación en una medida limitada.

En los Estados Unidos, la defensa del uso legítimo de los derechos de autor se ha invocado con éxito en casos de descompilación. Por ejemplo, en Sega v. Accolade , el tribunal sostuvo que Accolade podía realizar legalmente la descompilación para eludir el mecanismo de bloqueo de software utilizado por las consolas de juegos de Sega. [12] Además, la Ley de Derechos de Autor del Milenio Digital (LEY PÚBLICA 105–304 [13] ) tiene exenciones adecuadas tanto para las pruebas y evaluaciones de seguridad en el §1201(i), como para la ingeniería inversa en el §1201(f). [14]

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

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

En general, el derecho de descompilación previsto en el artículo 6 codifica lo que se considera una práctica habitual en la industria del software. Se sabe que han surgido pocas demandas europeas a raíz del derecho de descompilación. Esto podría interpretarse en el sentido de una de estas tres cosas:

  1. ) el derecho de descompilación no se utiliza con frecuencia y, por lo tanto, puede haber sido innecesario,
  2. ) el derecho de descompilación funciona bien y proporciona suficiente seguridad jurídica para no dar lugar a disputas jurídicas o
  3. ) La descompilación ilegal pasa prácticamente 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. [16]

Véase también

Descompiladores de Java

Otros descompiladores

Referencias

  1. ^ Van Emmerik, Mike (29 de abril de 2005). "Why Decompilation" (Por qué descompilar). Program-transformation.org. Archivado desde el original el 22 de septiembre de 2010. Consultado el 15 de septiembre de 2010 .
  2. ^ Miecznikowski, Jerome; Hendren, Laurie (2002). "Descompilación de código de bytes de Java: problemas, trampas y dificultades". En Horspool, R. Nigel (ed.). Construcción de compiladores: 11.ª conferencia internacional, actas / CC 2002 . Springer-Verlag . págs. 111–127. ISBN 3-540-43369-4.
  3. ^ Paul, Matthias R. (10 de junio de 2001) [1995]. "Descripción del formato de archivos .CPI de DOS, OS/2 y Windows NT, y .CP de Linux" (archivo CPI.LST) (1.30.ª ed.). Archivado desde el original el 20 de abril de 2016. Consultado el 20 de agosto de 2016 .
  4. ^ Paul, Matthias R. (13 de mayo de 2002). «[fd-dev] mkeyb». freedos-dev . Archivado desde el original el 10 de septiembre de 2018 . Consultado el 10 de septiembre de 2018 . […] Analizador, validador y descompilador de archivos de páginas de códigos .CPI y .CP […] Descripción general de los parámetros /Style: […] Archivos de inclusión de código fuente de ASM […] Archivos de código fuente de ASM independientes […] Archivos de código fuente de ASM modulares […]
  5. ^ Elo, Tommi; Hasu, Tero (2003). "Detección de código fuente coderivado: descripción general" (PDF) . Teknisjuridinen selvitys tekijänoikeudesta tietokoneohjelman lähdekoodiin Suomessa ja Euroopassa .
  6. ^ Cifuentes, Cristina; Gough, K. John (julio de 1995). "Descompilación de programas binarios". Software: práctica y experiencia . 25 (7): 811–829. CiteSeerX 10.1.1.14.8073 . doi :10.1002/spe.4380250706. S2CID  8229401. 
  7. ^ 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 . págs. 208–223. ISBN. 3-540-65699-5.
  8. ^ Cifuentes, Cristina (1994). "Capítulo 6". Técnicas de compilación inversa (PDF) (tesis doctoral). Queensland University of Technology . Archivado (PDF) desde el original el 2016-11-22 . Consultado el 2019-12-21 .)
  9. ^ Tian, ​​Yuandong; Fu, Cheng (27 de enero de 2021). "Presentación de N-Bref: un marco de descompilación basado en neuronas" . Consultado el 30 de diciembre de 2022 .
  10. ^ Rowland, Diane (2005). Derecho de la tecnología de la información (3.ª ed.). Cavendish. ISBN 1-85941-756-6.
  11. ^ "Oficina de Derechos de Autor de Estados Unidos - Ley de Derechos de Autor: Capítulo 1". Archivado desde el original el 25 de diciembre de 2017. Consultado el 10 de abril de 2014 .
  12. ^ "La legalidad de la descompilación". Program-transformation.org. 2004-12-03. Archivado desde el original el 2010-09-22 . Consultado el 2010-09-15 .
  13. ^ "Digital Millennium Copyright Act" (PDF) . Congreso de los Estados Unidos . 1998-10-28. Archivado (PDF) desde el original el 2013-12-10 . Consultado el 2013-11-15 .
  14. ^ "Federal Register :: Request Access" (Registro Federal :: Solicitud de acceso). 26 de octubre de 2018. Archivado desde el original el 25 de enero de 2022. Consultado el 31 de enero de 2021 .
  15. ^ Czarnota, Bridget; Hart, Robert J. (1991). Protección jurídica de los programas informáticos en Europa: una guía sobre la directiva de la CE . Londres: Butterworths Tolley . ISBN. 0-40600542-7.
  16. ^ "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 sobre la protección jurídica de programas de ordenador". Archivado desde el original el 4 de diciembre de 2020. Consultado el 26 de diciembre de 2020 .

Enlaces externos