1
+ /*
2
+ WIRESHARK FILTERS
3
+ Frame type Filter
4
+ Management frames wlan.fc.type eq 0
5
+ Control frames wlan.fc.type eq 1
6
+ Data frames wlan.fc.type eq 2
7
+
8
+ Frame subtype Filter
9
+ Association request wlan.fc.type_subtype eq 0
10
+ Association response wlan.fc.type_subtype eq 1
11
+ Probe request wlan.fc.type_subtype eq 4
12
+ Probe response wlan.fc.type_subtype eq 5
13
+ Beacon wlan.fc.type_subtype eq 8
14
+ Authentication wlan.fc.type_subtype eq 11
15
+ Deauthentication wlan.fc.type_subtype eq 12
16
+
17
+ SQLite3 REFERENCE
18
+ https://www.sqlite.org/c3ref/intro.html
19
+
20
+ ** Use airmon-ng to enable promiscuous mode **
21
+ ** For the moment, it's easier to debug. **
22
+
23
+ */
24
+
25
+ #include <time.h>
26
+ #include <stdio.h>
27
+ #include <stdlib.h>
28
+ // isalnum
29
+ #include <ctype.h>
30
+ // memset
31
+ #include <string.h>
32
+ // FSPL equations
33
+ #include <math.h>
34
+ // SQL
35
+ #include <sqlite3.h>
36
+ // Socket
37
+ #include <netinet/if_ether.h>
38
+ // IP Header structs
39
+ #include <netinet/ip.h>
40
+ // Local
41
+ #include "ssidentity.h"
42
+ // Verbose Assertions
43
+ #include "cAssert.h"
44
+
45
+
46
+ int main ( int argc , char * * argv ) {
47
+ //SQL vars
48
+ char * sqlCmd ;
49
+ char * sqlErr ;
50
+ sqlite3 * requestDB ;
51
+ // Buffer for received 80211 frames
52
+ uint8_t pktBuff [PKT_BUFF_SZ ];
53
+ // Setup a scoket for *any* protocol
54
+ struct sockaddr socketAddr ;
55
+ socklen_t addrLen = sizeof (socketAddr );
56
+ int sock = socket (AF_PACKET , SOCK_RAW , htons (ETH_P_ALL ));
57
+ cAssertMsg ( (sock >= 0 ), "Are you running as root?\n" );
58
+
59
+ while (TRUE) {
60
+ // Receive without needing a socket connection
61
+ int recvDataSize = recvfrom ( sock , pktBuff , PKT_BUFF_SZ ,
62
+ NOFLAG , & socketAddr , & addrLen );
63
+ // Parse it if it's a probe request
64
+ Request request = parseRaw (pktBuff , recvDataSize );
65
+ // Print it if it's not null
66
+ if ( request != NULL ){
67
+ printf ("%s \"%s\" %s\t\t%ddBm %umHz Dist: %.02fm\n" ,
68
+ request -> timeStamp ,
69
+ request -> clientMAC ,
70
+ request -> SSID ,
71
+ request -> RSSI ,
72
+ request -> frequency ,
73
+ request -> distance );
74
+ }
75
+ free (request );
76
+ }
77
+
78
+ return EXIT_SUCCESS ;
79
+ }
80
+
81
+
82
+ /*
83
+ Parse 802.11 probe requests from raw socket data.
84
+ Since this is an open, promiscuous socket..The data
85
+ could really be anything.
86
+
87
+ If the data yields;
88
+ - The correct frame protocol at the correct offset
89
+ - A broadcast MAC at the correct offset
90
+ - A valid SSID length
91
+ - Isn't a known protocol (IP layer)
92
+
93
+ It is then considered a valid probe request.
94
+ */
95
+ Request parseRaw ( uint8_t * buff , uint16_t buffSize ) {
96
+ // Get the frame protocol out
97
+ int16_t frameProtocol = (buff [FRAME_CTL_OFFSET ] & 0xF0 ) >> 4 ;
98
+ // Get frame header as iphdr struct
99
+ struct iphdr * ip_header ;
100
+ ip_header = (struct iphdr * )(buff + sizeof (struct ethhdr ));
101
+ // Get frame protocol
102
+ int protocol = ip_header -> protocol ;
103
+ // Skip known ethernet protocols and non broadcast frames
104
+ if ( frameProtocol == IEEE80211_STYPE_PROBE_REQ &&
105
+ isBroascast ( & buff [DEST_ADDR_OFFSET ]) &&
106
+ !isKnownProtocol ( protocol ) ){
107
+
108
+ int i ;
109
+ int validSSID = FALSE;
110
+ // Throw a new request onto the heap
111
+ Request request = malloc ( sizeof (req ) );
112
+ // Preformat the SSID with NULL chars
113
+ memset (request -> SSID , '\0' , SSID_BUFF_SZ );
114
+ // Check the SSID isn't blank or ovrflw
115
+ uint8_t SSIDlen = buff [SSID_LEN_OFFSET ];
116
+ if ( SSIDlen > 0 && SSIDlen <= SSID_BUFF_SZ ) {
117
+ // Copy SSID into request
118
+ for (i = 0 ; i < SSIDlen ; i ++ ){
119
+ // If it's a printable char
120
+ if ( isprint (buff [SSID_CHR_OFFSET + i ]) ) {
121
+ request -> SSID [i ] = buff [SSID_CHR_OFFSET + i ];
122
+ validSSID = TRUE;
123
+ // Otherwise it's something interesting...log it.
124
+ } else {
125
+ char hexByte [5 ];
126
+ snprintf (& hexByte [0 ], 2 ,
127
+ "\\x%02X" ,
128
+ (unsigned char )buff [SSID_CHR_OFFSET + i ]);
129
+ // Some STA buses are an example...
130
+ // Set the SSID to printable HEX
131
+ request -> SSID [i ] = hexByte [0 ];
132
+ request -> SSID [i + 1 ] = hexByte [1 ];
133
+ request -> SSID [i + 2 ] = hexByte [2 ];
134
+ request -> SSID [i + 3 ] = hexByte [3 ];
135
+ // Kick i fwd a few spots
136
+ i += 3 ;
137
+ validSSID = FALSE;
138
+ }
139
+ }
140
+ // Now get client MAC as uint64
141
+ uint64_t longMac = macU8ToU64 ( & buff [MAC_ADDR_OFFSET ] );
142
+ // Make a HEX string from it
143
+ snprintf (request -> clientMAC , 32 , "%012lX" , longMac );
144
+ // Give the request a time-stamp
145
+ setTimeStamp ( request );
146
+ // Set the RSSI
147
+ request -> RSSI = buff [RSSI_OFFSET ] - 0xFF ;
148
+ // Set the frequency
149
+ request -> frequency = (buff [FREQ_OFFSET ] & 0xFF ) << 8 ;
150
+ request -> frequency |= (buff [FREQ_OFFSET + 1 ] & 0xFF );
151
+ // set the distance estimate
152
+ request -> distance = signalToDistance (request -> RSSI ,
153
+ request -> frequency );
154
+ // Tell me if you see that bus go past
155
+ if (!validSSID ) infoRed ("Found that weird STA bus...\n" );
156
+ // Return the request
157
+ return request ;
158
+ } else {
159
+ // SSID length was outside spec
160
+ return NULL ;
161
+ }
162
+ } else {
163
+ // Frame protocol other than probe request
164
+ return NULL ;
165
+ }
166
+ }
167
+
168
+ /*
169
+ Time stamp a request.
170
+ It's a shame dealing with time in C is such a pain.
171
+ */
172
+ void setTimeStamp ( Request request ) {
173
+ // Epoch
174
+ time_t rawtime ;
175
+ // Time tm struct
176
+ struct tm * info ;
177
+ // Buffer for string rep
178
+ char buffer [80 ];
179
+ // Fill the struct
180
+ time ( & rawtime );
181
+ info = localtime ( & rawtime );
182
+ // Format the timestamp string
183
+ strftime (request -> timeStamp , TIME_BUFF_SZ ,"%x - %I:%M%p" , info );
184
+ }
185
+
186
+ /*
187
+ Check a decoded IP header protocol against known
188
+ protocols. Return true if it's;
189
+ -UDP
190
+ -TCP
191
+ -IGMP
192
+ -ICMP
193
+ */
194
+ int isKnownProtocol ( int protocol ) {
195
+ if ( protocol == PROTO_UDP || protocol == PROTO_TCP ||
196
+ protocol == PROTO_IGMP || protocol == PROTO_ICMP ) {
197
+ return TRUE;
198
+ } else {
199
+ return FALSE;
200
+ }
201
+ }
202
+
203
+ /*
204
+ Check 6 bytes of a buffer for a broadcast MAC.
205
+ uint8_t *buff should point to the first byte
206
+ of the MAC.
207
+
208
+ Assumes 6 bytes in buff.
209
+ */
210
+ int isBroascast ( uint8_t * buff ) {
211
+ if ( buff [5 ] == 0xFF && buff [4 ] == 0xFF &&
212
+ buff [3 ] == 0xFF && buff [2 ] == 0xFF &&
213
+ buff [1 ] == 0xFF && buff [0 ] == 0xFF ) {
214
+ return TRUE;
215
+ } else {
216
+ return FALSE;
217
+ }
218
+ }
219
+
220
+ /*
221
+ Shift a MAC address into a 64 bit unsigned int.
222
+ Useful for converting to a string.
223
+ */
224
+ uint64_t macU8ToU64 ( uint8_t * mac ) {
225
+ uint64_t macint ;
226
+ // MAC bytes into a long
227
+ macint = (uint64_t )(mac [0 ] & 0xFF ) << (8 * 5 );
228
+ macint |= (uint64_t )(mac [1 ] & 0xFF ) << (8 * 4 );
229
+ macint |= (uint64_t )(mac [2 ] & 0xFF ) << (8 * 3 );
230
+ macint |= (uint64_t )(mac [3 ] & 0xFF ) << (8 * 2 );
231
+ macint |= (uint64_t )(mac [4 ] & 0xFF ) << 8 ;
232
+ macint |= (uint64_t ) mac [5 ] & 0xFF ;
233
+ return macint ;
234
+ }
235
+
236
+ /*
237
+ Get an estimate of device distance from freq and RSSI.
238
+ Uses "free space path loss" equation.
239
+
240
+ https://en.wikipedia.org/wiki/Free-space_path_loss
241
+ for MHz / meters,
242
+
243
+ FSPL(dB) = 20*log10( dist ) + 20*log10( freq ) - 27.55
244
+
245
+ */
246
+ float signalToDistance ( int8_t RSSI , uint16_t frequency ) {
247
+ float distance = (27.55 - (20 * log10 (frequency ))+ abs (RSSI ))/20 ;
248
+ return (float )pow (10 , distance );
249
+ }
0 commit comments