Shellcode en Linux explicado: de C a los bytes
Cómo funciona el shellcode en Linux —syscalls, registros y código independiente de posición— y cómo ensamblarlo, codificarlo y probarlo de forma segura.
El shellcode en Linux es pequeño porque el kernel hace el trabajo pesado a través de las syscalls. No enlazas contra libc; preparas los registros y le pides al kernel directamente. Si la palabra "shellcode" es nueva para ti, lee antes qué es el shellcode.
Syscalls: x86 vs x64
Las dos arquitecturas difieren en tres cosas que importan para el shellcode:
| x86 | x64 | |
|---|---|---|
| Instrucción de syscall | int 0x80 | syscall |
| Número de syscall | eax | rax |
| Argumentos | ebx, ecx, edx, … | rdi, rsi, rdx, … |
execve es la syscall 11 en x86 y 59 en x64. Si te equivocas de número para la arquitectura, llamas a algo inesperado — un fallo habitual de principiante.
Código independiente de posición
Tus bytes caen en una dirección que no controlas, así que no puedes codificar punteros. El movimiento estándar para las cadenas es apilarlas en la pila y apuntar un registro a la pila:
xor eax, eax
push eax ; terminator
push 0x68732f2f ; "//sh"
push 0x6e69622f ; "/bin"
mov ebx, esp ; ebx now points at the string, wherever it is
Sin sección .data, sin dirección absoluta — funciona sin importar dónde se ejecute el código.
Evitar null bytes
xor eax, eax en lugar de mov eax, 0 no es estilo; la segunda forma se ensambla con null bytes que rompen la entrega basada en cadenas. Todo el oficio del shellcode compacto en Linux consiste en acertar con la lógica mientras esquivas valores de byte prohibidos. Mira null bytes en el shellcode.
Ensamblar a bytes
Escribe el ensamblador, ensámblalo y luego extrae los bytes de .text. Prototipar la lógica en C primero es una buena forma de encontrar las syscalls y los argumentos correctos antes de afinar el ensamblador a mano. Tienes ejemplos completos con sus cadenas de bytes en ejemplos de shellcode.
Orden de las pasadas de codificación
Si tu objetivo prohíbe ciertos bytes, codificas — pero el orden de los encoders importa: una segunda pasada puede reintroducir bytes que la primera eliminó. Esto hace tropezar a la gente constantemente; el razonamiento está en orden del pipeline de encoders.
Pruébalo
Ensambla, codifica para tu conjunto de bad chars y verifica —todo en el cliente— con el builder de Shellcodes, y luego ejecútalo solo dentro de una VM de laboratorio aislada que controles. Solo pruebas autorizadas: uso responsable.