Descompilador

Descompilador

Descompilador

Un descompilador o decompilador es un programa de ordenador que realiza la operación inversa a un compilador. Esto es, traducir código o información de bajo nivel de abstracción (sólo diseñado para ser leído por un ordenador, ej código máquina) a un lenguaje o medio de mayor nivel de abstracción (usualmente diseñado para ser leído por un humano, ej cualquier lenguaje de programación de alto nivel).

Contenido

Introducción

El término "descompilar" es más comúnmente aplicado a programas cuya función es la de traducir un ejecutable (la salida de un compilador) a código fuente en un lenguaje de alto nivel, que, cuando compile, volverá a producir un ejecutable cuyo comportamiento es el mismo que el del ejecutable original. En comparación, un desensamblador traduce un ejecutable a lenguaje ensamblador (y este código puede volver a ser ensamblado en un programa ejecutable).

Descompilar es el acto de utilizar un descompilador, aunque si es usado como nombre, puede referirse a la salida de un descompilador. Puede ser usado para recuperar código fuente, y es muy útil en casos de seguridad del ordenador, interoperatividad y correción de errores.[1] El éxito de la descompilación depende de la cantidad de información presente en el código que está siendo descompilado y en la sofisticación del análisis realizado sobre él. Los formatos de bytecode utilizados por muchas máquinas virtuales (como la Java Virtual Machine o el lenguaje .NET (.NET Framework Common Language Runtime)) en ocasiones incluyen metadatos en el alto nivel que hacen que la descompilación se más flexible. Los lenguajes máquina normalmente tienen mucha menos metadata, y son por lo tanto mucho más difíciles de compilar.

Algunos compiladores y herramientas de post-compilación producen código ofuscado (esto quiere decir que intentan producir una salida que es muy difícil de descompilar). Esto hace que sea más difícil revertir el código del ejecutable.

Diseño

Los descompiladores pueden ser pensados como un conjunto de fases, en las que cada una de ellas contribuye de una forma específica en el proceso de descompilación.

Cargador

La primera fase de descompilación es el cargador, que recibe el código máquina o el archivo binario de un lenguaje intermedio. El cargador debería ser capaz de descubrir datos básicos sobre el programa, como por ejemplo la arquitectura (Pentium, PowerPC, etc), y el punto de entrada. En muchos casos, debería ser capaz de encontrar la función main de un programa en C, que es el comienzo del código escrito por el usuario. Esto excluye el código de inicialización de la ejecución, que no debería ser descompilado si es posible.

Desensamblado

La siguiente fase lógica es el desensamblado del código máquina, éste pasa a una representación máquina independiente (IR). Por ejemplo, la instrucción Pentium

   mov    eax, [ebx+0x04]

debería ser traducida a IR

   eax := m[ebx+4];

Secuencias idiomáticas

Las secuencias de código máquina idiomáticas es un conjunto de secuencias de código cuya semántica no aparenta instrucciones semánticamente individuales. Tanto como parte de la fase de desensamblado, o como parte del análisis posterior, estas secuencias idiomáticas necesitan ser traducidas a su equivalente en código IR (representación máquina independiente). Por ejemplo, en lenguaje ensamblador x86:

   cdq    eax             ; edx está almacenado en el registro de extensión de eax
   xor    eax, edx
   sub    eax, edx

podría ser traducido a

   eax := abs(eax);

Análisis del programa

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

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

podría resultar en el siguiente código IR después de la progagación de expresiones:

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

La expresión resultante luce como lenguaje de alto nivel, y además ha eliminado el uso de los registros eax. Análisis siguientes podrían eliminar el registro ebx.

Análisis de tipos

Un buen descompilador debería implementar un análisis de tipos. Aquí, la forma en que se usan los registros o las regiones de memoria dan como resultado restricciones en el tipo de localidades. Por ejemplo, una instrucción and implica que el operando es un entero; los programas no usan tales operaciones sobre valores de punto flotante (excepto en código especial de librerías) o en punteros. Una instrucción and da como resultado 3 restricciones; ambos operandos pueden ser enteros, o uno entero y el otro un puntero (en este caso; la tercera restricción surge en el orden de los dos operandos cuando los tipos son diferentes).

Pueden reconocerse varias expresiones de alto nivel, al conocer las estructuras o los arreglos. De todas formas, es difícil de distinguir muchas de las posibilidades por la libertad del código máquina o también porque algunos lenguajes de alto nivel como C permiten casting y aritmética de punteros.

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

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

Estructuración

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

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

