SlideShare uma empresa Scribd logo
1 de 5
Baixar para ler offline
Ingeniería Inversa de Código Fuente
                            José Enrique Alvarez Estrada (jeae@prodigy.net.mx)
                         Elvia Morales Turrubiates (emorales@pampano.unacar.mx)


Resumen
Nadie pone en duda la importancia de la ingeniería como disciplina del conocimiento humano. Pero pocas
personas saben que esta disciplina posee una contraparte: la llamada ingeniería inversa.
El objetivo de la ingeniería, es desarrollar la solución a un problema a partir de la nada. En cambio, la inge-
niería inversa propone solucionar ese mismo problema, pero a partir de alguna tecnología existente, cuyo fun-
cionamiento no se conoce (al menos no totalmente), pero que se sabe tiene el potencial de resolverlo total o
parcialmente.
Si bien no existe una licenciatura en ingeniería inversa, es un hecho que muchos ingenieros dedican su vida
profesional a esta disciplina. Pero, curiosamente, muy poco o nada se habla de ella en las currículas universi-
tarias, y jamás se enseña formalmente. De hecho, en muchos círculos el hablar de ingeniería inversa todavía
es un tabú, y si bien se sabe y se acepta que la mayor parte de las empresas la utilizan, nadie quiere reconocer-
lo abiertamente.
El objetivo de esta ponencia es divulgar la importancia de esta disciplina, presentando su estado del arte para
la rama particular de la ingeniería inversa de código fuente.

                                                            Las técnicas de transformación de programas se
Introducción                                                utilizan en muchas áreas de la ingeniería de
Se puede definir a la ingeniería inversa como el            software     incluyendo    la     construcción    de
proceso mediante el cual una tecnología o producto          compiladores, la visualización de software, la
se analiza, con el fin de conocer los componentes           generación de documentación y la actualización
que lo integran y la forma en que éstos interactúan,        automatizada del software. En todas estas
para lograr finalmente una comprensión cabal de             aplicaciones podemos distinguir dos aspectos
su modo de funcionamiento, con el objetivo                  principales, por ejemplo, uno donde el lenguaje
probable de construir una tecnología similar. La            fuente y destino son diferentes (las traducciones) y
ingeniería inversa toma un producto cuyo formato            otro aspecto cuando son iguales (la reformulación).
presenta un bajo grado de abstracción, y obtiene            Estos panoramas principales se pueden refinar en
una nueva presentación del mismo, con una                       un número de aspectos secundarios típicos
abstracción mayor.                                              basados en su efecto sobre el nivel de
Sin duda, cada rama del conocimiento ha                         abstracción de un programa y en la medida
desarrollado sus propias técnicas de ingeniería                 que preservan la semántica de un programa.
inversa. Por ejemplo, en el caso de la química, el
análisis espectrográfico de los componentes que
forman una substancia (digamos, un fármaco)                 Decompilación
puede utilizarse para crear una substancia similiar.
En la mecánica, el desensamble de un mecanismo              La decompilación es lo inverso de la compilación:
permite al ingeniero ver las partes que lo integran,        traducir un archivo ejecutable a un archivo en un
sus medidas, los materiales de que está hecho, etc.         lenguaje de más alto nivel. La decompilación es
de modo que esté en condiciones de crear un clon            útil si el código fuente original no está disponible.
del mismo.                                                  La decompilación completamente automatizada no
En el caso del software, la transformación de               es posible, pero aunque se pudiera llevar a cabo el
programas es el acto de cambiar un programa en              resultado obtenido no sería totalmente objetivo:
otro. El lenguaje en el cual el programa es                 este problema es teóricamente equivalente a “The
transformado y el programa que resulta se                   Halting Problem”, y por tanto la decompilación es
denominan lenguaje fuente y lenguaje destino,               computacionalmente irresoluble.
respectivamente.                                            La decompilación no puede ser exitosa para todos
                                                            los programas, pues es difícil alcanzar una
completa separación de datos y del código en           “dependiente o específica del compilador en
máquinas con arquitectura Von Neumann.                 cuestión” y otra forma “genérica o general”.
Además, si se logra un cierto grado de éxito, el
                                                       La primera aproximación intenta ir del ejecutable
programa generado carece de nombres de
                                                       al fuente, basándose en el análisis de la salida
funciones y variables significativos, pues éstos no
                                                       generada por un compilador especifico. Esto por lo
se almacenan normalmente en un archivo
                                                       general da mejores resultados con respecto a
ejecutable (excepto cuando son almacenados con
                                                       generar código fuente que se asemeje al código
propósitos de depuración, situación que se
                                                       fuente original. Esta aproximación es limitada, en
denomina “almacenar la tabla de símbolos en el
                                                       el sentido de que tiene que construirse un
código objeto”).
                                                       decompilador para cada compilador individual.
Algunas personas creen que solamente es posible
lograr que la decompilación recupere los códigos
fuentes en lenguaje ensamblador, pero ya en sí éste    Decompilación Dependiente
no es un problema trivial, nuevamente debido a su
equivalencia al problema de la detención de la         En la decompilación dependiente o específica del
máquina de Turing. Sin embargo, existen en la          compilador, se puede seguir el siguiente proceso:
práctica aproximaciones que se ocupan del              1.   El ejecutable tiene que examinarse para ver si
desensamblaje y la decompilación. Los más                   está comprimido y si es así, tiene que
acertados hasta la fecha hacen uso de información           descomprimirse. O simplemente excluir ese
adicional -conocimiento acerca del compilador               tipo de ejecutable, advirtiéndole la razón al
empleado- o requieren la intervención humana en             usuario. Revisar el aviso de copyright para
las partes más complejas del proceso del                    verificar que el compilador y la versión sean
desensamblaje. Puede incluso ser posible para               las correctas. Una sola versión del
ciertos     decompiladores,       el   decompilar           decompilador puede ampliarse a múltiples
automáticamente una fracción grande de                      versiones del mismo compilador usando los
programas de código máquina provenientes del                archivos que contengan los datos críticos para
mundo real, no sólo ejercicios académicos.                  cada uno.
Sea como fuere, esta traducción se alcanza                  Se debe examinar el ejecutable para depurar
generalmente en varias fases en las cuales un               información y conservar esa información,
lenguaje de alto nivel primero se traduce a una             posiblemente en un archivo temporal. Esto
representación intermedia. La selección de la               puede ayudar a detectar librerías y recuperar
instrucción entonces traduce la representación              nombres de funciones y variables. Se puede
intermedia a instrucciones de máquina. El proceso           construir una lista ligada que permita observar
de la compilación generalmente también implica              qué partes del programa se conocen
un número de pasadas al código fuente. Por                  (completamente o parcialmente), y por lo
ejemplo, normalizaciones al programa, tales como            tanto, cuáles no se conocen. Cada nodo debe
poner las instrucciones en forma canónica,                  tener el tipo de memoria (código/dato),
simplificaciones algebraicas y varias formas de             nombre de la función, contenido si está
optimización de programas.                                  disponible y tipo de código (librería/usuario).
Las técnicas de la decompilación fueron utilizadas     2.   Como siguiente paso se debe determinar el
inicialmente en los años 60 para ayudar en la               punto de inicio del ejecutable, esto podría ser
migración de programas de una plataforma a otra.            el código de inicio de C que se traduciría como
Desde entonces, se han utilizado para ayudar en la
recuperación del código fuente perdido, en la          int main (int argc,
depuración (debugging) para eliminar errores de                  char *argv[],...)
programas, en la localización de virus, compresión     Más importante, el código de inicio indica dónde
de programas, recuperación de vistas de alto nivel     se han inicializado las variables y cuáles son sus
–diagramas de análisis y diseño- de programas, y       valores. Como no se puede conocer, inicialmente,
más.                                                   el tamaño o tipo de tales variables, examinar estos
                                                       datos puede ayudar a encontrar los tipos flotantes,
                                                       los dobles, las cadenas de caracteres, y quizá los
