dustbyter Posted January 9, 2016 Posted January 9, 2016 (edited) Hi All, I've finally had some time to pick up some development for the pineapple again. Starting working on a Wigle agent that will be set up as a command line infusion/module which the rest of the modules can use also. Right now, I have it able to search for a location based on a mac address, or to pull back some information about all networks that are found when searching by an SSID. Looking for ideas on what else you would like to see implemented. If your interested in trying it out, I have started to run it on my MKV. When developing it on my PC, the results are returned pretty quickly, on the MKV, it takes some time. Not sure where the bottleneck is at this point, but will work on it in the future. Have not tried it on a NANO, as i don't own one yet. You will need to install some packages on the MKV to get this to work correctly. I don't have that list handy right now, but try to run the script and python will tell you what libraries it needs installed. Looking for some feedback. Thanks! Note: Below is the code for the three files you will need to create. Place them in the same directory. Location on the pineapple doesn't matter. To execute the script, the command line is (with sample output): Example run (search by ssid): python testWigleAgent.py -u <username> -p <password> -s <SSID> to search for info per SSID ============================== [*] WIGLE: This user was validated [*] WIGLE: Lat / Long and SSID have been retrived BSSID: 00:13:10:F8:9B:70 ESSID: NavyPier WEP: Y Channel: 6 Latitude: 41.87978745 Longitude: -87.62429047 Example run (search by macid): python testWigleAgent.py -u <username> -p <password> -m <MAC> to get the location for a specific BSSID [*] WIGLE: This user was validated [*] WIGLE: Lat / Long and SSID have been retrived ============================== SSID: NavyPier Latitude: 41.88973236 Longitude: -87.61649323 wigle_query.py #!/usr/bin/env python from uuid import getnode #from Modules.Common import * import sys import re import requests import json import helpers #Inspired and stolen from Jamie Bull (author).. at http://code.activestate.com/recipes/578637-wigle-wifi-geolocation/ class WigleAgent(): #These are the options we will set def __init__(self, username, password): self.agent(username, password) self.mac_address() # required options self.description = "simple WIGLE query" self.language = "python" # options we require user interaction for- format is {Option : [Value, Description]]} self.required_options = {"wigle_user" : ["offtest", "Set WIGLE User-Name"], "wigle_pass" : ["83128312", "Set WIGLE Password"], "mac" : ["00:22:55:DF:C8:01", "Set MAC Address"]} def get_lat_lng_by_mac(self, mac_address): #Start with Credintial check try: self.response = send_user_check() response = self.check_cred_login() if response == 'false': print "[*] Unable to validate this user..." except: #Use this two let user know we had a true login.. print helpers.color('[*] WIGLE: This user was validated', bold=False) pass if mac_address == None: mac_address = self.mac_address if '-' in mac_address: mac_address = mac_address.replace('-', ':') try: self.query_response = self.send_query_location_by_mac(mac_address) #Need to use Try statment since the "message" Key isnt always prsent when conducting query try: message = self.check_query_limit() if message == "too many queries": print "[*]" + message except: #Use pass since we dont have an error... pass response = self.parse_response_mac() except IndexError: response = 'BSSID (MAC) location not known' return response print helpers.color('[*] WIGLE: Lat / Long and SSID have been retrived', bold=False) return response def get_lat_lng_by_ssid(self, ssid): #Start with Credintial check try: self.response = send_user_check() response = self.check_cred_login() if response == 'false': print "[*] Unable to validate this user..." except: #Use this two let user know we had a true login.. print helpers.color('[*] WIGLE: This user was validated', bold=False) pass try: self.query_response = self.send_query_by_SSID(ssid) #Need to use Try statment since the "message" Key isnt always prsent when conducting query try: message = self.check_query_limit() if message == "too many queries": print "[*]" + message except: #Use pass since we dont have an error... pass response = self.parse_response_search() except IndexError: response = 'ESSID (ESSID) location not known' return response print helpers.color('[*] WIGLE: Lat / Long and SSID have been retrived', bold=False) return response def agent(self, username, password): self.agent = requests.Session() self.agent.post('https://wigle.net/api/v1/jsonLogin', data={'credential_0': username, 'credential_1': password, 'destination': '/https://wigle.net/'}) def mac_address(self): mac = hex(getnode()) mac_bytes = [mac[x:x+2] for x in xrange(0, len(mac), 2)] self.mac_address = ':'.join(mac_bytes[1:6]) def send_query_by_SSID(self, ssid): response = self.agent.post(url='https://wigle.net/api/v1/jsonSearch', data={'ssid': ssid,'Query': 'Query'}) #Check for and handle JSON Errors, due to blank returns try: #print "====>>>>" #print json.dumps( response.json(), indent=3 ) #print "<<<<====" #return response.json() return response except ValueError: # includes simplejson.decoder.JSONDecodeError print helpers.color('[*] WIGLE: Decoding JSON has failed', bold=False, warning=True) print helpers.color('[!] Exiting...', bold=True, warning=True) sys.exit() def send_query_location_by_mac(self, mac_address): response = self.agent.post(url='https://wigle.net/api/v1/jsonLocation', data={'netid': mac_address,'Query2': 'Query'}) #Check for and handle JSON Errors, due to blank returns try: return response.json() except ValueError: # includes simplejson.decoder.JSONDecodeError print helpers.color('[*] WIGLE: Decoding JSON has failed', bold=False, warning=True) print helpers.color('[!] Exiting...', bold=True, warning=True) sys.exit() def send_user_check(self): response = self.agent.post() return response.json() # this method does not process the response. it returns the object to the caller def parse_response_search(self): #print json.dumps( self.query_response.json(), indent=3 ) return self.query_response def parse_response_mac(self): #print "==================================================" #print self.query_response #print "==================================================" lat = self.get_lat() lng = self.get_lng() bssid = self.get_ssid() string = str(self.query_response) return {'lat':lat,'lng':lng, 'bssid':bssid, 'description':string} def get_lat(self): resp_lat = self.query_response['result'][0]['trilat'] return float(resp_lat) def get_lng(self): resp_lng = self.query_response['result'][0]['trilong'] return float(resp_lng) #Request the SSID name of the WIFI point def get_ssid(self): resp_ssid = self.query_response['result'][0]['ssid'] return str(resp_ssid) #Check to see if we reached our limit of 100 querys def check_query_limit(self): resp_message = self.query_response['message'] return str(resp_message) #Check User loign creds def check_cred_login(self): resp_message = self.query_response['success'] return str(resp_message) testWigleAgent.py #!/usr/bin/env python import os import optparse import urllib import requests.packages.urllib3 import re import urlparse import wigle_query import json wa = None def getLocationByMacID(macid): result = wa.get_lat_lng_by_mac(macid) print "==============================" if ( isinstance(result, dict) ): print "SSID: " + result["bssid"] print "Latitude: " + str(result["lat"]) print "Longitude: " + str(result["lng"]) else: print result return def getInformationBySSID(ssid): print "==============================" # result object needs to call .json() to get the actual dict object back result = wa.get_lat_lng_by_ssid(ssid) data = result.json() for key, value in data.iteritems(): if key == "results": for entry in value: print "BSSID: " + entry["netid"] print "ESSID: " + entry["ssid"] print "WEP: " + entry["wep"] print "Channel: " + entry["channel"] print "Latitude: " + entry["trilat"] print "Longitude: " + entry["trilong"] #print "Lasttime: " + entry["lasttime"] print "\n" return def main(): myusage = "usage: %prog -u <wigle username> -p <wigle_password> -n <macid>" #parser = optparse.OptionParser(usage=usage) parser = optparse.OptionParser(usage=myusage) parser.add_option("-u", dest="username", type="string", help="specify wigle username") parser.add_option("-p", dest="password", type="string", help="specify wigle password") parser.add_option("-s", dest="ssid", type="string", help="specify network BSSID") parser.add_option("-m", dest="mac", type="string", help="specify network ESSID") #parser.add_option('-a', dest='address', type='string', help='specify address in format address:state:zip') (options, args) = parser.parse_args() username = options.username password = options.password ssid = options.ssid macid = options.mac #address = options.address if username == None or password == None: print parser.usage exit(0) else: requests.packages.urllib3.disable_warnings() global wa wa = wigle_query.WigleAgent( username, password ) if macid != None and ssid == None: getLocationByMacID(macid) elif ssid != None: getInformationBySSID(ssid) if __name__ == '__main__': main() helpers.py #!/usr/bin/env python import os, sys, types, string, textwrap def color(string, status=True, warning=False, bold=True, blue=False): """ Change text color for the linux terminal, defaults to green. Set "warning=True" for red. stolen from Veil :) """ attr = [] if status: # green attr.append('32') if warning: # red attr.append('31') if bold: attr.append('1') if blue: #blue attr.append('34') return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), string) def formatLong(title, message, frontTab=True, spacing=16): """ Print a long title:message with our standardized formatting. Wraps multiple lines into a nice paragraph format. """ lines = textwrap.wrap(textwrap.dedent(message).strip(), width=50) returnString = "" i = 1 if len(lines) > 0: if frontTab: returnString += "\t%s%s" % (('{0: <%s}'%spacing).format(title), lines[0]) else: returnString += " %s%s" % (('{0: <%s}'%(spacing-1)).format(title), lines[0]) while i < len(lines): if frontTab: returnString += "\n\t"+' '*spacing+lines[i] else: returnString += "\n"+' '*spacing+lines[i] i += 1 return returnString Edited January 14, 2016 by dustbyter Quote
IvanDoe Posted January 9, 2016 Posted January 9, 2016 Thats pretty cool. So based on ssid/mac you find geo location. Few days ago i started messing around with wigle also but i went in different direction. Since there was no access points near me in wigle database online i made local database via wigle for android. Made php script that based on gps cordinates goes thru local wigle database and filters close ssids (50-100meters close). Was thinking of making pineapple change and spoof fake accesspoints based on location. Have option to spoof open only or protected networks as open etc. If anyone thinks this is good or wants it after i clean it up and test more i can release script on github :) Quote
dustbyter Posted January 14, 2016 Author Posted January 14, 2016 Made a bit more progress on this script. Now I can provide a street address and get back 100 networks that are listed near it. The output that is returned from the script is shown below. One could run the command-line module to get the results and then convert them to a format that they can post on Google Maps. Gonna have to see what needs to be done to make this a command-line module. Sample execution: python testWigleAgent.py -u <username> -p <password> -a "1600 Pennsylvania:DC:20500" ============================== [*] WIGLE: This user was validated [*] WIGLE: Lat / Long and SSID have been retrived BSSID: 00:0B:6C:BD:BD:BD ESSID: null WEP: ? Channel: null Latitude: 38.90174103 Longitude: -77.02464294 BSSID: 00:15:AF:17:ED:97 ESSID: GlobalSuiteWireless WEP: N Channel: 0 Latitude: 38.90188217 Longitude: -77.02464294 BSSID: 00:18:0A:81:EB:88 ESSID: DCPL_ MLK_Digital Commons_Staff WEP: 2 Channel: 1 Latitude: 38.89808655 Longitude: -77.02464294 BSSID: 00:18:F8:18:84:1B ESSID: tiger WEP: Y Channel: 11 Latitude: 38.89736938 Longitude: -77.02464294 ... truncated result set .... Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.