Ensamblador x86-64
Para explotar binarios y hacer reversing necesitas leer (y a veces escribir) ensamblador: es el lenguaje al que se compila el código y el nivel en el que trabajas cuando manipulas la ejecución. No hace falta dominarlo como un desarrollador de sistemas, pero sí entender registros, instrucciones básicas, cómo funciona el stack y las convenciones de llamada. Esta ficha es la base práctica para pwn-reversing.
Registros (x86-64)
Sección titulada «Registros (x86-64)»# propósito general (64 bits; las versiones de 32/16/8 bits son sub-registros)RAX RBX RCX RDX RSI RDI RBP RSP R8-R15# equivalencias de tamaño (RAX)RAX (64) -> EAX (32) -> AX (16) -> AL (8)# especialesRIP instruction pointer (qué se ejecuta) <- el objetivo del exploitRSP stack pointer (cima del stack)RBP base pointer (marco de la función)RFLAGS flags (resultado de comparaciones: ZF, CF, SF...)Instrucciones esenciales
Sección titulada «Instrucciones esenciales»mov dst, src copiar lea dst, [addr] cargar direcciónadd/sub dst, src aritmética xor/and/or lógicaspush/pop meter/sacar del stackcall func llamar (push RIP + salto) ret retornar (pop RIP)cmp a, b comparar (setea flags)jmp addr salto incondicionalje/jne/jg/jl... saltos condicionales (según flags)nop no hacer nada (0x90) -> útil en shellcode (NOP sled)syscall llamada al sistema (kernel)El stack y los marcos de función
Sección titulada «El stack y los marcos de función»# el stack crece hacia DIRECCIONES BAJAS# al llamar una función:call func -> push de la dirección de retorno, salto a func# prólogo típico:push rbp ; guardar el RBP anteriormov rbp, rsp ; nuevo marcosub rsp, N ; reservar espacio para locales# epílogo:leave ; mov rsp, rbp ; pop rbpret ; pop rip (vuelve a la dirección de retorno guardada)El ret saca de la cima del stack la dirección a la que volver y la pone en RIP. Si controlas lo que hay en esa posición del stack, controlas RIP (base del stack overflow, ver Stack buffer overflow).
Convención de llamada (System V, Linux x86-64)
Sección titulada «Convención de llamada (System V, Linux x86-64)»Clave para exploits: saber en qué registros van los argumentos.
# los primeros 6 argumentos van en registros, en este orden:RDI, RSI, RDX, RCX, R8, R9# el valor de retorno va en RAX# ejemplo: system("/bin/sh") -> RDI = puntero a "/bin/sh", luego call system# argumentos adicionales (7+) van en el stackEsto es por qué en ROP (Return-Oriented Programming (ROP)) buscas gadgets pop rdi; ret — para poner el argumento en RDI antes de llamar a una función.
Sintaxis Intel vs AT&T
Sección titulada «Sintaxis Intel vs AT&T»# Intel (la que usan la mayoría de herramientas de pwn, más legible)mov rax, rbx ; destino, origen# AT&T (gdb por defecto, GCC)mov %rbx, %rax ; origen, destino (orden inverso, % y $)# en gdb: set disassembly-flavor intelLeer ensamblador en la práctica
Sección titulada «Leer ensamblador en la práctica»objdump -d -M intel ./binario # desensamblargdb -> disassemble main # en el debugger (pwndbg/GEF)# en reversing: ghidra/IDA dan pseudo-C + ensamblador lado a lado (ver rev-static)Para la defensa
Sección titulada «Para la defensa»Entender ensamblador no es una defensa en sí, pero es la base para: analizar malware (ver malware), auditar binarios propios, entender exactamente qué hace un exploit, y escribir detecciones precisas. Del lado del desarrollo, los compiladores con mitigaciones (canarios, CFI) insertan comprobaciones a nivel de ensamblador que conviene conocer.
Checklist de dominio
Sección titulada «Checklist de dominio»- Reconozco los registros y sus tamaños (RAX/EAX/AX/AL)
- Entiendo RIP/RSP/RBP y su papel
- Leo las instrucciones básicas (mov, call, ret, jmp, cmp…)
- Explico el prólogo/epílogo y cómo ret controla RIP
- Conozco la convención de llamada (RDI, RSI, RDX…)
- Distingo sintaxis Intel de AT&T
- Desensamblo con objdump/gdb/ghidra
- Entiendo cómo syscall hace llamadas al kernel