stringtranslate.com

Descompilador

Un descompilador es un programa informático que traduce un archivo ejecutable a código fuente de alto nivel . Por 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 , requiriendo técnicas más sofisticadas. Los descompiladores generalmente no pueden reconstruir perfectamente el código fuente original, por lo que con frecuencia producen código ofuscado . No obstante, siguen siendo una herramienta importante en la ingeniería inversa de 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 ) a código fuente en un lenguaje de nivel (relativamente) alto que, cuando se compila, producirá un ejecutable cuyo comportamiento es el mismo que el ejecutable original. programa. En comparación, un desensamblador traduce un programa ejecutable a lenguaje ensamblador (y se podría usar un ensamblador para volver a ensamblarlo 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 usarse para la recuperación de código fuente perdido y también es útil en algunos casos para seguridad informática , interoperabilidad y 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 descompila y de la sofisticación del análisis realizado en él. Los formatos de código de bytes utilizados por muchas máquinas virtuales (como Java Virtual Machine o .NET Framework Common Language Runtime ) 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 resultados que son muy difíciles de descompilar, o que descompilan generando resultados confusos). Esto se hace para que sea más difícil realizar ingeniería inversa en el ejecutable.

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

Diseño

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

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 de lenguaje intermedio . Debería poder descubrir datos básicos sobre el programa de entrada, como la arquitectura (Pentium, PowerPC, etc.) y el punto de entrada. En muchos casos, debería poder encontrar el equivalente de la función de un programa C , que es el comienzo del código escrito por el usuario . Esto excluye el código de inicialización del tiempo de ejecución, que no debe descompilarse si es posible. Si están disponibles, también se cargan las tablas de símbolos y los datos de depuración. La interfaz puede 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 en el código. [5]main

Desmontaje

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

movimiento eax , [ ebx + 0x04 ]  

podría traducirse al IR

eax : = m [ ebx + 4 ] ;  

Modismos

Las secuencias idiomáticas de código de máquina son secuencias de código cuya semántica combinada no es inmediatamente evidente a partir de la semántica individual de las instrucciones. Ya sea como parte de la fase de desmontaje o como parte de análisis posteriores, estas secuencias idiomáticas deben traducirse a IR equivalentes conocidos. 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; algunos implican sólo 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 coincidencia de patrones en la fase de desmontaje probablemente no reconocería el patrón alterado. Las fases posteriores agrupan las expresiones de instrucción en expresiones más complejas y las modifican en una forma canónica (estandarizada), lo que hace más probable que incluso el idioma 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 declaraciones de cambio . 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 ] agregar eax ,[ ebx + 0x08 ] sub [ ebx + 0x0C ], eax     

podría dar como resultado 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. Análisis posteriores podrán eliminar el ebxregistro.

Análisis de 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 se puede aplicar a las ubicaciones que se utilizan para datos temporales y locales. Luego se puede formar un nombre diferente para cada conjunto conectado de definiciones y usos de valores. Es posible que se haya utilizado la misma ubicación de variable local 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 cual un valor puede fluir entre dos de esos usos, aunque en realidad nunca sucedería ni importaría. En casos graves, 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 dichas dependencias no naturales, lo que conducirá 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 necesaria ]

Análisis de tipo

Un buen descompilador de código de máquina realizará un análisis de tipos. Aquí, la forma en que se utilizan los registros o las ubicaciones de memoria genera restricciones sobre el posible tipo de ubicación. Por ejemplo, una andinstrucción implica que el operando es un número entero; Los programas no utilizan esta 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 de puntero respectivamente; la tercera restricción proviene del orden de los dos operandos cuando los tipos son diferentes). [6]

Se pueden reconocer varias 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 permiten el código de máquina o incluso algunos lenguajes de alto nivel como C con conversiones y 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 { int v0004 ; intv0008 ; _ intv000C ; _ }; 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/elsedeclaraciones 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 en:

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 algún código o agregar variables booleanas. [7]

Codigo de GENERACION

La fase final es la generación del código de alto nivel en la parte posterior del descompilador. Así como un compilador puede tener varios backends para generar código de máquina para diferentes arquitecturas, un descompilador puede tener varios backends 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 funciones y variables no genéricos. Sin embargo, estos se ingresan casi con la misma facilidad en una edición posterior a la descompilación. Es posible que el usuario desee cambiar aspectos estructurales, como convertir un whilebucle en un forbucle. Estos se modifican con menor facilidad con un simple editor de texto, aunque las herramientas de refactorización del código fuente pueden ayudar en este proceso. Es posible que el usuario necesite ingresar información que no pudo identificarse 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, es posible que sea necesario corregir el 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 . Un descompilador de este tipo puede entrenarse mediante aprendizaje automático para mejorar su precisión con el tiempo. [8]

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 cubren los derechos de autor difiere de una región a otra, la ley de derechos de autor generalmente proporciona al autor (los programadores o el empleador) una colección de derechos exclusivos sobre el programa. [9] Estos derechos incluyen el derecho a hacer copias, incluidas las copias realizadas en la RAM de la computadora (a menos que crear dicha copia sea esencial para usar el programa). [10] Dado que el proceso de descompilación implica realizar 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 Estados Unidos como en Europa permiten la descompilación hasta cierto punto.