Aproximaciones a la                                    enteros. Buscando por patrones de repetición de
Decompilación                                          entradas de tipo/tamaño, se podría (tentativamente)
                                                       identificar arreglos de tipo estándar y de
Existen dos formas distintas de atacar el proceso de   estructuras. Se puede diferenciar entre arreglos y
decompilación: una forma que pudiéramos llamar
variables múltiples escalares en una            línea   5.   Concentrarse en una función a la vez, no
examinando el código que las referencia.                     siguiendo las llamadas a funciones. El código
                                                             de entrada a la función informa acerca de las
3.   El siguiente paso es desensamblar, siguiendo
                                                             variables automáticas, y el examen del código
     el flujo del programa principal, observando las
                                                             puede revelar el tamaño y probablemente
     direcciones de las funciones llamadas y las
                                                             también el tipo. El mismo tipo de análisis
     direcciones de inicio de las instrucciones
                                                             aplicado al área de las variables inicializadas
     ejecutadas. Las áreas de confusión (donde un
                                                             se puede utilizar para localizar estructuras.
     goto es dirigido a la mitad de una
     instrucción) pueden ser ensambladas en línea            El segundo paso para una función es
     (y marcarlas como tal) siguiendo siempre la             identificar llamadas a funciones y el código
     ejecución del programa. Se emite una                    que le pasa parámetros a la función. Para el
     advertencia cuando es probable que lo                   paso de valores que no son solamente
     realizado no sea correcto. Luego se puede ver           operaciones de carga/descarga, se puede crear
     si las funciones invocadas corresponden a               un nuevo nodo de código que contenga el
     cualquiera en la lista de información.                  código que genera el valor que es cargado.
     Entonces, se repite recursivamente para cada            Para funciones donde los tipos de parámetros
     rutina llamada, revisando la lista de                   son conocidos, se puede ajustar la información
     información, y comparando el código con la              acerca de las variables involucradas (por
     biblioteca para ese compilador. Cualquier               ejemplo, identificar una variable de archivo
     módulo de bilbioteca conocido puede                     “FILE *”). Esta es una forma de
     eliminarse previa consideración, excepto                concordancia de patrones, pero debe realizarse
     cuando una función de biblioteca llama a otras          antes de avanzar para que sea más fácil.
     funciones; entonces, se puede también
                                                             El paso tres es la identificación de plantillas,
     eliminar las funciones llamadas, etc.
                                                             para cualquiera de las plantillas que se han
     Conociendo qué es lo que hacen las diferentes
                                                             determinado para el compilador. Conforme se
     interrupciones (INT), se pueden delimitar
                                                             van identificando los segmentos de código y el
     áreas que sean de datos. Cuando este proceso
                                                             código fuente, se crea un nodo de código, el
     se haya realizado (y éste involucra varios
                                                             cuál agrega el código fuente generado al
     pasos), se desarrolla un enorme árbol de
                                                             binario. La identificación de plantillas debe
     información acerca del ejecutable, y se puede
                                                             realizarse recursivamente para identificar
     producir un archivo de lenguaje ensamblador
                                                             ciclos anidados, etc. El código ajustado para
     intermedio que tenga la biblioteca descubierta
                                                             los ciclos los identifica como: for, while ó
     (incluso si no había información depurada),
     variables estáticas inicializadas identificadas         do, si no el ciclo no interesa y puede elegirse
     junto con sus valores iniciales.                        de forma arbitraria. Esto conducirá a
                                                             identificar sentencias switch, case, if y
4.   Una vez que se tiene la versión                         llamadas de funciones, convertidas en código
     desensamblada, junto con nuestra lista de               en línea por las instrucciones del
     información, se puede comenzar el proceso               preprocesador “#pragma inline”. Cuando
     real de decompilación. Se puede usar una lista          se encuentra código controlado por #pragma,
     ligada de ramificación; cada nodo indica el             debe colocarse el enunciado pragma en el
     nombre de la función (determinada de la                 código fuente; La localización actual depende
     información depurada o sintetizada), y un               de que si el pragma puede utilizarse como un
     apuntador a la lista de código para esa función.
                                                             bloque de código local o para el archivo entero
     El nodo de la lista de código indica el tipo de
                                                             (y hay un #pragma correspondiente que lo
     código contenido (fuente, binario, o
     ensamblado en línea), un apuntador a memoria            desactiva).
     que contiene el fuente del ASCII, y un                  El paso cuatro busca el código en línea que
     apuntador a un binario no desensamblado.                tiene una representación directa del fuente y
     Como el código es desensamblado, las                    agrega el código fuente al nodo de código. Ese
     entradas en la lista de código se dividen y se          es el código que reúne una o más variables, las
     mezclan; cuando la función completa es                  modifica, y pone uno o más valores de retorno.
     desensamblada, hay una única entrada en la              Se debe poner atención a las fuentes de
     lista de código. El binario se retiene hasta que        variables de registro (desde la lista de
     la     función    ha     sido    desensamblada          automáticas) de manera que el fuente pueda
     completamente.                                          identificar correctamente la variable original.
                                                             El condicional en las instrucciones if puede
                                                             determinarse en este punto, ya que ahora es
