Skip to content

Commit c2bcde2

Browse files
committed
Land rapid7#4377, Support DYNAMIC_BASE templates - resolves rapid7#4366
2 parents 36404eb + 985245e commit c2bcde2

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

lib/msf/util/exe.rb

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,22 @@ def self.to_executable(framework, arch, plat, code = '', opts = {})
147147
nil
148148
end
149149

150+
# Clears the DYNAMIC_BASE flag for a Windows executable
151+
# @param exe [String] The raw executable to be modified by the method
152+
# @param pe [Rex::PeParsey::Pe] Use Rex::PeParsey::Pe.new_from_file
153+
# @return [String] the modified executable
154+
def self.clear_dynamic_base(exe, pe)
155+
c_bits = ("%32d" %pe.hdr.opt.DllCharacteristics.to_s(2)).split('').map { |e| e.to_i }.reverse
156+
c_bits[6] = 0 # DYNAMIC_BASE
157+
new_dllcharacteristics = c_bits.reverse.join.to_i(2)
158+
159+
# PE Header Pointer offset = 60d
160+
# SizeOfOptionalHeader offset = 94h
161+
dll_ch_offset = exe[60, 4].unpack('h4')[0].reverse.hex + 94
162+
exe[dll_ch_offset, 2] = [new_dllcharacteristics].pack("v")
163+
exe
164+
end
165+
150166
def self.to_win32pe(framework, code, opts = {})
151167

152168
# For backward compatability, this is roughly equivalent to 'exe-small' fmt
@@ -168,6 +184,7 @@ def self.to_win32pe(framework, code, opts = {})
168184
# Create a new PE object and run through sanity checks
169185
fsize = File.size(opts[:template])
170186
pe = Rex::PeParsey::Pe.new_from_file(opts[:template], true)
187+
171188
text = nil
172189
pe.sections.each {|sec| text = sec if sec.name == ".text"}
173190

@@ -178,7 +195,7 @@ def self.to_win32pe(framework, code, opts = {})
178195
:template => opts[:template],
179196
:arch => :x86
180197
})
181-
injector.generate_pe
198+
return injector.generate_pe
182199
end
183200

184201
raise RuntimeError, "No .text section found in the template" unless text
@@ -282,6 +299,7 @@ def self.to_win32pe(framework, code, opts = {})
282299
exe[exe.index([cks].pack('V')), 4] = [0].pack("V")
283300
end
284301

302+
exe = clear_dynamic_base(exe, pe)
285303
pe.close
286304

287305
exe
@@ -348,6 +366,7 @@ def self.to_winpe_only(framework, code, opts = {}, arch="x86")
348366
# put the shellcode at the entry point, overwriting template
349367
entryPoint_file_offset = pe.rva_to_file_offset(addressOfEntryPoint)
350368
exe[entryPoint_file_offset,code.length] = code
369+
exe = clear_dynamic_base(exe, pe)
351370
exe
352371
end
353372

@@ -429,7 +448,6 @@ def self.string_to_pushes(string)
429448
end
430449

431450
def self.exe_sub_method(code,opts ={})
432-
433451
pe = self.get_file_contents(opts[:template])
434452

435453
case opts[:exe_type]
@@ -495,7 +513,7 @@ def self.to_win64pe(framework, code, opts = {})
495513
:template => opts[:template],
496514
:arch => :x64
497515
})
498-
injector.generate_pe
516+
return injector.generate_pe
499517
end
500518
opts[:exe_type] = :exe_sub
501519
exe_sub_method(code,opts)

0 commit comments

Comments
 (0)