¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Fundamentos de ingeniería inversa

Aquí está la lección completa para leer. Crea una cuenta gratuita para practicarla en un laboratorio en vivo.

Laboratorio de máquina virtual12 min de lectura7 comandos

Un archivo sin código fuente

Una empresa encuentra una pequeña herramienta en su propio servidor y nadie recuerda quién la escribió. No hay código fuente, solo el programa. Antes de ejecutarlo, alguien tiene que leer lo que hace. Eso es la ingeniería inversa: averiguar cómo funciona un programa a partir del propio programa.

Al terminar esta lección

Nota

Puedo usar una herramienta para averiguar qué hace un programa sin su código fuente.

La regla que debes recordar

Nota

Este laboratorio sirve para leer cómo funciona un programa, como lo hace quien defiende un sistema o quien estudia compiladores. Úsalo con los programas de tu propio laboratorio y con nada más. Nunca enseña, y nunca debes usarlo para: software malicioso, saltarte la licencia de un programa real, generadores de claves, esconder un programa de un depurador o atacar un programa que no es tuyo. En el Reino Unido eso es delito según la Computer Misuse Act 1990, y en cualquier otro país las leyes también lo castigan.

Palabras clave

  • Binario: un programa tal como lo ejecuta el ordenador, un archivo de instrucciones de máquina.
  • Desensamblador: una herramienta que convierte las instrucciones de máquina en ensamblador legible.
  • Depurador: una herramienta que ejecuta un programa, lo detiene donde tú dices y muestra su memoria.
  • Registro: una memoria diminuta dentro del procesador. En esta máquina, rdi guarda el primer argumento de una llamada.
  • Llamada a biblioteca: una llamada a código ya hecho, como puts, que imprime texto.
  • Llamada al sistema: una petición de un programa al sistema operativo, por ejemplo para escribir.

Para empezar: lo que ya sabes

Nota

Responde mentalmente. 1. ¿Qué es el código fuente? 2. ¿Qué hace un compilador con él? 3. ¿Qué es un argumento de una función? Necesitas la tercera respuesta enseguida.

Antes de empezar

Nota

Pulsa Iniciar el laboratorio en la barra de la parte superior de esta lección. Este laboratorio es una máquina Ubuntu completa para ti, así que tarda un poco más en arrancar que un contenedor. Cada botón Ejecutar escribe su comando en el terminal de la máquina, uno tras otro en la misma sesión. Si uno dice que la máquina aún está arrancando, espera unos segundos y púlsalo otra vez. Para verlos, o para escribir los tuyos, pulsa Abrir terminal en la barra.

Un binario es un archivo que se puede describir

El laboratorio guarda sus programas en la carpeta revlab. hello no esconde ningún secreto: imprime una línea. El comando file dice qué clase de archivo es sin ejecutarlo. Fíjate en ELF, el formato de los programas en Linux, en el procesador para el que se construyó y en not stripped, que significa que los nombres de sus funciones siguen dentro.

Comando
file revlab/hello

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Strings encuentra el texto dentro de un programa

Un programa lleva su texto dentro, legible, lo haya querido mostrar alguien o no. strings imprime cada serie de caracteres legibles, que es una lista larga, así que el comando se queda solo con la línea que contiene Hello. Descubres lo que dice el programa sin ejecutarlo.

Comando
strings revlab/hello | grep Hello

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Comprueba

Consejo

¿De dónde salieron las palabras, si nunca ejecutaste el programa? Respuesta: del interior del archivo: un programa lleva su texto consigo.

Un error frecuente

Advertencia

Mucha gente cree que compilar un programa oculta lo que dice. Compilar cambia la forma, no los hechos: el texto, los nombres de las llamadas y el orden de los pasos siguen ahí. Todo lo que un programa necesita saber para funcionar, un lector puede encontrarlo, así que nunca guardes un secreto en un programa.

Un desensamblador muestra las instrucciones