posible identificar el código (inmediato) de la     equivalencias. Se generan problemas cuando en el
     comparación.                                        código original se fuerza el cambio de tipo
                                                         (casting). También los tipos enumerados y otros
6.   Cualquier cosa que se haya dejado en este
                                                         tipos que son equivalentes a los tipos estándares,
     punto probablemente puede convertirse en
                                                         no pueden recuperarse.
     código en línea del ensamblador. En cualquier
     caso, ésta es la última posición para retornar.     La detección de los tipos arreglos y tipos apuntador
                                                         no es difícil: los tipos estructurados, especialmente
                                                         cuando se utilizan uniones, generan problemas
Decompilación Independiente                              extra.
La segunda aproximación se caracteriza por
analizar la semántica del ejecutable, y de este
análisis se deriva un archivo fuente equivalente, sin
                                                         Reglas de Traducción de
hacer uso de información acerca de qué compilador        Código para Lenguajes de
fue utilizado para generar el ejecutable. El código
fuente generado no puede asemejarse en todo al           Alto Nivel
original. La ventaja es que el método trabaja para
cualquier compilador que pudiera haberse                 El ensamblador es, a fin de cuentas, un lenguaje de
utilizado.                                               programación como cualquier otro. Teóricamente,
                                                         si se cuenta con la definición de la gramática del
1.   Se asume que se inicia con la salida de             mismo, pudiera construirse un parser que
     ensamblador del desensamblador, que también         reconociera el código fuente, lo estructurase en
     contiene las etiquetas propias. Se podría leer el   forma de un árbol de análisis sintáctico, y
     archivo entero, dentro de la memoria, y             posteriormente recorrer dicho árbol para generar
     agrupar instrucciones en bloques, basados en        código en C o algún otro lenguaje de alto nivel.
     las etiquetas.
                                                         En la práctica, para poder realizar la ingeniería
2.   Decodificar cada instrucción en más                 inversa de código de Ensamblador, se deben hallar
     operaciones primitivas, para así evitar todos       las estructuras de control básicas presentes en el
     los diferentes modos de direccionamiento. La        código fuente de ensamblador, y traducirlas a un
     mayoría de las instrucciones sólo se modifican      lenguaje de mayor nivel. El problema es que la
     en registros o direcciones de memoria.              gramática de ningún ensamblador toma en
3.   A partir de esto, debe ser posible determinar       cuenta dichas estructuras de control. Esto se
     qué registros se leen y escriben por cada           debe a que la mayor parte de las instrucciones del
     bloque (asumiendo que las direcciones de            ensamblador      se   mapean       directamente    a
     memoria se refieren a variables C). Basado en       instrucciones de la capa ISA, y por ello la
     ello se puede hacer un análisis de flujo, para      estructura gramatical del lenguaje ensamblador
     encontrar si hay algún registro de variables        tiende a tomar la forma de un conjunto de líneas,
     detectadas (mapped).                                cada una de las cuáles está compuesta por una
                                                         etiqueta opcional (para identificarla en caso de
4.   Si esto se ha llevado a cabo, se puede              saltos o llamados a subrrutinas), una instrucción de
     determinar cuáles son las expresiones que son       ensamblador directamente traducible a lenguaje
     calculadas por las instrucciones para cada          máquina, y un comentario opcional.
     almacén a una variable (también las basadas
     en registros o memoria). Se necesitara la           Bajo estas circunstancias, es responsabilidad
     normalización de esta expresión.                    completa del programador de lenguaje
                                                         Ensamblador, instrumentar las estructuras de
5.   Ahora, se tiene que reconocer las instrucciones     control secuenciales, selectivas y repetitivas
     de alto nivel que resultaron en la estructura del   mediante combinaciones más o menos extensas de
     bloque, y los saltos entre ellos. Desde aquí es     instrucciones de este lenguaje, usando para ello
     posible empezar a generar el código que             tantas líneas de código como sea necesario♦. La
     solamente tratará operaciones con bytes,            problemática estriba en traducir un código que no
     words, longwords y flotantes (doubles).             necesariamente se pensó y programó con buenas
Para la reconstrucción de tipos, primero se              técnicas estructuradas ni modulares, a un código
necesitan técnicas de resolución de tipos, siempre y
cuando los parámetros sean pasados en llamadas a         
                                                           En ello estriba la dificultad de aprender a
funciones, o cuando se asignan de uno a otro. La         programar en lenguaje Ensamblador: la creación de
manera de hacer esto es asignar un tipo único a          las estructuras de control es responsabilidad del
cada variable y parámetro, y derivar reglas de           programador, y no del compilador.
estructurado y modular en un lenguaje de alto          •   Bertelsons, Boris y Mathias Rasch. PC al
nivel.                                                     Límite, Programación Avanzada. Ed.
A diferencia del Ensamblador, un programa en               Computec-Marcombo. ISBN 970-15-0085-7.
lenguaje C puede construirse utilizando                •   Cifuentes, Cristina. Reverse Compilation
cualquier combinación sintácticamente correcta             Techniques. Tesis Doctoral, Australia, 1994.
de estructuras for, while, do..while, if,
switch, etc. La gramática de C cuenta con clases       •   Godfrey, J. Terry. Lenguaje Ensamblador
sintácticas para describir y reconocer cada una de         para     Microcomputadoras      IBM. Ed.
ellas, y crear el respectivo árbol de análisis             Prentice-Hall. ISBN 968-880-204-2.
sintáctico para después traducirlas a Ensamblador o    •   Lemone, Karen A. Fundamentos de
a lenguaje máquina.                                        Compiladores. Ed. CECSA. ISBN 968-26-
Y aquí es donde se encuentra el reto del estado del        1297-7.
arte de esta disciplina:                               •   O’Gorman, John. Systematic Decompilation.
Describir      gramáticas      que     sean    un          Tesis Doctoral. Irlanda, 1991.
superconjunto de las gramáticas habituales de
los lenguajes ensambladores, pero que agrupen          •   Pratt, Terrence y Marvin V. Zelkowitz.
las instrucciones de éstos con el objeto de                Lenguajes de Programación, Diseño e
reconocer estructuras de control secuenciales,             Implementación. Ed. Prentice-Hall. ISBN 0-
selectivas y repetitivas, llamados a funciones y           13-678012-1.
procedimientos, operaciones aritméticas y              •   Teufel, Schmidt y Teufel. Compiladores,
lógicas, todo ello traducible posteriormente a un          Conceptos Fundamentales. Ed. Addison-
lenguaje de alto nivel.                                    Wesley Iberoamericana. ISBN 0-201-65365-6.
Para ello, es necesario revisar la relación entre      •   Tischer, Michael y Bruno Jennrich. PC
instrucciones Ensamblador y estructuras de control         Interno, Programación de Sistemas. Ed.
de alto nivel, con el afán de definir reglas de            Computec-Marcombo. ISBN 970-15-0079-2.
reconocimiento de patrones estructurales, que
posteriormente puedan usarse para reconocer tales
patrones y traducir el código a lenguaje de alto
nivel.


