Skip to content

Commit 544cbe8

Browse files
committed
Initial commit
1 parent 3be28ab commit 544cbe8

File tree

3 files changed

+405
-0
lines changed

3 files changed

+405
-0
lines changed

cAssert.h

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
4+
// Uncomment to disable assertion
5+
// for Production / Auto Marking
6+
//#define NDEBUG
7+
8+
#ifndef NDEBUG
9+
// ANSI Colour escape codes
10+
#define ANSI_RED "\x1b[31m"
11+
#define ANSI_BLUE "\x1b[34m"
12+
#define ANSI_CYAN "\x1b[36m"
13+
#define ANSI_GREEN "\x1b[32m"
14+
#define ANSI_YELLOW "\x1b[33m"
15+
#define ANSI_MAGENTA "\x1b[35m"
16+
// ANSI Reset code
17+
#define ANSI_RESET "\x1b[0m"
18+
/*
19+
Coloured 'Info' printfs.
20+
Using the colours of the ANSI rainbow.
21+
NDEBUG will disable these at compile time.
22+
23+
*/
24+
#define infoRed(s) printf( ANSI_RED s ANSI_RESET )
25+
#define infoBlue(s) printf( ANSI_BLUE s ANSI_RESET )
26+
#define infoCyan(s) printf( ANSI_CYAN s ANSI_RESET )
27+
#define infoGreen(s) printf( ANSI_GREEN s ANSI_RESET )
28+
#define infoYellow(s) printf( ANSI_YELLOW s ANSI_RESET )
29+
#define infoMagenta(s) printf( ANSI_MAGENTA s ANSI_RESET )
30+
/*
31+
Coloured Asserion.
32+
Key information is highlighted for easier
33+
late night debugging.
34+
*/
35+
#define cAssert( e ) ( e == 1 ) ? : \
36+
({ \
37+
printf( \
38+
ANSI_RED "Assertion %s failed\n" \
39+
ANSI_RESET \
40+
, __STRING(e)); \
41+
printf( \
42+
ANSI_CYAN "\tBlame: " \
43+
ANSI_YELLOW "%s" \
44+
ANSI_CYAN " => function: " \
45+
ANSI_YELLOW "%s" \
46+
ANSI_CYAN " => line: " \
47+
ANSI_YELLOW "%d\n" \
48+
ANSI_RESET, \
49+
__FILE__, __func__, __LINE__); \
50+
abort(); \
51+
})
52+
/*
53+
Coloured Asserion with info message.
54+
Info message should be something insightful
55+
regarding the condition being tested.
56+
*/
57+
#define cAssertMsg( e, m ) ( e == 1 ) ? : \
58+
({ \
59+
printf( \
60+
ANSI_RED "Assertion %s failed\n" \
61+
ANSI_RESET \
62+
, __STRING(e)); \
63+
printf( \
64+
ANSI_CYAN "\tBlame: " \
65+
ANSI_YELLOW "%s" \
66+
ANSI_CYAN " => function: " \
67+
ANSI_YELLOW "%s" \
68+
ANSI_CYAN " => line: " \
69+
ANSI_YELLOW "%d\n" \
70+
ANSI_RESET, \
71+
__FILE__, __func__, __LINE__); \
72+
printf( \
73+
ANSI_CYAN "\tAssociated Info: " \
74+
ANSI_YELLOW m \
75+
ANSI_RESET); \
76+
abort(); \
77+
})
78+
#else
79+
// No assert MACROS
80+
#define cAssert( e ) ((void)0)
81+
#define cAssertMsg( e, m ) ((void)0)
82+
// No info MACROS
83+
#define infoRed(s) ((void)0)
84+
#define infoBlue(s) ((void)0)
85+
#define infoCyan(s) ((void)0)
86+
#define infoGreen(s) ((void)0)
87+
#define infoYellow(s) ((void)0)
88+
#define infoMagenta(s) ((void)0)
89+
#endif

ssidentity.c

+249
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
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

Comments
 (0)