#!/usr/bin/env python
#
# This will use the skyhook wireless API to locate a given BSSID
#
# See here for more details:
# http://coderrr.wordpress.com/2008/09/10/get-the-physical-location-of-wireless-router-from-its-mac-address-bssid/
#
# Aaron Peterson & Midnight Research Labs
import socket, sys, httplib, re
class skyhook():
def __init__(self, bssid, outputFile=None):
self.apihost="api.skyhookwireless.com"
self.url="/wps2/location"
self.outputFile=outputFile
self.bssid=self._validateBssid(bssid)
self.results={}
self.reqStr = """
beta
js.loki.com
%s
-50
""" % self.bssid
def _validateBssid(self, bssid):
if not re.compile(r"^([\dabcdef]{2}:){5}[\dabcdef]{2}$", re.I).search(bssid):
print " [*] BSSID [%s] does not appear to be valid" % bssid
sys.exit(1)
bssid = bssid.replace(":", "").upper()
return bssid
def _parseResponse(self, xml):
match = re.compile(r"([^<]*)([^<]*)").search(xml)
if match:
self.results["Latitude"] = match.group(1)
self.results["Longitude"] = match.group(2)
else:
print " [!] Couldn't find basic attributes in response.."
sys.exit(1)
try:
# Sorry, too lazy to use a real xml parser...
# I wish the core python would include simplexmlapi or a xpath implementation
self.results["Street Number"] = re.compile(r"([^<]*)").search(xml).group(1)
self.results["Address"] = re.compile(r"([^<]*)").search(xml).group(1)
self.results["City"] = re.compile(r"([^<]*)").search(xml).group(1)
self.results["Postal Code"] = re.compile(r"([^<]*)").search(xml).group(1)
self.results["County"] = re.compile(r"([^<]*)").search(xml).group(1)
self.results["State"] = re.compile(r"([^<]*)").search(xml).group(1)
self.results["Country"] = re.compile(r"([^<]*)").search(xml).group(1)
except AttributeError:
print " [!] Couldn't find street address..."
def _writeKml(self):
kml = """
%s
Access Point BSSID: %s
%s,%s,0
""" % (self.bssid, self.bssid, self.results["Longitude"], self.results["Latitude"])
f = open(outputFile, "w")
f.write(kml)
f.close()
self.results["Output KML File"] = outputFile
def getLocation(self):
try:
dataLen=len(self.reqStr)
conn = httplib.HTTPSConnection(self.apihost)
conn.putrequest("POST", self.url)
conn.putheader("Content-type", "text/xml")
conn.putheader("Content-Length", str(dataLen))
conn.endheaders()
conn.send(self.reqStr)
except (socket.gaierror, socket.error):
print(" [!] There was a problem when connecting to host [%s]" % (self.apihost))
sys.exit(1)
response = conn.getresponse()
if response.status != 200:
print " [!] There was an error from the sever: [%s %s]" % (response.status, response.reason)
sys.exit(1)
xml = response.read()
if re.compile(r"Unable to locate").search(xml):
print " [!] Unable to find info for [%s]" % bssid
sys.exit(1)
self._parseResponse(xml)
if self.outputFile:
self._writeKml()
return self.results
if __name__=="__main__":
if len(sys.argv) < 2:
print "\tusage: %s (