Conclusiones
Se necesita formalizar la enseñanza de la ingeniería
inversa en las aulas de las Facultades e Institutos
de México, puesto que las empresas líderes interna-
cionales emplean a discreción tales técnicas, y no
conocerlas nos pone en desventaja.
Cuanto mayor sea el número de profesionales que
conozcan y apliquen la ingeniería inversa de códi-
go fuente, tanto mayor será nuestro conocimiento
respecto a las reglas de reconocimiento de patrones
estructurales que es necesario aplicar, en distintos
tipos de compiladores.


Bibliografía
•   Abel, Peter. Lenguaje Ensamblador y
    Programación para PC IBM y Compatibles.
    Ed. Pearson. ISBN 968-880-708-7.
•   Aho, Sethi y Ullman. Compiladores,
    Principios, Técnicas y Herramientas. Ed.
    Pearson. ISBN 968-444-333-1.

Mais conteúdo relacionado

Mais procurados

Multiple access control protocol
Multiple access control protocol Multiple access control protocol
Multiple access control protocol meenamunesh
 
Handoff or Handover and Types
Handoff or Handover and Types Handoff or Handover and Types
Handoff or Handover and Types Dhruv Agarwal
 
Wireless communication is 95 stander cdma
Wireless communication is 95 stander cdmaWireless communication is 95 stander cdma
Wireless communication is 95 stander cdmaVijay Kumar
 
Introduction to Mobile Ad hoc Networks
Introduction to Mobile Ad hoc NetworksIntroduction to Mobile Ad hoc Networks
Introduction to Mobile Ad hoc NetworksSayed Chhattan Shah
 
Dynamic synchronous transfer mode
Dynamic synchronous transfer modeDynamic synchronous transfer mode
Dynamic synchronous transfer modeShamama Kamal
 
Csma(carriers sense-multiple-acess)
Csma(carriers sense-multiple-acess) Csma(carriers sense-multiple-acess)
Csma(carriers sense-multiple-acess) Rajan Kandel
 
mobile computing - Unit 1 Material.pdf
mobile computing - Unit 1 Material.pdfmobile computing - Unit 1 Material.pdf
mobile computing - Unit 1 Material.pdfdeepapriya28
 
2 g planning-optimization-part-5
2 g planning-optimization-part-52 g planning-optimization-part-5
2 g planning-optimization-part-5Rizwan Javed
 
نقل الصوت عبر برتوكول النت
نقل الصوت عبر برتوكول النتنقل الصوت عبر برتوكول النت
نقل الصوت عبر برتوكول النتasmaa2015
 
Asynchronous Transfer Mode (ATM)
Asynchronous Transfer Mode (ATM)Asynchronous Transfer Mode (ATM)
Asynchronous Transfer Mode (ATM)Agreeta Sharma
 
Weightless - a new standard, a new technology
Weightless - a new standard, a new technologyWeightless - a new standard, a new technology
Weightless - a new standard, a new technologyDhruvit Rajpura
 

Mais procurados (15)

Multiple access control protocol
Multiple access control protocol Multiple access control protocol
Multiple access control protocol
 
Handoff or Handover and Types
Handoff or Handover and Types Handoff or Handover and Types
Handoff or Handover and Types
 
Wireless communication is 95 stander cdma
Wireless communication is 95 stander cdmaWireless communication is 95 stander cdma
Wireless communication is 95 stander cdma
 
Introduction to Mobile Ad hoc Networks
Introduction to Mobile Ad hoc NetworksIntroduction to Mobile Ad hoc Networks
Introduction to Mobile Ad hoc Networks
 
Dynamic synchronous transfer mode
Dynamic synchronous transfer modeDynamic synchronous transfer mode
Dynamic synchronous transfer mode
 
Csma(carriers sense-multiple-acess)
Csma(carriers sense-multiple-acess) Csma(carriers sense-multiple-acess)
Csma(carriers sense-multiple-acess)
 
mobile computing - Unit 1 Material.pdf
mobile computing - Unit 1 Material.pdfmobile computing - Unit 1 Material.pdf
mobile computing - Unit 1 Material.pdf
 
Códigos
Códigos Códigos
Códigos
 
Investigación técnicas de modulación
Investigación técnicas de modulaciónInvestigación técnicas de modulación
Investigación técnicas de modulación
 
2 g planning-optimization-part-5
2 g planning-optimization-part-52 g planning-optimization-part-5
2 g planning-optimization-part-5
 
نقل الصوت عبر برتوكول النت
نقل الصوت عبر برتوكول النتنقل الصوت عبر برتوكول النت
نقل الصوت عبر برتوكول النت
 
Asynchronous Transfer Mode (ATM)
Asynchronous Transfer Mode (ATM)Asynchronous Transfer Mode (ATM)
Asynchronous Transfer Mode (ATM)
 
Weightless - a new standard, a new technology
Weightless - a new standard, a new technologyWeightless - a new standard, a new technology
Weightless - a new standard, a new technology
 
Application Layer
Application LayerApplication Layer
Application Layer
 
Error correction, ARQ, FEC
Error correction, ARQ, FECError correction, ARQ, FEC
Error correction, ARQ, FEC
 

Semelhante a Ingeniería Inversa de Código Fuente (20)

LENGUAJE en C
LENGUAJE en CLENGUAJE en C
LENGUAJE en C
 
Informe lpi
Informe lpiInforme lpi
Informe lpi
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Ts101924450
Ts101924450Ts101924450
Ts101924450
 
BRANDON VELASQUEZ
BRANDON VELASQUEZBRANDON VELASQUEZ
BRANDON VELASQUEZ
 