En Estados Unidos, la defensa del uso legítimo del derecho 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 participar legalmente en la descompilación para eludir el mecanismo de bloqueo de software utilizado por las consolas de juegos de Sega. [11] Además, la Ley de Derechos de Autor del Milenio Digital (LEY PÚBLICA 105–304 [12] ) tiene exenciones adecuadas tanto para las pruebas y evaluaciones de seguridad en §1201(i) como para la ingeniería inversa en §1201(f). [13]

En Europa, la Directiva de software de 1991 establece explícitamente el derecho a descompilar para lograr la interoperabilidad. Como resultado de un acalorado debate entre, por un lado, los proteccionistas del software y, por el otro, académicos y desarrolladores de software independientes, el artículo 6 sólo permite la descompilación 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 podrá transmitirse a terceros.

En general, el derecho de descompilación previsto en el artículo 6 codifica lo que se afirma que es una práctica común en la industria del software. Se sabe que han surgido pocas demandas europeas por el derecho de descompilación. Esto podría interpretarse en el sentido de una de 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 seguridad jurídica suficiente para no dar lugar a litigios o
  3. ) la descompilación ilegal pasa prácticamente desapercibida.

En un informe de 2000 sobre la implementación de la Directiva de Software por parte de los estados miembros europeos, la Comisión Europea pareció apoyar la segunda interpretación. [15]

Ver también

Descompiladores de Java

Otros descompiladores

Referencias

  1. ^ Van Emmerik, Mike (29 de abril de 2005). "Por qué la descompilación". Programa-transformación.org. Archivado desde el original el 22 de septiembre de 2010 . Consultado el 15 de septiembre de 2010 .
  2. ^ Miecznikowski, Jerónimo; Hendren, Laurie (2002). "Descompilar Java Bytecode: problemas, trampas y trampas". En Horspool, R. Nigel (ed.). Construcción del compilador: XI Conferencia Internacional, actas / CC 2002 . Springer-Verlag . págs. 111-127. ISBN 3-540-43369-4.
  3. ^ Paul, Matías 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, Matías 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 origen ASM incluidos […] Archivos fuente ASM independientes […] Archivos fuente ASM modulares […]
  5. ^ 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. 
  6. ^ Mycroft, Alan (1999). "Descompilación basada en tipos". En Swierstra, S. Doaitse (ed.). Lenguajes y sistemas de programación: VIII Simposio Europeo sobre Lenguajes y Sistemas de Programación . Springer-Verlag . págs. 208–223. ISBN 3-540-65699-5.
  7. Cifuentes, Cristina (1994). "Capítulo 6". Técnicas de compilación inversa (PDF) (tesis doctoral). Universidad Tecnológica de Queensland . Archivado (PDF) desde el original el 22 de noviembre de 2016 . Consultado el 21 de diciembre de 2019 .)
  8. ^ Tian, ​​Yuandong; Fu, Cheng (27 de enero de 2021). "Presentación de N-Bref: un marco descompilador basado en neuronas" . Consultado el 30 de diciembre de 2022 .
  9. ^ Rowland, Diane (2005). Ley de tecnologías de la información (3 ed.). Cavendish. ISBN 1-85941-756-6.
  10. ^ "Oficina de derechos de autor de EE. UU. - 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 .
  11. ^ "La legalidad de la descompilación". Programa-transformación.org. 2004-12-03. Archivado desde el original el 22 de septiembre de 2010 . Consultado el 15 de septiembre de 2010 .
  12. ^ "Ley de derechos de autor del milenio digital" (PDF) . Congreso de Estados Unidos . 1998-10-28. Archivado (PDF) desde el original el 10 de diciembre de 2013 . Consultado el 15 de noviembre de 2013 .
  13. ^ "Registro Federal :: Solicitar acceso". Archivado desde el original el 25 de enero de 2022 . Consultado el 31 de enero de 2021 .
  14. ^ Czarnota, Bridget; Hart, Robert J. (1991). Protección legal de programas informáticos en Europa: una guía para la directiva CE . Londres: Butterworths Tolley . ISBN 0-40600542-7.
  15. ^ "Informe de la Comisión al Consejo, al Parlamento Europeo y al Comité Económico y Social sobre la implementación y los efectos de la Directiva 91/250/CEE sobre la protección jurídica de los programas de ordenador". Archivado desde el original el 4 de diciembre de 2020 . Consultado el 26 de diciembre de 2020 .

enlaces externos