Saturday, 27 September 2008

Get the physical location of wireless router from its MAC address (BSSID)

http://coderrr.wordpress.com/2008/09/10/get-the-physical-location-of-wireless-router-from-its-mac-address-bssid/
Get the physical location of wireless router from its MAC address (BSSID)
Filed under: network, ruby, security, slashdot — Tags: network, ruby, security, slashdot — coderrr @ 1:20 am

A nice company called SkyHook Wireless has been war driving the country for years. Basically they’ve been paying people to ride around in cars and record the unique IDs (BSSID, aka MAC address) that your wireless routers broadcast. Doesn’t matter if your router has encryption on or not, its BSSID is still public and in their database (if they’ve driven past your house). They’ve then taken all this information and put it in a huge database. They’ve even made a nice little javascript API which given a BSSID will tell you its longitude and latitude. But it will only let you do this for yourself, only sending BSSIDs which you are in range of.

For their API to work it requires you to install a browser extension. Which contains, along with the extension source code (which is fully viewable, for Firefox at least), some compiled c++ code (loki.dll for windows). So what does the proprietary stuff do? It does the actual query to their API. And what does it send? It asks your wireless card to list all of the BSSIDs that you are in range of and sends those along with the signal strength of each.

So why can’t you just send any BSSID you want? Simple, because they don’t tell you how. The actual query is done inside of their compiled code, so it’s a secret and no one will ever figure it out. Well, only the people that try at least. After reverse engineering their code I did a google search on one of the unique-ish terms in the XML that is used as part of the API call and it seems there are others who know how to use this secret API of theirs.

So to keep things short. Here’s how to query their service to find the physical location of any wireless router whose BSSID you know.

Send an HTTPS POST request to api.skyhookwireless.com/wps2/location with XML in the following format:
view plaincopy to clipboardprint

1.
2.
3.
4.
5. beta
6. js.loki.com
7.

8.

9.
10. 00AA11BB22CC
11. -50
12.

13.






beta
js.loki.com



00AA11BB22CC
-50



You’ll receive back either this (success!):
view plaincopy to clipboardprint

1.
2. 49.242250711.4624963150


49.242250711.4624963150

or this (failure!):
view plaincopy to clipboardprint

1.
2. Unable to locate location


Unable to locate location

Here’s a dirty little ruby script which does the query based on a BSSID you pass in from the command line:
view plaincopy to clipboardprint

1. require 'net/https'
2.
3. mac = ARGV.first.delete(':').upcase
4.
5. req_body = %{
6.
7.
8.
9.
10. beta
11. js.loki.com
12.

13.

14.
15. #{mac}
16. -50
17.

18.

19. }.gsub(/^\s+|[\r\n]/, '')
20.
21. http = Net::HTTP.new('api.skyhookwireless.com', 443)
22. http.use_ssl = true
23.
24. http.start do |h|
25. resp = h.post '/wps2/location', req_body, 'Content-Type' => 'text/xml'
26.
27. if resp.body =~ /([^<]+).+([^<]+)/
28. puts "#$1, #$2"
29. else
30. puts "not found"
31. end
32. end

require 'net/https'

mac = ARGV.first.delete(':').upcase

req_body = %{




beta
js.loki.com



#{mac}
-50


}.gsub(/^\s+|[\r\n]/, '')

http = Net::HTTP.new('api.skyhookwireless.com', 443)
http.use_ssl = true

http.start do |h|
resp = h.post '/wps2/location', req_body, 'Content-Type' => 'text/xml'

if resp.body =~ /([^<]+).+([^<]+)/
puts "#$1, #$2"
else
puts "not found"
end
end

Usage:
getloc.rb aa:bb:cc:dd:ee:ff

Or here’s a one liner for UNIX thanks to George:
view plaincopy to clipboardprint

1. MYMAC=AABBCCDDEEFF && curl --header "Content-Type: text/xml" --data "betajs.loki.com$MYMAC-50" https://api.skyhookwireless.com/wps2/location

MYMAC=AABBCCDDEEFF && curl --header "Content-Type: text/xml" --data "betajs.loki.com$MYMAC-50" https://api.skyhookwireless.com/wps2/location

* note: This API is how the iPhone’s “Locate me” feature works

No comments: