Diseño del Descompilador

Introduccion

La descompilación es una forma de ingeniería inversa de programas informáticos. Su objetivo es convertir un archivo binario compilado en un archivo fuente. Es posible que desee hacer esto por varias razones, por ejemplo, para comprender cómo funciona un programa, o para tratar de modificar un programa para mejorarlo o corregir un error.

La descompilación ha existido por muchos años, probablemente desde que la gente comenzó a compilar programas desde lenguajes de alto nivel hasta formatos de bajo nivel como ensamblaje y código de máquina.

Se han llevado a cabo varios intentos para escribir descompiladores ejecutables binarios. Esta página tiene algunos ejemplos.

Hay aún más decompiladores disponibles para entornos administrados que usan byte-code, como Java y C #. Una extensa lista está disponible en la wiki de transformación del programa.

En estas páginas nos enfocaremos en la descompilación de ejecutables binarios, o del código de la máquina al código fuente, ya que esto es mucho más difícil que descompilar el código de bytes Java o C #.

Varios lenguajes y compiladores pueden producir códigos de máquina, incluidos algunos compiladores de Java, C # y Visual Basic. Por lo tanto, el descompilador deberá saber qué idioma se utilizó para compilar el programa y deberá contar con soporte para generarlo. Sin embargo, la mayoría de los problemas difíciles de descompilación aparecen cuando se utilizan lenguajes menos restrictivos, a saber, C, Pascal o C ++.

La mayoría de los algoritmos se pueden usar para todos los idiomas, por lo que usaremos principalmente ejemplos escritos en C. Cuando mostramos un algoritmo, usaremos C o C ++, ya que estos son los idiomas más disponibles tanto en Linux como en Windows.

Independientemente del idioma de destino, un descompilador trata principalmente con 3 tipos de entidades:

  • Objetos de código (funciones, declaraciones)
  • Objetos de datos (variables globales y locales)
  • Tipos (tipos de variables, prototipos de función)

El problema constante de un descompilador es tratar de inferir una o más de las tres entidades anteriores a partir de una secuencia de bytes encontrados en el archivo binario. Para hacer esto, es útil saber cómo las herramientas de desarrollo (que llamamos herramientas de ingeniería directa) se utilizan al escribir un programa, ya que ese es el proceso que estamos tratando de revertir.