Articulo de referencia

Descompilador

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

Un descompilador es un programa informático que traduce un archivo ejecutable a código fuente de alto nivel . A diferencia de un compilador , que convierte el código de alto nivel en código de máquina, un descompilador realiza el proceso inverso. Mientras que los desensambladores traducen los ejecutables al lenguaje ensamblador, los descompiladores van un paso más allá al reconstruir el desensamblado en lenguajes de nivel superior como C. Sin embargo, los descompiladores a menudo no pueden recrear perfectamente el código fuente original y pueden producir código ofuscado o menos legible.

Introducción

La descompilación es el proceso de transformar código ejecutable en un formato de alto nivel legible para humanos mediante un descompilador. Este proceso se utiliza habitualmente para tareas que implican aplicar ingeniería inversa a la lógica detrás del código ejecutable, como recuperar código fuente perdido o no disponible. Los descompiladores enfrentan 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 estructura del código.

Ciertos factores pueden afectar el éxito de la descompilación. Los ejecutables que contienen metadatos detallados, como los que se utilizan en Java y .NET , son más fáciles de aplicar mediante ingeniería inversa porque suelen conservar las estructuras de clase, las firmas de los métodos y la información de depuración. Los archivos ejecutables desprovistos de dicho contexto son mucho más difíciles de traducir a código fuente significativo.

Algunos desarrolladores de software pueden ofuscar , empaquetar o cifrar partes de sus programas ejecutables, lo que hace que el código descompilado sea mucho más difícil de interpretar. Estas técnicas suelen emplearse para impedir la ingeniería inversa, lo que hace que el proceso sea más difícil y lleve más tiempo.

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. [1]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). [2]

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. [3]

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. [4]

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 el empleador) una colección de derechos exclusivos sobre el programa. [5] 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). [6] 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. [7] Además, la Ley de Derechos de Autor del Milenio Digital (LEY PÚBLICA 105–304 [8] ) tiene exenciones adecuadas tanto para las pruebas y evaluaciones de seguridad en §1201(i), como para la ingeniería inversa en §1201(f). [9]

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:

  • En primer lugar, una persona o entidad debe tener una licencia para utilizar el programa que se va a descompilar.
  • En segundo lugar, la descompilación debe ser necesaria para lograr la interoperabilidad con el programa de destino 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. La necesidad debe ser demostrada por el descompilador. El propósito de esta importante limitación es principalmente proporcionar un incentivo para que los desarrolladores documenten y divulguen la información de interoperabilidad de sus productos. [10]
  • En tercer lugar, el proceso de descompilación debe limitarse, si es posible, a las partes del programa de destino que sean 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 resultar difícil de cumplir. Una vez más, la carga de la prueba recae sobre el descompilador.

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. [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: práctica y experiencia . 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 . págs. 208–223. ISBN. 3-540-65699-5.
  3. ^ 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 .)
  4. ^ 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 .
  5. ^ Rowland, Diane (2005). Derecho de la tecnología de la información (3.ª ed.). Cavendish. ISBN 1-85941-756-6.
  6. ^ "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 .
  7. ^ "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 .
  8. ^ "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 .
  9. ^ "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 .
  10. ^ 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.
  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 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 .
Obtenido de "https://es.wikipedia.org/w/index.php?title=Descompilador&oldid=1263766102"