¿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

Leer ensamblador x86-64 básico

Después de esta lección: Puedo leer unas pocas líneas de ensamblador x86-64 y decir qué hacen.

Lección de 55 min4 comandosLaboratorio de ingeniería inversa: leer programas con gdb, radare2, strace y ltrace en una VM

Qué es el ensamblador

El ensamblador son las instrucciones del procesador escritas con nombres que una persona puede leer. Saber leer unas pocas líneas de ensamblador x86-64 es la base de la ingeniería inversa, porque un binario solo trae eso.

Una instrucción como cmp compara dos valores. La siguiente, como jne, decide a dónde ir según el resultado.

Al final de esta lección

Nota

Puedo leer unas pocas líneas de ensamblador x86-64 y decir qué hacen.

Palabras clave

PalabraQué significaEjemplo
Registrouna casilla muy pequeña dentro del procesadorrax
Instrucciónuna orden sencilla que ejecuta el procesadormov
Operandoel valor o registro con el que trabaja una instrucción
Banderaun bit que recuerda el resultado de la última comparación
Salto condicionaluna instrucción que cambia de camino según una banderajne

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Un registro es una casilla del procesador

Un registro es una casilla muy pequeña dentro del procesador. En x86-64 hay unos pocos con nombre, como rax o rdi. Las instrucciones los leen y los escriben mucho más deprisa que la memoria.

rax guarda 64 bits. Su mitad baja, eax, guarda 32 bits y es la que usa un int de C.

Los registros que más verás

RegistroPara qué suele servir
rax o eaxel resultado de una función
rdiel primer argumento de una llamada
rsiel segundo argumento de una llamada
rspla cima de la pila
rbpla base de la función en curso
ripla instrucción que toca ejecutar

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

mov copia, add suma y sub resta

Usaremos la sintaxis Intel, que también usa radare2. Aquí el destino va primero. mov eax, 5 copia 5 en eax. add eax, 3 suma 3 a eax. sub eax, 1 resta 1.

Entre corchetes, como [rbp-0x4], hay una dirección de memoria: la casilla de una variable local, en la pila. Los números con 0x van en hexadecimal. El primer Run crea stock, un programa de ejemplo nuestro.

Crea el programa de ejemplo stock

Comando
printf '#include <stdio.h>\nint main(void) {\n    int stock = 12;\n    if (stock < 20) { puts("Hay que reponer"); return 1; }\n    puts("Stock suficiente");\n    return 0;\n}\n' | gcc -O0 -no-pie -x c -o /tmp/stock -

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

Lee sus mov, cmp y jg en Intel

Comando
objdump -d /tmp/stock --disassemble=main -M intel | grep -E "mov|cmp|jg" | cut -f3

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

Lee dos de ellas en sintaxis AT&T

Comando
objdump -d /tmp/stock --disassemble=main | grep -E "movl|cmpl" | cut -f3

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

Un error frecuente

Advertencia

Mucha gente lee mov rax, rbx como «copia rax en rbx». En la sintaxis Intel el destino va primero, así que copia rbx en rax. En AT&T, la que usa objdump si no le pides otra, el orden es el contrario. Antes de leer, comprueba qué sintaxis tienes delante.

cmp compara y un salto decide

cmp a, b compara dos valores y anota el resultado en las banderas, sin guardar nada más. La instrucción siguiente decide. jne salta si no eran iguales, jg si el primero era mayor y jle si era menor o igual.

El compilador a veces invierte la condición. if (stock < 20) sale como cmp con 0x13 y jg: salta de largo cuando stock es mayor que 19.

Pasa 0x13 y 0xff a decimal

Comando
printf '%d %d\n' 0x13 0xff

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

Para ir más lejos

Crea otra versión de stock en /tmp/stock2, con stock < 12 en lugar de stock < 20, y lee su cmp con el mismo Run.

Antes de ejecutarlo, escribe qué número hexadecimal esperas ver. Después explica con tus palabras por qué el compilador compara con un número menos que el del código.

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 este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.