Erickson abre el libro defendiendo una idea concreta: hacking no es romper sistemas, es resolver problemas creativamente explotando reglas que nadie pensó que se podían usar de esa manera. La misma mentalidad que lleva a un programador a encontrar un atajo elegante en un algoritmo es la que lleva a otro a encontrar un buffer overflow en un parser XML.
La diferencia entre el "hacker bueno" y el "hacker malo" no está en la técnica, está en la intención y el contexto legal. La técnica es la misma:
- Leer atentamente la especificación.
- Encontrar el caso que el autor no contempló.
- Forzar al sistema a ese caso.
- Observar qué pasa.
El conocimiento no es ilegal. La acción puede serlo.
Aprender cómo funciona un buffer overflow en tu propia máquina es estudio. Lanzarlo contra un servidor ajeno sin autorización es delito. El libro te enseña la primera parte; la segunda es responsabilidad tuya.
El libro se centra en C y x86 porque:
- C no protege al programador. No hay bounds checking, no hay garbage collector, los punteros son enteros disfrazados. Eso lo hace ideal para entender qué pasa de verdad en memoria.
- El compilador genera ensamblador. Si no entiendes ensamblador, no puedes leer lo que el atacante ve cuando ataca tu binario.
- El sistema operativo está escrito en C. Linux, los servicios de red, las librerías estándar. Si quieres entender al objetivo, lee su lengua materna.
El libro original (2008) usa x86 32-bit. Estos apuntes asumen x86-64 (64 bits) porque es lo que tienen los PCs actuales. Las diferencias clave que aparecerán a lo largo del libro:
| Concepto | x86 (libro) | x86-64 (estos apuntes) |
|---|---|---|
| Registros generales | eax, ebx, ecx, edx, esi, edi, esp, ebp |
rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp (+ r8–r15) |
| Puntero de instrucción | eip |
rip |
| Tamaño de puntero | 4 bytes | 8 bytes |
| Calling convention | argumentos en la pila | primeros 6 argumentos en rdi, rsi, rdx, rcx, r8, r9 (System V AMD64) |
| Direcciones típicas | 0x08048xxx |
0x55555555xxxx (PIE) |
Cuando el libro diga "argumento en [ebp+8]", en x86-64 con la calling convention SysV el argumento está en rdi. Esto cambia mucho los exploits de buffer overflow del libro: hay que reescribir el shellcode y los offsets.
- gcc — compilador. Flags importantes:
-gañade símbolos de debug (necesario paragdb).-fno-stack-protectordesactiva el canary (necesario para overflows del libro).-z execstackpermite ejecutar código en la pila (necesario para shellcode clásico).-no-piedesactiva PIE (binario en direcciones fijas, más fácil de explotar).-m32compila como x86 32-bit (a veces útil para reproducir el libro literalmente).
- gdb — debugger. Configurado con sintaxis Intel:
echo "set disassembly intel" > ~/.gdbinit
- objdump — desensamblador estático.
objdump -M intel -d binario. - strace / ltrace — traza syscalls y llamadas a libc.
- readelf — inspección de binarios ELF.
- xxd / hexdump — hexdump de archivos.
- python3 / perl — generar payloads (
python3 -c 'import sys; sys.stdout.buffer.write(b"A"*64)'). - nasm — ensamblador para escribir shellcode.
Linux moderno bloquea muchas de las técnicas del libro por defecto. Para los capítulos 0x300+ desactivaré temporalmente:
# ASLR — direcciones aleatorias
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # off
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space # on (default)# ptrace — restricción de attach a procesos
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope # off (cualquier proceso puede attach)
echo 1 | sudo tee /proc/sys/kernel/yama/ptrace_scope # on (solo padre, default)Estas medidas se restauran después de cada sesión.
- Leer la sección.
- Reproducir cada ejemplo en mi máquina, copiando el código a
codigo/<seccion>/. - Compilar con
make <seccion>y ejecutar. - Romper algo a propósito (cambiar un valor, alimentar input inesperado) y entender por qué falla.
- Anotar en este capítulo lo que aprendí, con tablas y comandos exactos.
Si no puedo reproducir un ejemplo, no avanzo hasta entender por qué — es la regla más importante del libro.