objdump -d convierte las instrucciones en ensamblador, una por línea. El comando pide solo la función main y se queda con las líneas que mencionan puts: hay una, una llamada (call) a la función de biblioteca que imprime. radare2 hace el mismo trabajo y añade nombres. aa le pide que analice el archivo y pdf @ main imprime la función. Busca el nombre puts y el texto que recibe.

Comando
objdump -d revlab/hello --disassemble=main | grep puts

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Comando
r2 -q -e scr.color=0 -c 'aa' -c 'pdf @ main' revlab/hello 2>/dev/null

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un depurador detiene el programa y muestra su memoria

Ejecuta el programa bajo gdb y deténlo en la primera línea de puts. Por la forma en que funciona una llamada en esta máquina, puts encuentra la dirección de su texto en el registro rdi. x/s $rdi significa: muestra la cadena (string) que hay en esa dirección. Así lees el argumento de una función mientras el programa está en pausa, como leerás una contraseña.

Comando
gdb -batch -ex 'break puts' -ex 'run' -ex 'x/s $rdi' revlab/hello

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Rastrear muestra las llamadas que hace un programa

ltrace imprime cada llamada a biblioteca con sus argumentos, y strace cada llamada al sistema. La primera muestra a puts recibiendo el texto. La segunda muestra al programa pidiendo al sistema operativo que escriba los mismos bytes en la pantalla, con write. Aquí el saludo se envía a ninguna parte para que solo se vea el rastro. Ninguna de las dos obliga a leer ensamblador.

Comando
ltrace revlab/hello

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Comando
strace -e trace=write revlab/hello >/dev/null

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ahora haz el laboratorio

Consejo

Has mirado un programa inofensivo con cada herramienta. Tu laboratorio tiene cinco programas, cada uno con una clave distinta en tu copia, y leerás cada uno con la herramienta que le conviene. Abre el archivo README.md de tu carpeta personal con cat README.md en el terminal y escribe las claves que encuentres en answers.txt.

Comprobación final

Consejo

Responde sin mirar atrás. 1. ¿Qué herramienta lista el texto legible de un programa? 2. ¿Qué herramienta permite detener un programa en marcha y leer su memoria? 3. ¿Qué diferencia hay entre una llamada a biblioteca y una llamada al sistema? 4. ¿Por qué un secreto dentro de un programa nunca es del todo secreto? Respuestas: strings; un depurador, gdb; una llamada a biblioteca va a código ya hecho, una llamada al sistema va al sistema operativo; porque cualquiera puede leer lo que hay en el archivo.

Para el profesorado

Consejo

Esta lección es un pequeño ejemplo de una lección que se trabaja en un laboratorio: los pasos y los botones Ejecutar son la lección, y el laboratorio es la copia de cada alumno. Se trabaja en un laboratorio de VM: cada alumno tiene su propia máquina Ubuntu, y un botón Ejecutar escribe en su terminal y muestra lo que se imprimió. Puntos clave: 1. Un programa se puede leer sin su código fuente. 2. El texto y las llamadas permanecen dentro de un programa compilado. 3. Un depurador muestra la memoria de un programa en marcha. 4. Rastrear muestra las llamadas que hace un programa. Error frecuente: creer que compilar oculta lo que hace un programa. Material: el laboratorio y un navegador. Consejo: pida a la clase que diga qué hace hello antes de usar ninguna herramienta y compruebe después cada hipótesis. El propio laboratorio tiene una comprobación que compara las claves de answers.txt con las generadas para cada copia. Es lectura defensiva de los programas del propio laboratorio y nada más. Copie la lección en su propio módulo para cambiarla, o construya una desde cero con el menú Laboratorio del generador de lecciones.

Sobre este laboratorio y su código: Laboratorio de ingeniería inversa: leer programas con gdb, radare2, strace y ltrace en una VM

¿Enseñas a una clase? Asigna estas lecciones a tus estudiantes con calificación y un laboratorio para cada uno.