Ts101924450
Ts101924450Ts101924450
Ts101924450
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Fundamentos del programación de diseño web
Fundamentos del programación de  diseño webFundamentos del programación de  diseño web
Fundamentos del programación de diseño web
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Unidad3 130504163038-phpapp02 (1)
Unidad3 130504163038-phpapp02 (1)Unidad3 130504163038-phpapp02 (1)
Unidad3 130504163038-phpapp02 (1)
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Unidad 3 margie
Unidad 3 margieUnidad 3 margie
Unidad 3 margie
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
UNIDAD 3
UNIDAD 3 UNIDAD 3
UNIDAD 3
 
Unidad 3
Unidad 3Unidad 3
Unidad 3
 
Proyecto fernando compiladores 1
Proyecto fernando compiladores 1Proyecto fernando compiladores 1
Proyecto fernando compiladores 1
 

Mais de José Enrique Alvarez Estrada

Elon Musk: el verdadero Ironman [detrás de Tesla Motors, SpaceX y SolarCity]
Elon Musk: el verdadero Ironman [detrás de Tesla Motors, SpaceX y SolarCity]Elon Musk: el verdadero Ironman [detrás de Tesla Motors, SpaceX y SolarCity]
Elon Musk: el verdadero Ironman [detrás de Tesla Motors, SpaceX y SolarCity]José Enrique Alvarez Estrada
 
Utilidad e impacto de las redes sociales versión 1.5
Utilidad e impacto de las redes sociales versión 1.5Utilidad e impacto de las redes sociales versión 1.5
Utilidad e impacto de las redes sociales versión 1.5José Enrique Alvarez Estrada
 
¡Crea tu propio Lab de Ciencias con tu Computadora o Smartphone!
¡Crea tu propio Lab de Ciencias con tu Computadora o Smartphone!¡Crea tu propio Lab de Ciencias con tu Computadora o Smartphone!
¡Crea tu propio Lab de Ciencias con tu Computadora o Smartphone!José Enrique Alvarez Estrada
 
De aventón... Una historia de TERROR en [y con] el transporte público
De aventón... Una historia de TERROR en [y con] el transporte públicoDe aventón... Una historia de TERROR en [y con] el transporte público
De aventón... Una historia de TERROR en [y con] el transporte públicoJosé Enrique Alvarez Estrada
 
De ingeniero a hacker... ¡y de hacker a maker! La necesidad de más práctica e...
De ingeniero a hacker... ¡y de hacker a maker! La necesidad de más práctica e...De ingeniero a hacker... ¡y de hacker a maker! La necesidad de más práctica e...
De ingeniero a hacker... ¡y de hacker a maker! La necesidad de más práctica e...José Enrique Alvarez Estrada
 

Mais de José Enrique Alvarez Estrada (20)

Video Mapping con Open Source
Video Mapping con Open SourceVideo Mapping con Open Source
Video Mapping con Open Source
 
Video Mapping con Open Source
Video Mapping con Open SourceVideo Mapping con Open Source
Video Mapping con Open Source
 
BAT 2 CLI, CLI 2 COW, COW 2 GUI
BAT 2 CLI, CLI 2 COW, COW 2 GUIBAT 2 CLI, CLI 2 COW, COW 2 GUI
BAT 2 CLI, CLI 2 COW, COW 2 GUI
 
Clubes de ciencia
Clubes de cienciaClubes de ciencia
Clubes de ciencia
 
Elon Musk: el verdadero Ironman [detrás de Tesla Motors, SpaceX y SolarCity]
Elon Musk: el verdadero Ironman [detrás de Tesla Motors, SpaceX y SolarCity]Elon Musk: el verdadero Ironman [detrás de Tesla Motors, SpaceX y SolarCity]
Elon Musk: el verdadero Ironman [detrás de Tesla Motors, SpaceX y SolarCity]
 
Cómo el Open Source Cambió mi Vida
Cómo el Open Source Cambió mi VidaCómo el Open Source Cambió mi Vida
Cómo el Open Source Cambió mi Vida
 
Breve historia de la propiedad industrial
Breve historia de la propiedad industrialBreve historia de la propiedad industrial
Breve historia de la propiedad industrial
 
Utilidad e impacto de las redes sociales versión 1.5
Utilidad e impacto de las redes sociales versión 1.5Utilidad e impacto de las redes sociales versión 1.5
Utilidad e impacto de las redes sociales versión 1.5
 
Taller "Small Data con SQL"
Taller "Small Data con SQL"Taller "Small Data con SQL"
Taller "Small Data con SQL"
 
De profesor a emprendedor
De profesor a emprendedorDe profesor a emprendedor
De profesor a emprendedor
 
¡Crea tu propio Lab de Ciencias con tu Computadora o Smartphone!
¡Crea tu propio Lab de Ciencias con tu Computadora o Smartphone!¡Crea tu propio Lab de Ciencias con tu Computadora o Smartphone!
¡Crea tu propio Lab de Ciencias con tu Computadora o Smartphone!
 
Las sinrazones de la Educación Superior
Las sinrazones de la Educación SuperiorLas sinrazones de la Educación Superior
Las sinrazones de la Educación Superior
 
De aventón... Una historia de TERROR en [y con] el transporte público
De aventón... Una historia de TERROR en [y con] el transporte públicoDe aventón... Una historia de TERROR en [y con] el transporte público
De aventón... Una historia de TERROR en [y con] el transporte público
 
Grammars and Syntax
Grammars and SyntaxGrammars and Syntax
Grammars and Syntax
 
Pensamiento STEM Guiado por Datos
Pensamiento STEM Guiado por DatosPensamiento STEM Guiado por Datos
Pensamiento STEM Guiado por Datos
 
De ingeniero a hacker... ¡y de hacker a maker! La necesidad de más práctica e...
De ingeniero a hacker... ¡y de hacker a maker! La necesidad de más práctica e...De ingeniero a hacker... ¡y de hacker a maker! La necesidad de más práctica e...
De ingeniero a hacker... ¡y de hacker a maker! La necesidad de más práctica e...
 
Las apps en el Sector Educativo
Las apps en el Sector EducativoLas apps en el Sector Educativo
Las apps en el Sector Educativo
 
Pirámide organizacional
Pirámide organizacionalPirámide organizacional
Pirámide organizacional
 
De homo sapiens a homo deus
De homo sapiens a homo deusDe homo sapiens a homo deus
De homo sapiens a homo deus
 
