├── .gitignore
├── LICENSE.md
├── README.md
├── network_meta_info.txt
└── probespy.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | location.db
2 | network_meta_info.txt
3 | meta.lst
4 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 stumblebot
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Probespy
2 | Probespy is a dumb and dirty tool for analyzing directed and broadcast probe request data sent by wifi client devices.
3 |
4 | Usage: bash probespy.sh -c
-d
5 | bash probespy.sh -c -d -l <"lat,lng"> -r
6 | bash probespy.sh -c -d -l <"lat,lng"> -r -f
7 | Options:
8 | -c: The directory to read pcap files from
9 | -f: Report output format
10 | Options: html or txt
11 | -d: The directory to write the current report to
12 | -l: The location to bound our SSID search to
13 | -r: The distance to search from the coordinate
14 | designated by -l
15 | -h: Display this help
16 |
--------------------------------------------------------------------------------
/network_meta_info.txt:
--------------------------------------------------------------------------------
1 | Air Canada: Airline wifi. Traveller. Air Canada Customer.
2 | Apple Store: Retail wifi. Apple Customer.
3 | ATL Free Wi-Fi: Airport wifi. Traveller. Visited ATL Airport, GA, USA.
4 | att-wifi: ISP Shared wifi. Potential AT&T Customer.
5 | attwifi: ISP Shared wifi. Potential AT&T Customer.
6 | Belle Tire Free wiFi: Retail Wifi. Belle Tire Customer.
7 | BestBuy: Retail wifi. BestBuy Customer.
8 | BlackHatUSA2017: BlackHat Briefings 2017 attendee. Visited Las Vegas, NV, USA.
9 | Boingo Hotspot: Airport wifi. Traveller.
10 | BostonMkt_Guest: Restaraunt wifi. Boston Market Customer.
11 | C21 Guest: Century 21 Customer.
12 | CARite-Public: Retail wifi. CARite Customer.
13 | City of Minneapolis Public WiFi: Visited Minneapolis, MN, USA.
14 | CMU: University wifi. Visited Carnegie Mellon University, PA, USA.
15 | CMU-GUEST: University wifi. Visited Carnegie Mellon University, PA, USA.
16 | CMU-SECURE: University wifi. Visited Carnegie Mellon University, PA, USA.
17 | Comfort_Suites: Hotel wifi. Traveller. Comfort Inn and Suites Customer.
18 | CountryInnAndSuites: Hotel wifi. Traveller. Country Inn and Suites Customer.
19 | Courtyard_GUEST: Hotel wifi. Traveller. Courtyard Customer.
20 | DefCon: Defcon attendee. Visited Las Vegas, NV, USA.
21 | DefCon-Open: Defcon attendee. Visited Las Vegas, NV, USA. RENEGADE.
22 | DeltaSkyClub: Airport wifi. Traveller. Delta Airlines Customer.
23 | - DEN Airport Free WiFi: Airport wifi. Traveller. Visited DEN Airport, CO, USA.
24 | Detroit Airport Wi-Fi: Airport wifi. Traveller. Visited DTW Airport, MI, USA.
25 | Devonport City Wifi: Visited Devonport, Tasmania, Austrialia.
26 | FairField Inn_GUEST: Hotel wifi. Traveller. FairField Inn Customer.
27 | _Free_MDW_Wi-Fi: Traveller. Visited MDW Airport, IL, USA.
28 | _Free_ORD_Wi-Fi: Traveller. Visited ORD Airport, IL, USA.
29 | ...GAP_FREE: Retail wifi. GAP Customer.
30 | gogoinflight: Traveller. Airplane wifi.
31 | GSP-Public-WiFi: Airport wifi. Traveller. Visited GSP Airport, SC, USA.
32 | Guest T-Mobile: ISP Shared wifi. Potential T-Mobile Customer.
33 | Helsinki Airport Free Wi-Fi: Traveller. Visited Helsinki Airport, Finland.
34 | HFHS.Guest: Hospital wifi.
35 | hhonors: Hotel wifi. Traveller. Hilton Customer.
36 | hhonors_guest: Hotel wifi. Traveller. Hilton Customer.
37 | hhonors-public: Hotel wifi. Traveller. Hilton Customer.
38 | HI Express: Hotel wifi. Traveller. Holiday Inn Customer.
39 | HI Express Rocklin: Hotel wifi. Traveller. Holiday Inn Customer. Visited Rocklin, CA, USA.
40 | HI Express Shreveport Park Plaza: Hotel wifi. Traveller. Holiday Inn Customer. Visited Shreveport, LA, USA.
41 | Hyatt_GUEST: Hotel wifi. Traveller. Hyatt Customer.
42 | Hyatt Guest Room: Hotel wifi. Traveller. Hyatt Customer.
43 | hyatt: Hotel wifi. Traveller. Hyatt Customer.
44 | @Hyatt_WiFi: Hotel wifi. Traveller. Hyatt Customer.
45 | Ihopmanager: Restaraunt wifi.
46 | KFC FREE WIFI: Restaraunt wifi. KFC Customer.
47 | kroger: Grocery wifi. Kroger Customer.
48 | Kroger Guest: Grocery wifi. Kroger Customer.
49 | KrogerWiFi: Grocery wifi. Kroger Customer.
50 | _LAX Free WiFi: Airport wifi. Traveller. Visited LAX Airport, CA, USA.
51 | Loews_Guest: Loews Customer.
52 | Marriott_Guest: Hotel wifi. Traveller. FairField Inn Customer.
53 | McCarran_WiFi: Airport wifi. Traveler. Visited LAS Airport, NV, USA.
54 | McDonalds Free WiFi: Restaraunt wifi. McDonalds customer.
55 | MGMResorts-WiFi: Hotel wifi. MGM resorts customer.
56 | MicroCenterGuest: Retail wifi: MicroCenter Customer.
57 | Oddfellows Cafe + Bar: Restaraunt wifi. Visited Seattle, WA, USA.
58 | Olgas Guest: Restaraunt wifi. Olgas Diner Customer.
59 | Olgas Guest WiFi: Restaraunt wifi. Olgas Diner Customer.
60 | Origins Wi-Fi: Retail wifi. Origins Customer.
61 | Otopeni Airport: Airport wifi. Traveller. Visited Otopeni Airport, Romania.
62 | PANERA: Restaraunt wifi. Panera Bread Customer
63 | Park Plaza County Hall: Hotel wifi. Visited London, United Kingdom.
64 | PartyCity_Guest: Retail wifi. PartyCity Customer.
65 | Penn Station: Restaraunt wifi. Penn Station Sandwiches Customer.
66 | Qdoba_Guest: Restaraunt wifi. Qdoba Customer.
67 | Quality Inn and Suites: Hotel wifi. Traveller. Quality Inn Customer.
68 | Renaissance_GUEST: Hotel wifi. Traveller. Renaissance Customer.
69 | ResidenceInn_GUEST: Hotel wifi. Traveller. FairField Inn Customer.
70 | Roeper Student and Guest: Edu wifi.
71 | Schiphol_Airport_WiFi: Airport wifi. Traveller. Visited Amsterdam, Netherlands.
72 | SEATAC-FREE-WIFI: Airport wifi. Traveller. Visited SEATAC Airport, WA, USA.
73 | Sheraton-Guestrooms: Hotel wifi. Traveller. Sheraton Customer.
74 | Sheraton-Meeting Room: Hotel wifi. Traveler. Sheraton Customer.
75 | SouthwestWiFi: Airline wifi. Traveller. Southwest Customer.
76 | Target Guest Wi-Fi: Retail wifi. Target Customer.
77 | Toronto Pearson Wi-Fi: Airport wifi. Traveller. Visited
78 | United_Wi-Fi: Airline wifi. Traveller. United Airlines customer.
79 | WestinGuestrooms: Hotel wifi. Traveller. Westin Customer.
80 | WholeFoodsMarket: Grocery wifi. Whole Foods Customer.
81 | WIFI_BEN_GURION_AIRPORT: Airport wifi. Traveller. Visited Ben Gurion Airport, Israel.
82 | #WiFi@Changi: Airport wifi. Traveller. Visited Changi Airport, Shanghai, China.
83 | www.hotel-litz.de: Hotel wifi. Traveller. Hotel Litz Customer. Visited Langenargen, Germany.
84 | xfinitywifi: ISP Shared wifi. Potential Xfinity Customer.
85 | YOW Free Wi-Fi: Airport wifi. Traveller. Visited YOW Airport, Ottawa, CA.
86 | Five Guys: Restaraunt wifi. Five Guys Customer.
87 | FlyDulles: Airport wifi. Traveller. Visited IAD Airport, Washington DC, USA.
88 | VenetianPalazzoWifi: Hotel wifi. Traveller. Visited Venetian Palazzo Hotel, Las Vegas, NV, USA.
89 | McCarran WiFi: Airport wifi. Traveller. Visited Las Vegas, NV, USA.
90 | united_club: Airline wifi. Traveller. United airlines customer.
91 | Copthorne Lobby Wireless: Hotel wifi. Traveller. Copthorne Hotels Customer.
92 | flyCOS: Airport wifi. Traveller. Visited Colorado Springs, CO, USA.
93 |
--------------------------------------------------------------------------------
/probespy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #TODO
4 |
5 | #PRIORITY
6 | #Local database lookup via wigle export
7 | # figure out what is going on with the elongated lat/lng values
8 |
9 | #BACK BURNER
10 | #Centralized report file
11 | #re-integrate direct capture from probespy
12 | #update report display format
13 | #active attacks??
14 | # beacon honeypotting
15 | #Change maps lookups to use openstreetmaps instead of google
16 | #cluster search
17 | #turn on/off location lookup
18 | #sort a given run by profile mac address or SSID
19 | #wigle billing status check
20 |
21 | #set the internal field separator to newlines only
22 | IFS=$'\n'
23 |
24 | #Initialize variables from probespy.conf
25 | #check if probespy.conf is present
26 | if [[ -z "$(ls probespy.conf 2>/dev/null)" ]];
27 | then
28 | echo probespy.conf could not be found. Please create probespy.conf, in the current directory
29 | echo and add a WIGLE API key in the following format.
30 | echo
31 | echo WIGLE_API_KEY=\'AID0d903714c7d78b11a222c77b956d4200:e6c1b74909bdba1f331776e5b96c696f\'
32 | else
33 | echo -n found probespy.conf
34 | #source conf file
35 | . probespy.conf
36 | if [[ -z "$(echo $WIGLE_API_KEY)" ]]
37 | then
38 | echo
39 | echo No WIGLE API key present. Please add a key to probespy.conf in the following format
40 | echo
41 | echo WIGLE_API_KEY=\'AID0d903714c7d78b11a222c77b956d4200:e6c1b74909bdba1f331776e5b96c696f\'
42 | else
43 | echo ...WIGLE API key loaded
44 | fi
45 | fi
46 |
47 | userLocation=''
48 |
49 | usage() {
50 | echo "Usage: bash probespy.sh -c -d " 1>&2
51 | echo " bash probespy.sh -c -d -l <\"lat,lng\"> -r " 1>&2
52 | echo " bash probespy.sh -c -d -l <\"lat,lng\"> -r -f " 1>&2
53 | # echo " bash probespy.sh -c -i " 1>&2
54 | echo "Options:" 1>&2
55 | echo "-c: The directory to read pcap files from" 1>&2
56 | # echo "-i: The network interface to capture packets on" 1>&2
57 | echo "-f: Report output format" 1>&2
58 | echo " Options: html or txt" 1>&2
59 | echo "-d: The directory to write the current report to" 1>&2
60 | echo "-l: The location to bound our SSID search to" 1>&2
61 | echo "-r: The distance to search from the coordinate" 1>&2
62 | echo " designated by -l" 1>&2
63 | echo "-h: Display this help" 1>&2
64 | exit 1
65 | }
66 |
67 | #Defining script arguments
68 | while getopts :i:c:f:d:l:r:g:h option;
69 | do
70 | case $option in
71 | i)
72 | networkInterface=$OPTARG
73 | ;;
74 | c)
75 | captureDir=$OPTARG
76 | ;;
77 | f)
78 | reportFormat=$OPTARG
79 | ;;
80 | d)
81 | reportDir=$OPTARG
82 | ;;
83 | l)
84 | userLocation=$OPTARG
85 | ;;
86 | r)
87 | searchRange=$OPTARG
88 | ;;
89 | g)
90 | clusterSearch=$OPTARG
91 | ;;
92 | h)
93 | usage
94 | ;;
95 | \?)
96 | echo "Invalid option: $OPTARG" 1>&2
97 | ;;
98 | :)
99 | echo "option -$OPTARG needs an argument"
100 | exit
101 | ;;
102 | esac
103 | done
104 |
105 | #Check for valid capture directory
106 | if [ -z "$captureDir" ]; then
107 | echo "ERROR: supply a directory to read pcaps from"
108 | echo ""
109 | usage
110 | fi
111 |
112 | #Check for valid report directory
113 | if [ -z "$reportDir" ]; then
114 | echo "ERROR: supply a directory to write report results"
115 | echo ""
116 | usage
117 | fi
118 |
119 | #Check for valid report format
120 | if [ -z $reportFormat ]
121 | then
122 | echo Report format was not set, Defaulting to TXT
123 | echo Report will be printed to stdout
124 | elif [ $reportFormat == html ]
125 | then
126 | echo Report format set to HTML
127 | echo Report will be written to $reportDir
128 | elif [ $reportFormat == txt ]
129 | then
130 | echo Report format set to TXT
131 | echo Report will be printed to stdout
132 | else
133 | echo Reporting format $reportFormat is not recognized
134 | echo Please define a valid reporting format
135 | echo ------------------------------------------------
136 | usage
137 | exit
138 | fi
139 |
140 | #Check for valid user location
141 | if [ -z $userLocation ]
142 | then
143 | echo No location has been set to search within
144 | userLocation='NOLOC'
145 | else
146 | echo -n Location has been set as: $userLocation
147 | fi
148 |
149 | echo \ with a range of $searchRange miles
150 | echo ------------------------------------------------
151 |
152 | #INITIALIZE MORE VARIABLES
153 | dataDir=$(echo $reportDir/data/)
154 | htmlDir=$(echo $reportDir/html/)
155 |
156 |
157 | ###############################################################################
158 | #INTERFACE CAPTURE JUNK
159 | # This code is not in use right now, but may be helpful if/when I re-implement
160 | # capturing probe requests from within probespy
161 | ###############################################################################
162 | #clear pcaps from the ringbuffer directory
163 | #rm ringbuffer/*
164 |
165 | #TEMP DEV SHIT
166 | #copy other pcaps in here because sometimes we dont have awesome sampling
167 | #cp ~/a/directory/*.cap ringbuffer/
168 |
169 | #start capturing data from the wireless adapter to the ringbuffer
170 | #tshark -i $networkInterface -f 'subtype probereq ' -w ringbuffer/probes -b duration:60 -b files:5 2> /dev/null &
171 | #alternate with no ringbuffer
172 | #tshark -i $networkInterface -f 'subtype probereq ' -w ringbuffer/probes 2> /dev/null &
173 |
174 | #wait for tshark to write something to the ringbuffer dir before continuing
175 | : '
176 | echo -n "Initializing tshark"
177 | while [ -z $(ls ringbuffer/) ]
178 | do
179 | echo -n .
180 | sleep 1
181 | done
182 | echo
183 |
184 | #wait for a probe request before continuing
185 | echo -n "Waiting for probe requests"
186 | while [[ -z $probes ]]
187 | do
188 | probes=$(for files in $( ls ringbuffer/);do sudo tshark -r ringbuffer/$files 2> /dev/null | grep "Probe Request, SN=";done)
189 | echo -n .
190 | sleep 1
191 | done
192 | echo
193 |
194 |
195 | # perform the rest of these actions until the user cancels the script
196 | while [ 1 -eq 1 ]
197 | do
198 | #'
199 | #END OF INTERFACE CAPTURE JUNK
200 | ###############################################################################
201 |
202 | ###############################################################################
203 | #CREATE REPORTING DIRECTORIES
204 | ###############################################################################
205 | report_directory (){
206 | mkdir -p $dataDir
207 | mkdir -p $htmlDir
208 | }
209 |
210 |
211 | ###############################################################################
212 | #PCAP PROCESSING FUNCTION
213 | ###############################################################################
214 | pcap_processing () {
215 |
216 | #clear profile data from previous runs
217 | rm -f $dataDir/*.mac
218 | rm -f $dataDir/*.compressed
219 |
220 | #do some actions for each pcap in the current captureDir
221 | for i in $( ls $captureDir/ | grep .cap );
222 | do
223 | echo 'Processing '$i
224 | #for each pcap, output only the data we want, the source MAC and SSID
225 | for j in $( tshark -r $captureDir/$i -Y 'wlan.fc.type_subtype == 0x0004' -Nn 2> /dev/null | egrep -v 'SSID=Broadcast$|\[Malformed Packet\]$' | cut -d '.' -f 2- | cut -d ' ' -f 2,12- | sed 's/ SSID=/,SSID=/g' | egrep -v "\\\001|\\\002|\\\003|\\\004|\\\005|\\\006|\\\016|\\\017|\\\020|\\\021|\\\022|\\\023|\\\024|\\\025|\\\026|\\\027|\\\030|\\\031|\\\032|\\\033|\\\034|\\\035|\\\036|\\\037|\\\277|\\\357" | sort -u )
226 | do
227 | echo $j >> $dataDir/$i.compressed
228 | #also create a file for each source mac from each capture file
229 | touch $dataDir/$(echo $j | cut -d , -f 1).mac
230 | done
231 | done
232 |
233 | echo Compressing results
234 | #Create a sorted, deduped file of all data
235 | cat $dataDir/*.compressed | sort -u > $dataDir/all.compressed
236 | }
237 |
238 | ###############################################################################
239 | #MASTER GEOLOCATION FUNCTION
240 | ###############################################################################
241 | geolocation () {
242 | #create the file location.db if it does not already exist
243 | #if [ -z $(ls $dataDir/location.db) ];
244 | #then
245 | #seems like maybe I don't actually need to check if this file exists
246 | touch $dataDir/location.db
247 | #fi
248 |
249 | echo -------------------------------Begin SSID Lookup---------------------------------
250 |
251 | #run a wigle query for all SSIDs listed in all.compressed
252 | #we need to pass some arguments to the other function in order for it to work
253 | cat $dataDir/all.compressed | cut -d = -f 2- | sort -u | parallel --no-notice -j 10 ssidGeolocation {} $dataDir $userLocation $WIGLE_API_KEY $searchRange
254 |
255 | echo ------------------------------SSID Lookup Complete-------------------------------
256 |
257 | #remove duplicates and sort
258 | echo Trimming the database
259 | sort -u -o $dataDir/location.db $dataDir/location.db
260 | }
261 |
262 | ###############################################################################
263 | #SSID GEOLOCATION FUNCTION
264 | # Runs a the geolocation search via wigle and handles some other location
265 | # meta-info gathering tasks at this time.
266 | ###############################################################################
267 | ssidGeolocation () {
268 | #re-instantiate variables (required for parallelization)
269 | i=$(echo $1)
270 | dataDir=$(echo $2)
271 | userLocation=$(echo $3)
272 | WIGLE_API_KEY=$(echo $4)
273 | searchRange=$(echo $5)
274 |
275 | #sanitize control chars from bash because... I don't have a better way to fix the bug now
276 | sanSSID=$(echo $i | sed -e 's/\*/\\*/g' \
277 | -e 's/\[/\\[/g' \
278 | -e 's/\]/\\]/g' \
279 | -e 's/\&/\\&/g' )
280 | if [ -z "$(grep -i "\"ssid\"\:\"$sanSSID\"" $dataDir/location.db)" ]
281 | then
282 | #entry is new
283 | echo -n $i
284 |
285 | #urlencode spaces with sed because curl bitches at you otherwise
286 | urlencodeSSID=$(echo $i | sed -e 's/ /%20/g' -e 's/\&/%26/g')
287 |
288 | #run query for the current SSID by wigle
289 | #at this time, since we haven't determined better criteria, only
290 | # keep entries that return one network
291 | if [ $userLocation == 'NOLOC' ]
292 | then
293 | wigle=$(curl --connect-timeout 30 -s -u $WIGLE_API_KEY "https://api.wigle.net/api/v2/network/search?latrange1=&latrange2=&longrange1=&longrange2=&variance=0.010&lastupdt=&netid=&ssid=$urlencodeSSID&ssidlike=&Query=Query&resultsPerPage=2" | grep "\"resultCount\"\:1\," )
294 | else
295 | #this isn't the RIGHT way to calc these distances, but it's pretty close most of the time
296 | # and I don't care that much about precision at the moment
297 |
298 | latRange=$(echo $searchRange/69.2 | bc -l)
299 | lngRange=$(echo $searchRange/69.2 | bc -l)
300 |
301 | lat=$(echo $userLocation | cut -d , -f 1)
302 | lng=$(echo $userLocation | cut -d , -f 2)
303 | latlow=$(echo "$lat-$latRange" | bc)
304 | lathigh=$(echo "$lat+$latRange" | bc)
305 | lnglow=$(echo "$lng-$lngRange" | bc)
306 | lnghigh=$(echo "$lng+$lngRange" | bc)
307 |
308 | #lat/lng is not placed dynamicaly at this time, so these location settings
309 | # will only work in the north american lat/lng quadrant
310 | wigle=$(curl --connect-timeout 30 -s -u $WIGLE_API_KEY "https://api.wigle.net/api/v2/network/search?latrange1=$latlow&latrange2=$lathigh&longrange1=$lnglow&longrange2=$lnghigh&variance=0.010&lastupdt=&netid=&ssid=$urlencodeSSID&ssidlike=&Query=Query&resultsPerPage=2" | grep "\"resultCount\"\:1\," )
311 | fi
312 |
313 | if [ -z "$wigle" ]
314 | then
315 | echo "\"trilat\":NULL,\"trilong\":NULL,\"ssid\":\"$i\",\"wep\":\"\"" >> $dataDir/location.db
316 | echo ""
317 | else
318 | gkey=$(echo "AIzaSyCPMj_9PkQKstTkTNv9RH5gwY40WmJP8N4")
319 | trilat=$(echo $wigle | jq .results[].trilat )
320 | trilong=$(echo $wigle | jq .results[].trilong )
321 |
322 | #add headers and junk for the location.db (re-evaluate if this is still needed pls)
323 | displaytrilat=$(echo $trilat | sed -e 's/^/\"trilat\":/g')
324 | displaytrilong=$(echo $trilong | sed -e 's/^/\"trilong\":/g')
325 |
326 | #bits and pieces that we need from the wigle results
327 | coordinates=$( echo $trilat,$trilong )
328 | ssid=$(echo $wigle | jq .results[].ssid | sed -e 's/^/\"ssid\":/g')
329 | encryption=$(echo $wigle | jq .results[].encryption)
330 |
331 | #if the coordinates from wigle return 0,0, as they sometimes do, fix them by
332 | # marking the locations as unlocated and avoid running the meta-info lookup
333 | # because there's no point
334 | if [ $coordinates = '0,0' ]
335 | then
336 | displaytrilat=$(echo "\"trilat\":NULL")
337 | displaytrilong=$(echo "\"trilong\":NULL")
338 | address=$(echo "NULL")
339 | addressType=$(echo "NULL")
340 | encryption=$(echo "NULL")
341 | else
342 | #Otherwise, try to find out how the location has been identified by google
343 | #stored json from google's geocoding API
344 | geocode=$(curl -s https://maps.googleapis.com/maps/api/geocode/json?latlng=$coordinates)
345 | #google's placeid is required to get more meta information about the location
346 | placeid=$(echo $geocode | jq .results[].place_id | head -n1 | sed 's/\"//g')
347 | #identify what type of address this is
348 | addressType=$(curl -s "https://maps.googleapis.com/maps/api/place/details/json?placeid=$placeid&key=$gkey" | jq .result.types[])
349 | address=$(echo $geocode | jq .results[].formatted_address | head -n1)
350 | fi
351 |
352 | echo $displaytrilat,$displaytrilong,$ssid,$encryption,$address,$addressType >> $dataDir/location.db
353 | echo " :LOCATED"
354 | fi
355 | fi
356 | }
357 | #function needs to be exported so parallel can interact with it
358 | export -f ssidGeolocation
359 |
360 | ###############################################################################
361 | #DEVICE PROFILING FUNCTION
362 | # place SSID probes from each source MAC in its own file
363 | # ensure that only unique entries are in each file
364 | ###############################################################################
365 | profile_gen () {
366 | for i in $(cat $dataDir/all.compressed )
367 | do
368 | echo $(echo $i | cut -d , -f 2) >> $dataDir/$(echo $i | cut -d , -f 1).mac
369 | done
370 |
371 | for i in $(ls $dataDir/*.mac)
372 | do
373 | sort -u -o $i $i
374 | done
375 | }
376 |
377 | ###############################################################################
378 | #TXT REPORT GENERATION FUNCTION
379 | ###############################################################################
380 | txt_gen () {
381 | for i in $(ls $dataDir/*.mac);
382 | do
383 | for e in $(cat $i);
384 | do
385 | mac=$(echo $i | rev | cut -d \/ -f 1 | rev | cut -d . -f 1)
386 | ssid=$(echo $e | cut -d = -f 2)
387 |
388 | extended=$(grep "$ssid" $dataDir/location.db)
389 | if [ -z $(echo $extended | grep "\"trilat\"\:NULL\,\"trilong\"\:NULL\,") ]
390 | then
391 | #network has lat/lng
392 | ext=$(echo $extended | cut -d , -f 1,2,4-)
393 | else
394 | #network has no lat/lng
395 | #check for behavior data
396 | behavior=$(grep "^$ssid:" network_meta_info.txt)
397 | if [[ -z $behavior ]]
398 | then
399 | #no information is known about this network
400 | ext=$(echo NO_DATA)
401 | else
402 | #a beavioral profile has been determined for this network
403 | ext=$(echo $behavior | cut -d : -f 2-)
404 | fi
405 | fi
406 |
407 | echo $mac:$ssid:$ext;
408 | done;
409 | done
410 | }
411 |
412 | ###############################################################################
413 | #HTML REPORT GENERATION FUNCTION
414 | ###############################################################################
415 | html_gen () {
416 | #clear old html files
417 | rm -f $htmlDir/*.html
418 |
419 | echo ------------------------------Generating Profiles--------------------------------
420 | #generate a default display.html so there's always something
421 | #for the active page to refresh to
422 | #this is decommissioned for now
423 | #echo "BEAR WITH US
TECHNICAL DIFFICULTIES


" > html/display.html
424 |
425 | #perform these actions on each .mac profile
426 | for i in $( ls $dataDir/*.mac)
427 | do
428 | echo -n .
429 | #woo variables because we reuse them all the time
430 | mac=$(echo $i | sed 's/.*\///g' | cut -d . -f 1)
431 | manufacturer=$(grep -i $(echo $mac | cut -d : -f -3 | sed 's/://g' ) /usr/share/ieee-data/oui.txt | cut -d ' ' -f 3)
432 | #apply the following actions only on .mac profiles with more than one SSID
433 | #I'm disabling this temporarily for now. I may make it a flagged option?
434 | # if [ "$(cat $i | wc -l)" -gt 1 ]
435 | # then
436 | #Download google maps image for this location
437 | #for each SSID in this .mac profile
438 | for j in $(cat $i | cut -d = -f 2-)
439 | do
440 | #create a variable for all this shit
441 | #because we're going to be using it a LOT
442 | data=$(grep ":\"$j\"," $dataDir/location.db | grep -v "\"trilat\":NULL,\"trilong\":NULL,")
443 | ssid=$(echo $data | cut -d , -f 3 | sed -e 's/\"ssid\":"//g' -e 's/\"$//g')
444 | #display the current lat,lng
445 | latlng=$(echo $data | cut -d , -f 1-2 | sed -e 's/"trilat"://g' -e 's/"trilong"://g')
446 | #if the current SSID does not have google maps photo
447 | if ls $htmlDir/$ssid.png 1> /dev/null 2>&1
448 | then
449 | #do nothing, file exists
450 | :
451 | else
452 | #if the file does not exst, see if we have
453 | #coordinates for it, don't download anything if we
454 | #don't. DUH
455 | if [[ $loc == *"\"trilat\":NULL,\"trilong\":NULL,"* ]]
456 | then
457 | :
458 | else
459 | wget -q https://maps.googleapis.com/maps/api/staticmap?markers=color:red%7Clabel:$ssid%7C$latlng\&zoom=13\&size=400x400\&maptype=roadmap -O $htmlDir/$ssid.png
460 | fi
461 | fi
462 | done
463 |
464 | #generate html page
465 | #for each SSID in this .mac profile
466 | for n in $(cat $i | cut -d = -f 2-)
467 | do
468 | if [ -z "$manufacturer" ]
469 | then
470 | manufacturer=$(echo UNKNOWN)
471 | fi
472 |
473 | #if an image exists for this network, add it to the html
474 | if [ -z "$(ls $htmlDir/*.png 2>/dev/null | grep "\/$n.png")" ]
475 | then
476 | :
477 | else
478 | #if we haven't created an html file for this
479 | # profile yet, add the boilerplate header
480 | if [ -z "$(grep $mac $htmlDir/*html 2>/dev/null)" ]
481 | then
482 | uniqueNets=$(cat $i | wc -l)
483 | echo -n "Device ID $mac, manufacturer:$manufacturer
Looking for $uniqueNets network(s):::Located network count: LOCATED_NETS_STRING_HERE
" >> $htmlDir/$mac.html
484 | fi
485 | #add the image to the profile
486 | address=$(grep \"$n\" $dataDir/location.db | cut -d , -f 5- | sed -e 's/\",\"//g' -e 's/,//' -e 's/\"$//g' -e 's/^\"//g')
487 | latlng=$(grep \"$n\" $dataDir/location.db | cut -d , -f 1-2 | sed -e 's/"trilat"://g' -e 's/"trilong"://g' )
488 | encryption=$(grep \"$n\" $dataDir/location.db| cut -d , -f 4 | sed 's/\"//g')
489 | echo -n "SSID: $nLAT,LNG: $latlngEncryption: $encryption$address | " >> $htmlDir/$mac.html
490 | #echo -n " | SSID: $n |
COORDINATE: $latlng |
ADDRESS: $address |
" >> html/$mac.html
491 | fi
492 | done
493 | #end of 'one probe' profile generation loop
494 | # fi
495 |
496 | #now that the profile has been fully generated, replace placeholder
497 | # for number of located networks with the actual value
498 | if [ -z "$(grep $mac $htmlDir/*html 2>/dev/null )" ]
499 | then
500 | :
501 | else
502 | locatedNets=$(sed 's/\.png/.png\n/g' $htmlDir/$mac.html 2>/dev/null | wc -l)
503 | if [ $locatedNets -ne 0 ]
504 | then
505 | sed -i -e "s/LOCATED_NETS_STRING_HERE/$locatedNets/" $htmlDir/$mac.html
506 | fi
507 |
508 | echo "
Networks that have not been located
" >> $htmlDir/$mac.html
509 | cat $i | cut -d = -f 2- | while read net
510 | do
511 | behavior=$(grep "^$net:" network_meta_info.txt)
512 | if [ -z "$behavior" ]
513 | then
514 | if [ -z "$(grep -v "\"trilat\":NULL,\"trilong\":NULL" $dataDir/location.db | grep ",\"ssid\":\"$net\"," )" ]
515 | then
516 | echo $net | sed 's/^/- /g' >> $htmlDir/$mac.html
517 | fi
518 | # echo $net | sed 's/^/
- /g' >> $htmlDir/$mac.html
519 | else
520 | echo $behavior | sed -e 's/\(.*\):/\1<\/b>:/' -e 's/^/
- /g' >> $htmlDir/$mac.html
521 | fi
522 | done
523 |
524 | if [ -z "$(grep "
- " $htmlDir/$mac.html)" ]
525 | then
526 | sed -i -e 's/
Networks that have not been located
//g' $htmlDir/$mac.html
527 | fi
528 |
529 | echo "
" >> $htmlDir/$mac.html
530 | fi
531 |
532 | echo -n .
533 | done
534 | echo ''
535 | echo -------------------------------Profiles Complete---------------------------------
536 | }
537 |
538 | ###############################################################################
539 | #CALL FUNCTIONS TO DO THINGS!
540 | ###############################################################################
541 | report_directory
542 | pcap_processing
543 | geolocation
544 | profile_gen
545 |
546 | if [ -z $reportFormat ]
547 | then
548 | txt_gen
549 | elif [ $reportFormat == html ]
550 | then
551 | html_gen
552 | elif [ $reportFormat == txt ]
553 | then
554 | txt_gen
555 | fi
556 |
557 | ###############################################################################
558 | #CHILL FUNCTION
559 | ###############################################################################
560 | chill_out () {
561 | #just chill for a second. jesus
562 | echo -n Chill out. Take a beat
563 | for ani in $(seq 1 5)
564 | do
565 | sleep 1
566 | echo -n .
567 | done
568 | echo " Back to it"
569 | }
570 |
571 | #continue looping
572 | #done
573 |
--------------------------------------------------------------------------------