podría traducirse como:

   eax = 0;
   while (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. Algunas soluciones replican código, o agregan variables booleanas. Véase el capítulo 6 de.[2]

Generación de código

La fase final es la generación de código de alto nivel. Tal como un compilador puede tener varios lenguajes destinos para generar código máquina de diferentes arquitecturas, un descompilador puede tener varios destinos de generación de código en diferentes lenguajes de alto nivel.

Justo antes de la generación del código, es deseable permitir la edición interactiva del código IR, tal vez haciendo uso de alguna interfaz gráfica de usuario. Esto puede permitir al usuario agregar comentarios, variables no genéricas y nombres de funciones. Aun así, esto también se puede agregar en ediciones posteriores a la descompilación. El usuario puede cambiar algunos aspectos estructurales, como por ejemplo, convertir un ciclo while a un ciclo for. Esto se puede cambiar con un simple editor de textos, o también se pueden usar herramientas de refactoring sobre el código fuente. El usuario también necesitará agregar información que no se pudo reconocer durante la fase de análisis de tipos, por ejemplo, modificar una expresión de memorias a un arreglo o a una estructura. Finalmente, se necesita corregir código IR incorrecto, o hacer cambios para hacer que la salida de código sea más legible.

Aspectos legales

La mayoría de los programas de ordenador están cubiertos por las leyes del copyright. Aunque determinar con precisión qué cubre el copyright y qué no, difiere entre países; la ley de copyright generalmente provee al autor (el/los programador/es o empleado/s) de una colección exclusiva de derechos sobre el programa. Estos derechos incluyen la posibilidad de realizar copias, incluyendo copias realizadas sobre la memoria RAM del ordenador. Como el proceso de decompilación implica la realización de múltiples copias, ha sido prohibido generalmente sin autorización del propietario de los derechos. Sin embargo, la descompilación es en ocasiones necesaria a la hora de buscar interoperatividad; las leyes de copyright en Europa y Estados Unidos que permiten en este caso la descompilación hasta un cierto límite.

En Estados Unidos, las leyes del buen uso del copyright han sido utilizadas satisfactoriamente en casos de descompilación. Por ejemplo, existió un caso entre Sega y Accolade, en el que finalmente se permitía a Accolade la descompilación de ciertas partes de código siempre que no copiasen el mecanismo de juego utilizado por las consolas de Sega.[3]

En Europa, la Directiva del Software de 1991 provee explícitamente derechos de decompilación siempre y cuando se busque la interoperatividad entre programas. El resultado de un acalorado debate entre proteccionistas de software y desarrolladores independientes de código, fue el Artículo 6, que permite la descompilación sólo si un número de condiciones se cumplen:

  • Primero, el descompilador (en este caso referido al usuario que realiza la operación de descompilar) debe tener licencia para usar el programa que se desea descompilar.
  • Segundo, la descompilación debe ser necesaria en los casos en los que se desee añadir interoperatividad ya sea al programa que se descompila o a programas que se van a comunicar con éste. La información sobre la interoperatividad de un programa no tiene porque estar disponible, pero sí que se debe proporcionar información sobre su funcionamiento mediante manuales y documentación de la API. Esta es una limitación importante. El propósito de esta importante limitación es principalmente incentivar a los desarrolladores a que documenten bien sus productos en el ámbito de la interoperatividad. Ver.[4]
  • Tercero, el proceso de descompilación debe, si es posible, estar confinado a partes del programa que son relevantes para la interoperatividad. Como uno de los propósitos de la descompilación es adquirir el conocimiento sobre la estructura de un programa, esta tercera limitación es difícil de aplicar. Una vez más, la responsabilidad recae sobre el descompilador.

Además, el Artículo 6 prescribe que la información obtenida a través de la descompilación no debe ser utilizada para otros propósitos y no puede ser dada a un tercero.

Por encima de todo esto, el derecho proveído en el artículo 6 es interesante, puesto que especifica hasta donde se puede llegar en la industria del software con los descompiladores. Pocos casos sobre estos derechos de descompilación se han visto en Europa. Esto puede ser intepretado de dos formas:

  1. El derecho de compilación no se usa frecuentemente y por lo tanto estas leyes son innecesarias.
  2. Estos derechos funcionan tan bien y son tan claros que no dan lugar a dudas que planteen disputas entre empresas de software.

En un reciente informe de la Directiva Europea del Software, la Comisión Europea apoyaba la segunda interpretación.

Referencias

  1. (en inglés) "Porqué Descompilación"
  2. C. Cifuentes. Técnicas de Compilación Inversa. Tesis PhD, Universidad de Tecnología de Queensland, 1994. (disponible como postscript comprimido)
  3. (en inglés) La legalidad de la descompilación
  4. (en inglés) B. Czarnota y R.J. Hart, Protección legal de programas de ordenador en Europa: una guía para la directiva. 1991, Londres: Butterworths.

Véase también

Enlaces externos

Obtenido de "Descompilador"

Wikimedia foundation. 2010.

Игры ⚽ Нужно решить контрольную?

Mira otros diccionarios:

  • SpiderMonkey — Este artículo o sección se encuentra desactualizado. Es posible que la información suministrada aquí haya cambiado o sea insuficiente. Se ha sugerido que …   Wikipedia Español

  • TraceMonkey — Este artículo o sección se encuentra desactualizado. Es posible que la información suministrada aquí haya cambiado o sea insuficiente. Se ha sugerido que …   Wikipedia Español

Compartir el artículo y extractos

Link directo
Do a right-click on the link above
and select “Copy Link”