Inducción al Sistema de Posgrado y MIGA
Inducción al Sistema de Posgrado y MIGAInducción al Sistema de Posgrado y MIGA
Inducción al Sistema de Posgrado y MIGA
 

Ingeniería Inversa de Código Fuente

  • 1. Ingeniería Inversa de Código Fuente José Enrique Alvarez Estrada (jeae@prodigy.net.mx) Elvia Morales Turrubiates (emorales@pampano.unacar.mx) Resumen Nadie pone en duda la importancia de la ingeniería como disciplina del conocimiento humano. Pero pocas personas saben que esta disciplina posee una contraparte: la llamada ingeniería inversa. El objetivo de la ingeniería, es desarrollar la solución a un problema a partir de la nada. En cambio, la inge- niería inversa propone solucionar ese mismo problema, pero a partir de alguna tecnología existente, cuyo fun- cionamiento no se conoce (al menos no totalmente), pero que se sabe tiene el potencial de resolverlo total o parcialmente. Si bien no existe una licenciatura en ingeniería inversa, es un hecho que muchos ingenieros dedican su vida profesional a esta disciplina. Pero, curiosamente, muy poco o nada se habla de ella en las currículas universi- tarias, y jamás se enseña formalmente. De hecho, en muchos círculos el hablar de ingeniería inversa todavía es un tabú, y si bien se sabe y se acepta que la mayor parte de las empresas la utilizan, nadie quiere reconocer- lo abiertamente. El objetivo de esta ponencia es divulgar la importancia de esta disciplina, presentando su estado del arte para la rama particular de la ingeniería inversa de código fuente. Las técnicas de transformación de programas se Introducción utilizan en muchas áreas de la ingeniería de Se puede definir a la ingeniería inversa como el software incluyendo la construcción de proceso mediante el cual una tecnología o producto compiladores, la visualización de software, la se analiza, con el fin de conocer los componentes generación de documentación y la actualización que lo integran y la forma en que éstos interactúan, automatizada del software. En todas estas para lograr finalmente una comprensión cabal de aplicaciones podemos distinguir dos aspectos su modo de funcionamiento, con el objetivo principales, por ejemplo, uno donde el lenguaje probable de construir una tecnología similar. La fuente y destino son diferentes (las traducciones) y ingeniería inversa toma un producto cuyo formato otro aspecto cuando son iguales (la reformulación). presenta un bajo grado de abstracción, y obtiene Estos panoramas principales se pueden refinar en una nueva presentación del mismo, con una un número de aspectos secundarios típicos abstracción mayor. basados en su efecto sobre el nivel de Sin duda, cada rama del conocimiento ha abstracción de un programa y en la medida desarrollado sus propias técnicas de ingeniería que preservan la semántica de un programa. inversa. Por ejemplo, en el caso de la química, el análisis espectrográfico de los componentes que forman una substancia (digamos, un fármaco) Decompilación puede utilizarse para crear una substancia similiar. En la mecánica, el desensamble de un mecanismo La decompilación es lo inverso de la compilación: permite al ingeniero ver las partes que lo integran, traducir un archivo ejecutable a un archivo en un sus medidas, los materiales de que está hecho, etc. lenguaje de más alto nivel. La decompilación es de modo que esté en condiciones de crear un clon útil si el código fuente original no está disponible. del mismo. La decompilación completamente automatizada no En el caso del software, la transformación de es posible, pero aunque se pudiera llevar a cabo el programas es el acto de cambiar un programa en resultado obtenido no sería totalmente objetivo: otro. El lenguaje en el cual el programa es este problema es teóricamente equivalente a “The transformado y el programa que resulta se Halting Problem”, y por tanto la decompilación es denominan lenguaje fuente y lenguaje destino, computacionalmente irresoluble. respectivamente. La decompilación no puede ser exitosa para todos los programas, pues es difícil alcanzar una
  • 2. completa separación de datos y del código en “dependiente o específica del compilador en máquinas con arquitectura Von Neumann. cuestión” y otra forma “genérica o general”. Además, si se logra un cierto grado de éxito, el La primera aproximación intenta ir del ejecutable programa generado carece de nombres de al fuente, basándose en el análisis de la salida funciones y variables significativos, pues éstos no generada por un compilador especifico. Esto por lo se almacenan normalmente en un archivo general da mejores resultados con respecto a ejecutable (excepto cuando son almacenados con generar código fuente que se asemeje al código propósitos de depuración, situación que se fuente original. Esta aproximación es limitada, en denomina “almacenar la tabla de símbolos en el el sentido de que tiene que construirse un código objeto”). decompilador para cada compilador individual. Algunas personas creen que solamente es posible lograr que la decompilación recupere los códigos fuentes en lenguaje ensamblador, pero ya en sí éste Decompilación Dependiente no es un problema trivial, nuevamente debido a su equivalencia al problema de la detención de la En la decompilación dependiente o específica del máquina de Turing. Sin embargo, existen en la compilador, se puede seguir el siguiente proceso: práctica aproximaciones que se ocupan del 1. El ejecutable tiene que examinarse para ver si desensamblaje y la decompilación. Los más está comprimido y si es así, tiene que acertados hasta la fecha hacen uso de información descomprimirse. O simplemente excluir ese adicional -conocimiento acerca del compilador tipo de ejecutable, advirtiéndole la razón al empleado- o requieren la intervención humana en usuario. Revisar el aviso de copyright para las partes más complejas del proceso del verificar que el compilador y la versión sean desensamblaje. Puede incluso ser posible para las correctas. Una sola versión del ciertos decompiladores, el decompilar decompilador puede ampliarse a múltiples automáticamente una fracción grande de versiones del mismo compilador usando los programas de código máquina provenientes del archivos que contengan los datos críticos para mundo real, no sólo ejercicios académicos. cada uno. Sea como fuere, esta traducción se alcanza Se debe examinar el ejecutable para depurar generalmente en varias fases en las cuales un información y conservar esa información, lenguaje de alto nivel primero se traduce a una posiblemente en un archivo temporal. Esto representación intermedia. La selección de la puede ayudar a detectar librerías y recuperar instrucción entonces traduce la representación nombres de funciones y variables. Se puede intermedia a instrucciones de máquina. El proceso construir una lista ligada que permita observar de la compilación generalmente también implica qué partes del programa se conocen un número de pasadas al código fuente. Por (completamente o parcialmente), y por lo ejemplo, normalizaciones al programa, tales como tanto, cuáles no se conocen. Cada nodo debe poner las instrucciones en forma canónica, tener el tipo de memoria (código/dato), simplificaciones algebraicas y varias formas de nombre de la función, contenido si está optimización de programas. disponible y tipo de código (librería/usuario). Las técnicas de la decompilación fueron utilizadas 2. Como siguiente paso se debe determinar el inicialmente en los años 60 para ayudar en la punto de inicio del ejecutable, esto podría ser migración de programas de una plataforma a otra. el código de inicio de C que se traduciría como Desde entonces, se han utilizado para ayudar en la recuperación del código fuente perdido, en la int main (int argc, depuración (debugging) para eliminar errores de char *argv[],...) programas, en la localización de virus, compresión Más importante, el código de inicio indica dónde de programas, recuperación de vistas de alto nivel se han inicializado las variables y cuáles son sus –diagramas de análisis y diseño- de programas, y valores. Como no se puede conocer, inicialmente, más. el tamaño o tipo de tales variables, examinar estos datos puede ayudar a encontrar los tipos flotantes, los dobles, las cadenas de caracteres, y quizá los Aproximaciones a la enteros. Buscando por patrones de repetición de Decompilación entradas de tipo/tamaño, se podría (tentativamente) identificar arreglos de tipo estándar y de Existen dos formas distintas de atacar el proceso de estructuras. Se puede diferenciar entre arreglos y decompilación: una forma que pudiéramos llamar
  • 3. variables múltiples escalares en una línea 5. Concentrarse en una función a la vez, no examinando el código que las referencia. siguiendo las llamadas a funciones. El código de entrada a la función informa acerca de las 3. El siguiente paso es desensamblar, siguiendo variables automáticas, y el examen del código el flujo del programa principal, observando las puede revelar el tamaño y probablemente direcciones de las funciones llamadas y las también el tipo. El mismo tipo de análisis direcciones de inicio de las instrucciones aplicado al área de las variables inicializadas ejecutadas. Las áreas de confusión (donde un se puede utilizar para localizar estructuras. goto es dirigido a la mitad de una instrucción) pueden ser ensambladas en línea El segundo paso para una función es (y marcarlas como tal) siguiendo siempre la identificar llamadas a funciones y el código ejecución del programa. Se emite una que le pasa parámetros a la función. Para el advertencia cuando es probable que lo paso de valores que no son solamente realizado no sea correcto. Luego se puede ver operaciones de carga/descarga, se puede crear si las funciones invocadas corresponden a un nuevo nodo de código que contenga el cualquiera en la lista de información. código que genera el valor que es cargado. Entonces, se repite recursivamente para cada Para funciones donde los tipos de parámetros rutina llamada, revisando la lista de son conocidos, se puede ajustar la información información, y comparando el código con la acerca de las variables involucradas (por biblioteca para ese compilador. Cualquier ejemplo, identificar una variable de archivo módulo de bilbioteca conocido puede “FILE *”). Esta es una forma de eliminarse previa consideración, excepto concordancia de patrones, pero debe realizarse cuando una función de biblioteca llama a otras antes de avanzar para que sea más fácil. funciones; entonces, se puede también El paso tres es la identificación de plantillas, eliminar las funciones llamadas, etc. para cualquiera de las plantillas que se han Conociendo qué es lo que hacen las diferentes determinado para el compilador. Conforme se interrupciones (INT), se pueden delimitar van identificando los segmentos de código y el áreas que sean de datos. Cuando este proceso código fuente, se crea un nodo de código, el se haya realizado (y éste involucra varios cuál agrega el código fuente generado al pasos), se desarrolla un enorme árbol de binario. La identificación de plantillas debe información acerca del ejecutable, y se puede realizarse recursivamente para identificar producir un archivo de lenguaje ensamblador ciclos anidados, etc. El código ajustado para intermedio que tenga la biblioteca descubierta los ciclos los identifica como: for, while ó (incluso si no había información depurada), variables estáticas inicializadas identificadas do, si no el ciclo no interesa y puede elegirse junto con sus valores iniciales. de forma arbitraria. Esto conducirá a identificar sentencias switch, case, if y 4. Una vez que se tiene la versión llamadas de funciones, convertidas en código desensamblada, junto con nuestra lista de en línea por las instrucciones del información, se puede comenzar el proceso preprocesador “#pragma inline”. Cuando real de decompilación. Se puede usar una lista se encuentra código controlado por #pragma, ligada de ramificación; cada nodo indica el debe colocarse el enunciado pragma en el nombre de la función (determinada de la código fuente; La localización actual depende información depurada o sintetizada), y un de que si el pragma puede utilizarse como un apuntador a la lista de código para esa función. bloque de código local o para el archivo entero El nodo de la lista de código indica el tipo de (y hay un #pragma correspondiente que lo código contenido (fuente, binario, o ensamblado en línea), un apuntador a memoria desactiva). que contiene el fuente del ASCII, y un El paso cuatro busca el código en línea que apuntador a un binario no desensamblado. tiene una representación directa del fuente y Como el código es desensamblado, las agrega el código fuente al nodo de código. Ese entradas en la lista de código se dividen y se es el código que reúne una o más variables, las mezclan; cuando la función completa es modifica, y pone uno o más valores de retorno. desensamblada, hay una única entrada en la Se debe poner atención a las fuentes de lista de código. El binario se retiene hasta que variables de registro (desde la lista de la función ha sido desensamblada automáticas) de manera que el fuente pueda completamente. identificar correctamente la variable original. El condicional en las instrucciones if puede determinarse en este punto, ya que ahora es
  • 4. posible identificar el código (inmediato) de la equivalencias. Se generan problemas cuando en el comparación. código original se fuerza el cambio de tipo (casting). También los tipos enumerados y otros 6. Cualquier cosa que se haya dejado en este tipos que son equivalentes a los tipos estándares, punto probablemente puede convertirse en no pueden recuperarse. código en línea del ensamblador. En cualquier caso, ésta es la última posición para retornar. La detección de los tipos arreglos y tipos apuntador no es difícil: los tipos estructurados, especialmente cuando se utilizan uniones, generan problemas Decompilación Independiente extra. La segunda aproximación se caracteriza por analizar la semántica del ejecutable, y de este análisis se deriva un archivo fuente equivalente, sin Reglas de Traducción de hacer uso de información acerca de qué compilador Código para Lenguajes de fue utilizado para generar el ejecutable. El código fuente generado no puede asemejarse en todo al Alto Nivel original. La ventaja es que el método trabaja para cualquier compilador que pudiera haberse El ensamblador es, a fin de cuentas, un lenguaje de utilizado. programación como cualquier otro. Teóricamente, si se cuenta con la definición de la gramática del 1. Se asume que se inicia con la salida de mismo, pudiera construirse un parser que ensamblador del desensamblador, que también reconociera el código fuente, lo estructurase en contiene las etiquetas propias. Se podría leer el forma de un árbol de análisis sintáctico, y archivo entero, dentro de la memoria, y posteriormente recorrer dicho árbol para generar agrupar instrucciones en bloques, basados en código en C o algún otro lenguaje de alto nivel. las etiquetas. En la práctica, para poder realizar la ingeniería 2. Decodificar cada instrucción en más inversa de código de Ensamblador, se deben hallar operaciones primitivas, para así evitar todos las estructuras de control básicas presentes en el los diferentes modos de direccionamiento. La código fuente de ensamblador, y traducirlas a un mayoría de las instrucciones sólo se modifican lenguaje de mayor nivel. El problema es que la en registros o direcciones de memoria. gramática de ningún ensamblador toma en 3. A partir de esto, debe ser posible determinar cuenta dichas estructuras de control. Esto se qué registros se leen y escriben por cada debe a que la mayor parte de las instrucciones del bloque (asumiendo que las direcciones de ensamblador se mapean directamente a memoria se refieren a variables C). Basado en instrucciones de la capa ISA, y por ello la ello se puede hacer un análisis de flujo, para estructura gramatical del lenguaje ensamblador encontrar si hay algún registro de variables tiende a tomar la forma de un conjunto de líneas, detectadas (mapped). cada una de las cuáles está compuesta por una etiqueta opcional (para identificarla en caso de 4. Si esto se ha llevado a cabo, se puede saltos o llamados a subrrutinas), una instrucción de determinar cuáles son las expresiones que son ensamblador directamente traducible a lenguaje calculadas por las instrucciones para cada máquina, y un comentario opcional. almacén a una variable (también las basadas en registros o memoria). Se necesitara la Bajo estas circunstancias, es responsabilidad normalización de esta expresión. completa del programador de lenguaje Ensamblador, instrumentar las estructuras de 5. Ahora, se tiene que reconocer las instrucciones control secuenciales, selectivas y repetitivas de alto nivel que resultaron en la estructura del mediante combinaciones más o menos extensas de bloque, y los saltos entre ellos. Desde aquí es instrucciones de este lenguaje, usando para ello posible empezar a generar el código que tantas líneas de código como sea necesario♦. La solamente tratará operaciones con bytes, problemática estriba en traducir un código que no words, longwords y flotantes (doubles). necesariamente se pensó y programó con buenas Para la reconstrucción de tipos, primero se técnicas estructuradas ni modulares, a un código necesitan técnicas de resolución de tipos, siempre y cuando los parámetros sean pasados en llamadas a  En ello estriba la dificultad de aprender a funciones, o cuando se asignan de uno a otro. La programar en lenguaje Ensamblador: la creación de manera de hacer esto es asignar un tipo único a las estructuras de control es responsabilidad del cada variable y parámetro, y derivar reglas de programador, y no del compilador.
  • 5. estructurado y modular en un lenguaje de alto • Bertelsons, Boris y Mathias Rasch. PC al nivel. Límite, Programación Avanzada. Ed. A diferencia del Ensamblador, un programa en Computec-Marcombo. ISBN 970-15-0085-7. lenguaje C puede construirse utilizando • Cifuentes, Cristina. Reverse Compilation cualquier combinación sintácticamente correcta Techniques. Tesis Doctoral, Australia, 1994. de estructuras for, while, do..while, if, switch, etc. La gramática de C cuenta con clases • Godfrey, J. Terry. Lenguaje Ensamblador sintácticas para describir y reconocer cada una de para Microcomputadoras IBM. Ed. ellas, y crear el respectivo árbol de análisis Prentice-Hall. ISBN 968-880-204-2. sintáctico para después traducirlas a Ensamblador o • Lemone, Karen A. Fundamentos de a lenguaje máquina. Compiladores. Ed. CECSA. ISBN 968-26- Y aquí es donde se encuentra el reto del estado del 1297-7. arte de esta disciplina: • O’Gorman, John. Systematic Decompilation. Describir gramáticas que sean un Tesis Doctoral. Irlanda, 1991. superconjunto de las gramáticas habituales de los lenguajes ensambladores, pero que agrupen • Pratt, Terrence y Marvin V. Zelkowitz. las instrucciones de éstos con el objeto de Lenguajes de Programación, Diseño e reconocer estructuras de control secuenciales, Implementación. Ed. Prentice-Hall. ISBN 0- selectivas y repetitivas, llamados a funciones y 13-678012-1. procedimientos, operaciones aritméticas y • Teufel, Schmidt y Teufel. Compiladores, lógicas, todo ello traducible posteriormente a un Conceptos Fundamentales. Ed. Addison- lenguaje de alto nivel. Wesley Iberoamericana. ISBN 0-201-65365-6. Para ello, es necesario revisar la relación entre • Tischer, Michael y Bruno Jennrich. PC instrucciones Ensamblador y estructuras de control Interno, Programación de Sistemas. Ed. de alto nivel, con el afán de definir reglas de Computec-Marcombo. ISBN 970-15-0079-2. reconocimiento de patrones estructurales, que posteriormente puedan usarse para reconocer tales patrones y traducir el código a lenguaje de alto nivel. Conclusiones Se necesita formalizar la enseñanza de la ingeniería inversa en las aulas de las Facultades e Institutos de México, puesto que las empresas líderes interna- cionales emplean a discreción tales técnicas, y no conocerlas nos pone en desventaja. Cuanto mayor sea el número de profesionales que conozcan y apliquen la ingeniería inversa de códi- go fuente, tanto mayor será nuestro conocimiento respecto a las reglas de reconocimiento de patrones estructurales que es necesario aplicar, en distintos tipos de compiladores. Bibliografía • Abel, Peter. Lenguaje Ensamblador y Programación para PC IBM y Compatibles. Ed. Pearson. ISBN 968-880-708-7. • Aho, Sethi y Ullman. Compiladores, Principios, Técnicas y Herramientas. Ed. Pearson. ISBN 968-444-333-1.