From cd1df65dc36ac35d526de195284d5ebf18e1f92b Mon Sep 17 00:00:00 2001 From: Marc Date: Fri, 17 Dec 2021 18:52:36 +0000 Subject: test: Add ctests for generation functions. This commit also enforces error code checking on functions inside of the generation functions, such as for `libwifi_quick_add_tag`. --- utils/.clang-format | 8 + utils/CMakeLists.txt | 15 + utils/src/helpers.c | 31 ++ utils/src/helpers.h | 60 +++ utils/src/test_generation.c | 924 ++++++++++++++++++++++++++++++++++++++++++++ utils/src/test_misc.c | 30 ++ utils/src/test_parsing.c | 613 +++++++++++++++++++++++++++++ 7 files changed, 1681 insertions(+) create mode 100644 utils/.clang-format create mode 100644 utils/CMakeLists.txt create mode 100644 utils/src/helpers.c create mode 100644 utils/src/helpers.h create mode 100644 utils/src/test_generation.c create mode 100644 utils/src/test_misc.c create mode 100644 utils/src/test_parsing.c (limited to 'utils') diff --git a/utils/.clang-format b/utils/.clang-format new file mode 100644 index 0000000..111249f --- /dev/null +++ b/utils/.clang-format @@ -0,0 +1,8 @@ +--- +BasedOnStyle: LLVM +IndentWidth: '4' +SpaceAfterCStyleCast: 'true' +ColumnLimit: 400 +AllowShortFunctionsOnASingleLine: None +IndentCaseLabels: 'true' +... diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt new file mode 100644 index 0000000..bdf7227 --- /dev/null +++ b/utils/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.18) + +project(libwifi_tests VERSION 0.1) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ggdb -O0") + +add_executable(test_misc src/helpers.c src/test_misc.c) +add_executable(test_generation src/helpers.c src/test_generation.c) +add_executable(test_parsing src/helpers.c src/test_parsing.c) +target_link_libraries(test_misc wifi) +target_link_libraries(test_generation wifi pcap) +target_link_libraries(test_parsing wifi pcap) diff --git a/utils/src/helpers.c b/utils/src/helpers.c new file mode 100644 index 0000000..9fc9d0b --- /dev/null +++ b/utils/src/helpers.c @@ -0,0 +1,31 @@ +#include "helpers.h" +#include + +void hexdump(void *data, size_t size) { + char ascii[17]; + size_t i, j; + ascii[16] = '\0'; + for (i = 0; i < size; ++i) { + printf("%02X ", ((unsigned char *) data)[i]); + if (((unsigned char *) data)[i] >= ' ' && ((unsigned char *) data)[i] <= '~') { + ascii[i % 16] = ((unsigned char *) data)[i]; + } else { + ascii[i % 16] = '.'; + } + if ((i + 1) % 8 == 0 || i + 1 == size) { + printf(" "); + if ((i + 1) % 16 == 0) { + printf("| %s \n", ascii); + } else if (i + 1 == size) { + ascii[(i + 1) % 16] = '\0'; + if ((i + 1) % 16 <= 8) { + printf(" "); + } + for (j = (i + 1) % 16; j < 16; ++j) { + printf(" "); + } + printf("| %s \n", ascii); + } + } + } +} diff --git a/utils/src/helpers.h b/utils/src/helpers.h new file mode 100644 index 0000000..99a5329 --- /dev/null +++ b/utils/src/helpers.h @@ -0,0 +1,60 @@ +#include +#include + +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" + +static const uint8_t radiotap_data[] = { + 0x00, + 0x00, // <-- radiotap version (ignore this) + 0x18, + 0x00, // <-- number of bytes in our header (count the number of "0x"s) + + /** + * The next field is a bitmap of which options we are including. + * The full list of which field is which option is in ieee80211_radiotap.h, + * but I've chosen to include: + * 0x00 0x01: timestamp + * 0x00 0x02: flags + * 0x00 0x03: rate + * 0x00 0x04: channel + * 0x80 0x00: tx flags (seems silly to have this AND flags, but oh well) + */ + 0x0f, + 0x80, + 0x00, + 0x00, + + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, // <-- timestamp + + /** + * This is the first set of flags, and we've set the bit corresponding to + * IEEE80211_RADIOTAP_F_FCS, meaning we want the card to add a FCS at the + * end of our buffer for us. + */ + 0x10, + + 0x00, // <-- rate + 0x00, + 0x00, + 0x00, + 0x00, // <-- channel + + /** + * This is the second set of flags, specifically related to transmissions. + * The bit we've set is IEEE80211_RADIOTAP_F_TX_NOACK, which means the card + * won't wait for an ACK for this frame, and that it won't retry if it + * doesn't get one. + */ + 0x08, + 0x00, +}; + +void hexdump(void *data, size_t size); diff --git a/utils/src/test_generation.c b/utils/src/test_generation.c new file mode 100644 index 0000000..407e87f --- /dev/null +++ b/utils/src/test_generation.c @@ -0,0 +1,924 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "helpers.h" + +#define LIVE_INJECT 0 +#define OFFLINE_DUMP 1 + +#define MODE_BEACON 0 +#define MODE_PROBE_RESPONSE 1 +#define MODE_PROBE_REQUEST 2 +#define MODE_DEAUTH 3 +#define MODE_DISASSOC 4 +#define MODE_ASSOC_RESPONSE 5 +#define MODE_ASSOC_REQUEST 6 +#define MODE_REASSOC_RESPONSE 7 +#define MODE_REASSOC_REQUEST 8 +#define MODE_AUTH 9 +#define MODE_RTS 10 +#define MODE_CTS 11 +#define MODE_RANDOM_BEACON 12 +#define MODE_ACTION 13 +#define MODE_ACTION_NOACK 14 +#define MODE_TIMING_AD 15 +#define MODE_ATIM 16 + +#define SNAPLEN 96 +#define CHANNEL 11 +#define BCAST_MAC "\xff\xff\xff\xff\xff\xff" +#define TO_MAC "\x00\x20\x91\xAA\xBB\xCC" +#define FROM_MAC "\x00\x20\x91\x11\x22\x33" +#define REASSOC_MAC "\xAA\xBB\xCC\xDD\xEE\xFF" +#define BEACON_SSID "libwifi-beacon" +#define PROBE_RESP_SSID "libwifi-probe-resp" +#define PROBE_REQ_SSID "libwifi-probe-req" +#define ASSOC_REQ_SSID "libwifi-assoc-req" +#define REASSOC_REQ_SSID "libwifi-reassoc-req" + +pcap_t *handle = NULL; +pcap_dumper_t *outputHandle = NULL; +FILE *filename = NULL; + +static unsigned char to[] = TO_MAC; +static unsigned char from[] = FROM_MAC; +static unsigned char bcast[] = BCAST_MAC; +static unsigned char reassoc_mac[] = REASSOC_MAC; +static unsigned char tag_data[] = "\x00\x00\00\x01This is a 221 tag from libwifi.\n"; + +static int mode = 0; +static int inject_mode = 0; + +void handle_interupt(int signal) { + if (signal == SIGINT) { + int oldmode = inject_mode; + mode = -1; + inject_mode = -1; + + if (oldmode == LIVE_INJECT) { + pcap_close(handle); + printf("\n\nClosed Capture Handle!\n"); + } else if (oldmode == OFFLINE_DUMP) { + pcap_dump_flush(outputHandle); + pcap_dump_close(outputHandle); + printf("\n\nDumped and Closed Output File!\n"); + } + + exit(EXIT_SUCCESS); + } +} + +void inject_frame(void *buf, size_t buf_sz) { + struct libwifi_radiotap_info info = {0}; + info.present = 0x0000002e; // 0x002e: Flags, Rate, Channel, dBm Ant Signal + info.channel.flags = 0x0140; // OFDM, 5GHz + info.channel.freq = 5180; // Channel 46 + info.flags = 0x0000; // No Flags + info.rate = 1; // 1 Mbit + info.rate_raw = info.rate * 2; // Radiotap uses 500kb/s increments + info.signal = -20; // Signal in dBm + + char *rtap = NULL; + rtap = malloc(LIBWIFI_MAX_RADIOTAP_LEN); + if (rtap == NULL) { + printf("malloc failure: %s\n", strerror(errno)); + return; + } + memset(rtap, 0, LIBWIFI_MAX_RADIOTAP_LEN); + + int rtap_len = libwifi_create_radiotap(&info, rtap); + if (rtap_len == -1) { + printf("error generating radiotap header\n"); + return; + } + + void *frame = NULL; + size_t frame_sz = rtap_len + buf_sz; + frame = malloc(frame_sz); + if (frame == NULL) { + printf("malloc failure: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + memcpy(frame, rtap, rtap_len); + memcpy(frame + rtap_len, buf, buf_sz); + + hexdump(rtap, rtap_len); + printf("-----\n"); + hexdump(frame, frame_sz); + + if (inject_mode == LIVE_INJECT) { + pcap_inject(handle, frame, frame_sz); + } else if (inject_mode == OFFLINE_DUMP) { + struct pcap_pkthdr hdr = {0}; + hdr.caplen = frame_sz; + hdr.len = frame_sz; + struct timeval tv; + gettimeofday(&tv, NULL); + hdr.ts = tv; + pcap_dump((unsigned char *) outputHandle, &hdr, frame); + } + + free(rtap); + free(frame); +} + +void inject_beacons(int random_mac) { + while (1) { + printf("Sending 50 beacons...\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_beacon beacon; + unsigned char txmac[6] = {0}; + memset(&beacon, 0, sizeof(struct libwifi_beacon)); + + if (random_mac) { + libwifi_random_mac(txmac, NULL); + } else { + memcpy(txmac, FROM_MAC, 6); + } + libwifi_create_beacon(&beacon, bcast, txmac, BEACON_SSID, CHANNEL); + libwifi_quick_add_tag(&beacon.tags, TAG_VENDOR_SPECIFIC, tag_data, sizeof(tag_data)); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_beacon_length(&beacon); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting beacon with:\n"); + printf("\tSSID: %s\n", BEACON_SSID); + printf("\tChannel: %d\n", CHANNEL); + printf("\tSource: " MACSTR "\n", MAC2STR(txmac)); + printf("\tDestination: " MACSTR "\n", MAC2STR(bcast)); + + libwifi_dump_beacon(&beacon, buf, buf_sz); + inject_frame(buf, buf_sz); + + libwifi_free_beacon(&beacon); + free(buf); + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_probe_responses() { + while (1) { + printf("Sending 50 probe responses, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_probe_resp probe_resp; + memset(&probe_resp, 0, sizeof(struct libwifi_probe_resp)); + + libwifi_create_probe_resp(&probe_resp, to, from, PROBE_RESP_SSID, CHANNEL); + libwifi_quick_add_tag(&probe_resp.tags, TAG_VENDOR_SPECIFIC, tag_data, sizeof(tag_data)); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_probe_resp_length(&probe_resp); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting probe responses with:\n"); + printf("\tSSID: %s\n", PROBE_RESP_SSID); + printf("\tChannel: %d\n", CHANNEL); + printf("\tSource: " MACSTR "\n", MAC2STR(from)); + printf("\tDestination: " MACSTR "\n", MAC2STR(to)); + + libwifi_dump_probe_resp(&probe_resp, buf, buf_sz); + inject_frame(buf, buf_sz); + + libwifi_free_probe_resp(&probe_resp); + free(buf); + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_probe_requests() { + while (1) { + printf("Sending 50 probe responses, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_probe_req probe; + memset(&probe, 0, sizeof(struct libwifi_probe_req)); + + libwifi_create_probe_req(&probe, to, from, to, PROBE_REQ_SSID, CHANNEL); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_probe_req_length(&probe); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting probe requests with:\n"); + printf("\tSSID: %s\n", PROBE_REQ_SSID); + printf("\tChannel: %d\n", CHANNEL); + printf("\tSource: " MACSTR "\n", MAC2STR(from)); + printf("\tDestination: " MACSTR "\n", MAC2STR(to)); + + libwifi_dump_probe_req(&probe, buf, buf_sz); + inject_frame(buf, buf_sz); + + libwifi_free_probe_req(&probe); + free(buf); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_deauths() { + while (1) { + printf("Sending 50 probe responses, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_deauth deauth; + memset(&deauth, 0, sizeof(struct libwifi_deauth)); + + libwifi_create_deauth(&deauth, to, from, REASON_STA_LEAVING); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_deauth_length(&deauth); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting deauths with:\n"); + printf("\tChannel: %d\n", CHANNEL); + printf("\tReason: %d\n", REASON_STA_LEAVING); + printf("\tSource: " MACSTR "\n", MAC2STR(from)); + printf("\tDestination: " MACSTR "\n", MAC2STR(to)); + + libwifi_dump_deauth(&deauth, buf, buf_sz); + inject_frame(buf, buf_sz); + + free(buf); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_disassocs() { + while (1) { + printf("Sending 50 probe responses, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_disassoc disassoc; + memset(&disassoc, 0, sizeof(struct libwifi_disassoc)); + + libwifi_create_disassoc(&disassoc, to, from, REASON_STA_LEAVING); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_disassoc_length(&disassoc); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting disassocs with:\n"); + printf("\tChannel: %d\n", CHANNEL); + printf("\tReason: %d\n", REASON_STA_LEAVING); + printf("\tSource: " MACSTR "\n", MAC2STR(from)); + printf("\tDestination: " MACSTR "\n", MAC2STR(to)); + + libwifi_dump_disassoc(&disassoc, buf, buf_sz); + inject_frame(buf, buf_sz); + + free(buf); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_assoc_requests() { + while (1) { + printf("Sending 50 association requests, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_assoc_req assoc_req; + memset(&assoc_req, 0, sizeof(struct libwifi_assoc_req)); + + libwifi_create_assoc_req(&assoc_req, to, from, ASSOC_REQ_SSID, CHANNEL); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_assoc_req_length(&assoc_req); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting association requests with:\n"); + printf("\tChannel: %d\n", CHANNEL); + printf("\tSource: " MACSTR "\n", MAC2STR(from)); + printf("\tDestination: " MACSTR "\n", MAC2STR(to)); + + libwifi_dump_assoc_req(&assoc_req, buf, buf_sz); + inject_frame(buf, buf_sz); + + free(buf); + libwifi_free_assoc_req(&assoc_req); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_assoc_responses() { + while (1) { + printf("Sending 50 association responses, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_assoc_resp assoc_resp; + memset(&assoc_resp, 0, sizeof(struct libwifi_assoc_req)); + + libwifi_create_assoc_resp(&assoc_resp, to, from, CHANNEL); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_assoc_resp_length(&assoc_resp); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting association responses with:\n"); + printf("\tChannel: %d\n", CHANNEL); + printf("\tSource: " MACSTR "\n", MAC2STR(from)); + printf("\tDestination: " MACSTR "\n", MAC2STR(to)); + + libwifi_dump_assoc_resp(&assoc_resp, buf, buf_sz); + inject_frame(buf, buf_sz); + + free(buf); + libwifi_free_assoc_resp(&assoc_resp); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_reassoc_requests() { + while (1) { + printf("Sending 50 reassociation requests, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_reassoc_req reassoc_req; + memset(&reassoc_req, 0, sizeof(struct libwifi_assoc_req)); + + libwifi_create_reassoc_req(&reassoc_req, to, from, reassoc_mac, REASSOC_REQ_SSID, CHANNEL); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_reassoc_req_length(&reassoc_req); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting reassociation requests with:\n"); + printf("\tChannel: %d\n", CHANNEL); + printf("\tSource: " MACSTR "\n", MAC2STR(from)); + printf("\tDestination: " MACSTR "\n", MAC2STR(to)); + printf("\tPrevious BSSID: " MACSTR "\n", MAC2STR(reassoc_mac)); + + libwifi_dump_reassoc_req(&reassoc_req, buf, buf_sz); + inject_frame(buf, buf_sz); + + free(buf); + libwifi_free_reassoc_req(&reassoc_req); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_reassoc_responses() { + while (1) { + printf("Sending 50 reassociation responses, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_reassoc_resp reassoc_resp; + memset(&reassoc_resp, 0, sizeof(struct libwifi_assoc_req)); + + libwifi_create_reassoc_resp(&reassoc_resp, to, from, CHANNEL); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_reassoc_resp_length(&reassoc_resp); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting reassociation responses with:\n"); + printf("\tChannel: %d\n", CHANNEL); + printf("\tSource: " MACSTR "\n", MAC2STR(from)); + printf("\tDestination: " MACSTR "\n", MAC2STR(to)); + + libwifi_dump_reassoc_resp(&reassoc_resp, buf, buf_sz); + inject_frame(buf, buf_sz); + + free(buf); + libwifi_free_reassoc_resp(&reassoc_resp); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_auths() { + while (1) { + printf("Sending 50 auth frames, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_auth auth; + memset(&auth, 0, sizeof(struct libwifi_deauth)); + + libwifi_create_auth(&auth, to, from, AUTH_OPEN, 0, STATUS_SUCCESS); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_auth_length(&auth); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + libwifi_dump_auth(&auth, buf, buf_sz); + inject_frame(buf, buf_sz); + + free(buf); + + memset(&auth, 0, sizeof(struct libwifi_deauth)); + + libwifi_create_auth(&auth, from, to, AUTH_OPEN, 1, STATUS_SUCCESS); + + buf = NULL; + buf_sz = libwifi_get_auth_length(&auth); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting auths with:\n"); + printf("\tChannel: %d\n", CHANNEL); + printf("\tAlgorithm: %d\n", AUTH_OPEN); + printf("\tSource: " MACSTR "\n", MAC2STR(from)); + printf("\tDestination: " MACSTR "\n", MAC2STR(to)); + + libwifi_dump_auth(&auth, buf, buf_sz); + inject_frame(buf, buf_sz); + + free(buf); + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_timing_ads() { + while (1) { + printf("Sending 50 timing advertisement frames, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_timing_advert time_ad = {0}; + struct libwifi_timing_advert_fields ad_fields = {0}; + + ad_fields.timing_capabilities = 2; + memcpy(ad_fields.time_error, "\xCC\xCC\xCC\xCC\xCC", 5); + memcpy(ad_fields.time_update, "\xBB", 1); + memcpy(ad_fields.time_value, + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", 10); + + libwifi_create_timing_advert(&time_ad, to, from, &ad_fields, "GB", -56, -56, -30, -20); + + unsigned char *buf = NULL; + size_t buf_len = libwifi_get_timing_advert_length(&time_ad); + buf = malloc(buf_len); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + printf("buf_len: %zu\n", buf_len); + + size_t ret = libwifi_dump_timing_advert(&time_ad, buf, buf_len); + if (ret < 0) { + printf("error dump: %zu\n", ret); + exit(EXIT_FAILURE); + } + hexdump(buf, buf_len); + inject_frame(buf, buf_len); + + free(buf); + libwifi_free_timing_advert(&time_ad); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_action_noacks() { + while (1) { + printf("Sending 50 action no ack frames, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_action action; + memset(&action, 0, sizeof(struct libwifi_action)); + + libwifi_create_action_no_ack(&action, to, from, ACTION_FAST_BSS_TRANSITION); + + unsigned char *action_buf = malloc(256); + memset(action_buf, 0, 256); + + size_t offset = 0; + size_t w = 0; + + memcpy(action_buf, "\x01", 1); // Fast BSS Request + offset += 1; + memcpy(action_buf + offset, "\xAA\xBB\xCC\xDD\xEE\xFF", 6); // STA Address + offset += 6; + memcpy(action_buf + offset, "\xFF\xEE\xDD\xCC\xBB\xAA", 6); // AP Address + offset += 6; + + unsigned char *tag_tmp = malloc(256); + memset(tag_tmp, 0, 256); + + struct libwifi_tagged_parameter rsne = {0}; + size_t tsz = libwifi_create_tag(&rsne, TAG_RSN, (const unsigned char * )"\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\x00\x00", 20); + w = libwifi_dump_tag(&rsne, tag_tmp, tsz); + memcpy(action_buf + offset, tag_tmp, w); + offset += w; + + + struct libwifi_tagged_parameter mobdom = {0}; + tsz = libwifi_create_tag(&mobdom, TAG_MOBILITY_DOMAIN, (const unsigned char*)"\x00\x11\x01", 3); + memset(tag_tmp, 0, tsz); + w = libwifi_dump_tag(&mobdom, tag_tmp, tsz); + memcpy(action_buf + offset, tag_tmp, w); + offset += w; + libwifi_free_tag(&mobdom); + + struct libwifi_tagged_parameter fbss = {0}; + tsz = libwifi_create_tag(&fbss, TAG_FAST_BSS_TRANSITION, (const unsigned char*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\x03\x04\xAA\xBB\x04\xAA\xBB\xCC\xDD", 88); + memset(tag_tmp, 0, tsz); + w = libwifi_dump_tag(&fbss, tag_tmp, tsz); + memcpy(action_buf + offset, tag_tmp, w); + offset += w; + libwifi_free_tag(&fbss); + + libwifi_add_action_detail(&action.fixed_parameters.details, action_buf, offset); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_action_length(&action); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting actions with:\n"); + printf("\tAction: %d\n", ACTION_FAST_BSS_TRANSITION); + printf("\tSource: " MACSTR "\n", MAC2STR(from)); + printf("\tDestination: " MACSTR "\n", MAC2STR(to)); + + libwifi_dump_action(&action, buf, buf_sz); + inject_frame(buf, buf_sz); + + free(buf); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_actions() { + while (1) { + printf("Sending 50 action frames, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_action action; + memset(&action, 0, sizeof(struct libwifi_action)); + + libwifi_create_action(&action, to, from, ACTION_FAST_BSS_TRANSITION); + + unsigned char *action_buf = malloc(256); + memset(action_buf, 0, 256); + + size_t offset = 0; + size_t w = 0; + + memcpy(action_buf, "\x01", 1); // Fast BSS Request + offset += 1; + memcpy(action_buf + offset, "\xAA\xBB\xCC\xDD\xEE\xFF", 6); // STA Address + offset += 6; + memcpy(action_buf + offset, "\xFF\xEE\xDD\xCC\xBB\xAA", 6); // AP Address + offset += 6; + + unsigned char *tag_tmp = malloc(256); + memset(tag_tmp, 0, 256); + + struct libwifi_tagged_parameter rsne = {0}; + size_t tsz = libwifi_create_tag(&rsne, TAG_RSN, (const unsigned char * )"\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\x00\x00", 20); + w = libwifi_dump_tag(&rsne, tag_tmp, tsz); + memcpy(action_buf + offset, tag_tmp, w); + offset += w; + + + struct libwifi_tagged_parameter mobdom = {0}; + tsz = libwifi_create_tag(&mobdom, TAG_MOBILITY_DOMAIN, (const unsigned char*)"\x00\x11\x01", 3); + memset(tag_tmp, 0, tsz); + w = libwifi_dump_tag(&mobdom, tag_tmp, tsz); + memcpy(action_buf + offset, tag_tmp, w); + offset += w; + libwifi_free_tag(&mobdom); + + struct libwifi_tagged_parameter fbss = {0}; + tsz = libwifi_create_tag(&fbss, TAG_FAST_BSS_TRANSITION, (const unsigned char*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\x03\x04\xAA\xBB\x04\xAA\xBB\xCC\xDD", 88); + memset(tag_tmp, 0, tsz); + w = libwifi_dump_tag(&fbss, tag_tmp, tsz); + memcpy(action_buf + offset, tag_tmp, w); + offset += w; + libwifi_free_tag(&fbss); + + libwifi_add_action_detail(&action.fixed_parameters.details, action_buf, offset); + + unsigned char *buf = NULL; + size_t buf_sz = libwifi_get_action_length(&action); + + buf = malloc(buf_sz); + if (buf == NULL) { + printf("malloc failure: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + printf("Injecting actions with:\n"); + printf("\tAction: %d\n", ACTION_FAST_BSS_TRANSITION); + printf("\tSource: " MACSTR "\n", MAC2STR(from)); + printf("\tDestination: " MACSTR "\n", MAC2STR(to)); + + libwifi_dump_action(&action, buf, buf_sz); + inject_frame(buf, buf_sz); + + free(buf); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_atim() { + while (1) { + printf("Sending 50 ATIM frames, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_atim atim = {0}; + + libwifi_create_atim(&atim, to, from, from); + + inject_frame(&atim, sizeof(struct libwifi_atim)); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_rts() { + while (1) { + printf("Sending 50 RTS frames, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_rts rts = {0}; + + libwifi_create_rts(&rts, to, from, 32); + + inject_frame(&rts, sizeof(struct libwifi_rts)); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void inject_cts() { + while (1) { + printf("Sending 50 CTS frames, then sleeping for 1 second\n"); + for (int i = 0; i < 50; ++i) { + struct libwifi_cts cts = {0}; + + libwifi_create_cts(&cts, to, 32); + + inject_frame(&cts, sizeof(struct libwifi_cts)); + + usleep(1e4); // 10ms + } + sleep(1); + } +} + +void help(const char *name) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\t%s --interface [interface] [--mode]\n", name); + fprintf(stderr, "\t\tor\n"); + fprintf(stderr, "\t%s --file [output file] [--mode]\n", name); + fprintf(stderr, "\n"); + fprintf(stderr, "Modes:\n"); + fprintf(stderr, "\t--beacon\n"); + fprintf(stderr, "\t--random-beacon\n"); + fprintf(stderr, "\t--probe-req\n"); + fprintf(stderr, "\t--probe-resp\n"); + fprintf(stderr, "\t--deauth\n"); + fprintf(stderr, "\t--disassoc\n"); + fprintf(stderr, "\t--assoc-req\n"); + fprintf(stderr, "\t--assoc-resp\n"); + fprintf(stderr, "\t--reassoc-req\n"); + fprintf(stderr, "\t--reassoc-resp\n"); + fprintf(stderr, "\t--auth\n"); + fprintf(stderr, "\t--timing-ad\n"); + fprintf(stderr, "\t--atim\n"); + fprintf(stderr, "\t--rts\n"); + fprintf(stderr, "\t--cts\n"); +} + +void handle_args(int argc, const char *argv[]) { + char errbuf[PCAP_ERRBUF_SIZE]; + memset(errbuf, 0, PCAP_ERRBUF_SIZE); + + if (argc < 4) { + help(argv[0]); + exit(EXIT_SUCCESS); + } + + if (strcmp(argv[1], "--file") == 0) { + inject_mode = OFFLINE_DUMP; + + filename = fopen(argv[2], "w+"); + if ((handle = pcap_open_dead(DLT_IEEE802_11_RADIO, BUFSIZ)) == NULL) { + fprintf(stderr, "1 %s: %s\n", argv[2], errbuf); + exit(EXIT_FAILURE); + } + if ((outputHandle = pcap_dump_fopen(handle, filename)) == NULL) { + fprintf(stderr, "2 %s: %s\n", argv[2], errbuf); + exit(EXIT_FAILURE); + } + } else if (strcmp(argv[1], "--interface") == 0) { + inject_mode = LIVE_INJECT; + + if ((handle = pcap_create(argv[2], errbuf)) == NULL) { + fprintf(stderr, "Couldn't open interface %s: %s\n", argv[2], errbuf); + exit(EXIT_FAILURE); + } + if (pcap_activate(handle) == 0) { + printf("Sniffing on %s\n", argv[2]); + } else { + fprintf(stderr, "Couldn't activate %s: %s\n", argv[2], pcap_geterr(handle)); + exit(EXIT_FAILURE); + } + } else { + help(argv[0]); + exit(EXIT_SUCCESS); + } + + if (strcmp(argv[3], "--beacon") == 0) { + mode = MODE_BEACON; + } else if (strcmp(argv[3], "--random-beacon") == 0) { + mode = MODE_RANDOM_BEACON; + } else if (strcmp(argv[3], "--probe-resp") == 0) { + mode = MODE_PROBE_RESPONSE; + } else if (strcmp(argv[3], "--probe-req") == 0) { + mode = MODE_PROBE_REQUEST; + } else if (strcmp(argv[3], "--deauth") == 0) { + mode = MODE_DEAUTH; + } else if (strcmp(argv[3], "--disassoc") == 0) { + mode = MODE_DISASSOC; + } else if (strcmp(argv[3], "--assoc-resp") == 0) { + mode = MODE_ASSOC_RESPONSE; + } else if (strcmp(argv[3], "--assoc-req") == 0) { + mode = MODE_ASSOC_REQUEST; + } else if (strcmp(argv[3], "--reassoc-resp") == 0) { + mode = MODE_REASSOC_RESPONSE; + } else if (strcmp(argv[3], "--reassoc-req") == 0) { + mode = MODE_REASSOC_REQUEST; + } else if (strcmp(argv[3], "--auth") == 0) { + mode = MODE_AUTH; + } else if (strcmp(argv[3], "--timing-ad") == 0) { + mode = MODE_TIMING_AD; + } else if (strcmp(argv[3], "--action") == 0) { + mode = MODE_ACTION; + } else if (strcmp(argv[3], "--action-noack") == 0) { + mode = MODE_ACTION_NOACK; + } else if (strcmp(argv[3], "--atim") == 0) { + mode = MODE_ATIM; + } else if (strcmp(argv[3], "--rts") == 0) { + mode = MODE_RTS; + } else if (strcmp(argv[3], "--cts") == 0) { + mode = MODE_CTS; + } else { + help(argv[0]); + exit(EXIT_SUCCESS); + } +} + +int main(int argc, const char *argv[]) { + signal(SIGINT, handle_interupt); + handle_args(argc, argv); + + printf("Starting in 5 seconds...\n"); + + sleep(5); + + switch (mode) { + case MODE_BEACON: + inject_beacons(0); + break; + case MODE_RANDOM_BEACON: + inject_beacons(1); + break; + case MODE_PROBE_RESPONSE: + inject_probe_responses(); + break; + case MODE_PROBE_REQUEST: + inject_probe_requests(); + break; + case MODE_DEAUTH: + inject_deauths(); + break; + case MODE_DISASSOC: + inject_disassocs(); + break; + case MODE_ASSOC_REQUEST: + inject_assoc_requests(); + break; + case MODE_ASSOC_RESPONSE: + inject_assoc_responses(); + break; + case MODE_REASSOC_REQUEST: + inject_reassoc_requests(); + break; + case MODE_REASSOC_RESPONSE: + inject_reassoc_responses(); + break; + case MODE_AUTH: + inject_auths(); + break; + case MODE_ACTION: + inject_actions(); + break; + case MODE_ACTION_NOACK: + inject_action_noacks(); + break; + case MODE_TIMING_AD: + inject_timing_ads(); + break; + case MODE_ATIM: + inject_atim(); + break; + case MODE_RTS: + inject_rts(); + break; + case MODE_CTS: + inject_cts(); + break; + } + + return 0; +} diff --git a/utils/src/test_misc.c b/utils/src/test_misc.c new file mode 100644 index 0000000..f103455 --- /dev/null +++ b/utils/src/test_misc.c @@ -0,0 +1,30 @@ +#include +#include +#include + +void gen_macs() { + printf("Getting 10 random MAC addresses:\n"); + for(int i = 0; i < 10; i++) { + unsigned char mac[6] = {0}; + libwifi_random_mac(mac, NULL); + printf(MACSTR "\n", MAC2STR(mac)); + } + + printf("Generating 10 random MAC addresses with 00:20:91 OUI:\n"); + for(int i = 0; i < 10; i++) { + unsigned char mac[6] = {0}; + libwifi_random_mac(mac, (unsigned char *) "\x00\x20\x91"); + printf(MACSTR "\n", MAC2STR(mac)); + } + printf("\n"); +} + +int main() { + libwifi_dummy(); + + printf("libwifi version: %s\n\n", libwifi_get_version()); + + gen_macs(); + + return 0; +} diff --git a/utils/src/test_parsing.c b/utils/src/test_parsing.c new file mode 100644 index 0000000..c345346 --- /dev/null +++ b/utils/src/test_parsing.c @@ -0,0 +1,613 @@ +#include "helpers.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCAP_SAVEFILE "/tmp/debug.pcap" +#define FILTER "" +#define MODE_BEACON 1 +#define MODE_PROBE_RESPONSE 2 +#define MODE_PROBE_REQUEST 3 +#define MODE_EAPOL 4 +#define MODE_DEAUTH 5 +#define MODE_DISASSOC 6 +#define MODE_ASSOC_RESPONSE 7 +#define MODE_ASSOC_REQUEST 8 +#define MODE_REASSOC_REQUEST 9 +#define MODE_REASSOC_RESPONSE 10 +#define MODE_DATA 11 +#define MODE_ALL 99 + +static pcap_t *handle; +pcap_dumper_t *pd; +static struct bpf_program *filter; +static int got_radiotap; +static unsigned long packet_num = 0; +static int mode = 0; +static int parse_radiotap_header = 0; + +struct libwifi_bss bss = {0}; +struct libwifi_sta sta = {0}; + +void help(const char *); +void parse_packet(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet); +void print_bss_info(struct libwifi_bss *bss); +void print_sta_info(struct libwifi_sta *sta); +void print_tag_info(unsigned char *data, size_t data_len); + +void interrupted(int signum) { + pcap_dump_close(pd); + pcap_close(handle); +} + +void print_bss_info(struct libwifi_bss *bss) { + if (bss == NULL) { + return; + } + + printf("=== BSS Parsing ===\n"); + printf("ESSID: %s\n", bss->hidden ? "(hidden)" : bss->ssid); + printf("BSSID: " MACSTR "\n", MAC2STR(bss->bssid)); + printf("Receiver: " MACSTR "\n", MAC2STR(bss->receiver)); + printf("Transmitter: " MACSTR "\n", MAC2STR(bss->transmitter)); + printf("Channel: %d\n", bss->channel); + printf("WPS: %s\n", bss->wps ? "yes" : "no"); + + char sec_buf[LIBWIFI_SECURITY_BUF_LEN]; + libwifi_get_security_type(bss, sec_buf); + printf("Encryption: %s\n", sec_buf); + + libwifi_get_group_ciphers(bss, sec_buf); + printf("\tGroup Ciphers: %s\n", sec_buf); + + libwifi_get_pairwise_ciphers(bss, sec_buf); + printf("\tPairwise Ciphers: %s\n", sec_buf); + + libwifi_get_auth_key_suites(bss, sec_buf); + printf("\tAuth Key Suites: %s\n", sec_buf); + + if (bss->rsn_info.rsn_capabilities & LIBWIFI_RSN_CAPAB_MFP_CAPABLE) { + printf("\tMFP Capable: Yes\n"); + } + if (bss->rsn_info.rsn_capabilities & LIBWIFI_RSN_CAPAB_MFP_REQUIRED) { + printf("\tMFP Required: Yes\n"); + } + + if (bss->tags.length) { + printf("Tagged Parameters:\n"); + print_tag_info(bss->tags.parameters, bss->tags.length); + } else { + printf("Tagged Parameters: None\n"); + } + + printf("=== BSS End ===\n"); + printf("\n\n"); +} + +void print_sta_info(struct libwifi_sta *sta) { + if (sta == NULL) { + return; + } + + printf("=== STA Parsing ===\n"); + + if (sta->broadcast_ssid) { + printf("ESSID: \n"); + } else { + printf("ESSID: %s\n", sta->ssid); + } + printf("Channel: %u\n", sta->channel); + printf("BSSID: " MACSTR "\n", MAC2STR(sta->bssid)); + printf("MAC: " MACSTR "\n", MAC2STR(sta->transmitter)); + + printf("=== STA End ===\n"); + printf("\n\n"); +} + +void print_tag_info(unsigned char *data, size_t data_len) { + struct libwifi_tag_iterator it; + if (libwifi_tag_iterator_init(&it, data, data_len) != 0) { + printf("Couldn't initialise tag iterator\n"); + return; + } + do { + printf("\tTag: %d (Size: %d)\n", it.tag_header->tag_num, it.tag_header->tag_len); + + int max_size = 16; + if (it.tag_header->tag_len < 16) { + max_size = it.tag_header->tag_len; + } + printf("\t%d bytes of Tag Data: ", max_size); + for (size_t i = 0; i < max_size; i++) { + printf("%02x ", it.tag_data[i]); + } + printf("\n"); + } while (libwifi_tag_iterator_next(&it) != -1); +} + +void parse_radiotap(const unsigned char *packet) { + struct libwifi_radiotap_info rtap_info; + libwifi_parse_radiotap_info(&rtap_info, packet); + + printf("=== Radiotap Parsing ===\n"); + printf("Radiotap Channel: %d\n", rtap_info.channel.freq); + printf("Radiotap Channel Flags: 0x%04x\n", rtap_info.channel.flags); + printf("Radiotap Rate: %.2f Mb/s\n", rtap_info.rate); + printf("Radiotap Rate Raw: 0x%02x\n", rtap_info.rate_raw); + printf("Radiotap Signal: %d dBm\n", rtap_info.signal); + for (int i = 0; i < rtap_info.antenna_count; i++) { + printf("Radiotap Antenna %d: %d dBm\n", rtap_info.antennas[i].antenna_number, rtap_info.antennas[i].signal); + } + printf("Radiotap Flags: 0x%04x\n", rtap_info.flags); + printf("Radiotap Extended Flags: 0x%08x\n", rtap_info.extended_flags); + printf("Radiotap RX Flags: 0x%04x\n", rtap_info.rx_flags); + printf("Radiotap TX Flags: 0x%04x\n", rtap_info.tx_flags); + printf("Radiotap TX Power: %d\n", rtap_info.tx_power); + printf("Radiotap RTS Retries: %d\n", rtap_info.rts_retries); + printf("Radiotap Data Retries: %d\n", rtap_info.data_retries); + printf("=== Radiotap End ===\n"); +} + +void parse_beacon(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_BEACON) { + printf("Packet : %lu\n", packet_num); + int ret = libwifi_parse_beacon(&bss, &frame); + if (ret != 0) { + printf("Failed to parse beacon: %d\n", ret); + pcap_dump(args, header, packet); + return; + } + + if (got_radiotap && parse_radiotap_header) { + parse_radiotap(packet); + } + + print_bss_info(&bss); + } +} + +void parse_probe_request(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_PROBE_REQ) { + printf("Packet : %lu\n", packet_num); + int ret = libwifi_parse_probe_req(&sta, &frame); + if (ret != 0) { + printf("Failed to parse probe request: %d\n", ret); + pcap_dump(args, header, packet); + return; + } + + if (got_radiotap && parse_radiotap_header) { + parse_radiotap(packet); + } + + print_sta_info(&sta); + } +} +void parse_probe_response(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_PROBE_RESP) { + printf("Packet : %lu\n", packet_num); + int ret = libwifi_parse_probe_resp(&bss, &frame); + if (ret != 0) { + printf("Failed to parse probe response: %d\n", ret); + pcap_dump(args, header, packet); + return; + } + + if (got_radiotap && parse_radiotap_header) { + parse_radiotap(packet); + } + + print_bss_info(&bss); + } +} +void parse_deauth(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_DEAUTH) { + printf("Packet : %lu\n", packet_num); + struct libwifi_parsed_deauth deauth; + int ret = libwifi_parse_deauth(&deauth, &frame); + if (ret != 0) { + printf("Failed to parse deauthentication: %d\n", ret); + pcap_dump(args, header, packet); + return; + } + + if (got_radiotap && parse_radiotap_header) { + parse_radiotap(packet); + } + + printf("=== Deauthentication Frame ===\n"); + if (deauth.ordered) { + printf("Address 1: " MACSTR "\n", MAC2STR(deauth.frame_header.ordered.addr1)); + printf("Address 2: " MACSTR "\n", MAC2STR(deauth.frame_header.ordered.addr2)); + printf("Address 3: " MACSTR "\n", MAC2STR(deauth.frame_header.ordered.addr3)); + } else { + printf("Address 1: " MACSTR "\n", MAC2STR(deauth.frame_header.unordered.addr1)); + printf("Address 2: " MACSTR "\n", MAC2STR(deauth.frame_header.unordered.addr2)); + printf("Address 3: " MACSTR "\n", MAC2STR(deauth.frame_header.unordered.addr3)); + } + + printf("Reason: %d (0x%04x)\n", deauth.fixed_parameters.reason_code, deauth.fixed_parameters.reason_code); + + if (deauth.tags.length) { + printf("Tagged Parameters:\n"); + print_tag_info(deauth.tags.parameters, deauth.tags.length); + } else { + printf("Tagged Parameters: None\n"); + } + + printf("=== End Deauthentication Frame ===\n"); + printf("\n\n"); + } +} +void parse_disassoc(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_DISASSOC) { + printf("Packet : %lu\n", packet_num); + struct libwifi_parsed_disassoc disassoc; + int ret = libwifi_parse_disassoc(&disassoc, &frame); + if (ret != 0) { + printf("Failed to parse diassociation: %d\n", ret); + pcap_dump(args, header, packet); + return; + } + + if (got_radiotap && parse_radiotap_header) { + parse_radiotap(packet); + } + + printf("=== Disassociation Frame ===\n"); + if (disassoc.ordered) { + printf("Address 1: " MACSTR "\n", MAC2STR(disassoc.frame_header.ordered.addr1)); + printf("Address 2: " MACSTR "\n", MAC2STR(disassoc.frame_header.ordered.addr2)); + printf("Address 3: " MACSTR "\n", MAC2STR(disassoc.frame_header.ordered.addr3)); + } else { + printf("Address 1: " MACSTR "\n", MAC2STR(disassoc.frame_header.unordered.addr1)); + printf("Address 2: " MACSTR "\n", MAC2STR(disassoc.frame_header.unordered.addr2)); + printf("Address 3: " MACSTR "\n", MAC2STR(disassoc.frame_header.unordered.addr3)); + } + + printf("Reason: %d (0x%04x)\n", disassoc.fixed_parameters.reason_code, disassoc.fixed_parameters.reason_code); + + printf("Tagged Parameters:\n"); + if (disassoc.tags.length == 0) { + printf("\tNo Tags\n"); + } else { + printf("\tTags Found\n"); + } + + printf("=== End Disassociation Frame ===\n"); + printf("\n\n"); + } +} +void parse_assoc_request(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_ASSOC_REQ) { + printf("Packet : %lu\n", packet_num); + int ret = libwifi_parse_assoc_req(&sta, &frame); + if (ret != 0) { + printf("Failed to parse association request: %d\n", ret); + pcap_dump(args, header, packet); + return; + } + + if (got_radiotap && parse_radiotap_header) { + parse_radiotap(packet); + } + + print_sta_info(&sta); + } +} +void parse_assoc_response(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_ASSOC_RESP) { + printf("Packet : %lu\n", packet_num); + int ret = libwifi_parse_assoc_resp(&bss, &frame); + if (ret != 0) { + printf("Failed to parse association response: %d\n", ret); + pcap_dump(args, header, packet); + return; + } + + if (got_radiotap && parse_radiotap_header) { + parse_radiotap(packet); + } + + print_bss_info(&bss); + } +} +void parse_reassoc_request(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_REASSOC_REQ) { + printf("Packet : %lu\n", packet_num); + int ret = libwifi_parse_reassoc_req(&sta, &frame); + if (ret != 0) { + printf("Failed to parse reassociation request: %d\n", ret); + pcap_dump(args, header, packet); + return; + } + + if (got_radiotap && parse_radiotap_header) { + parse_radiotap(packet); + } + + print_sta_info(&sta); + } +} +void parse_reassoc_response(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_REASSOC_RESP) { + printf("Packet : %lu\n", packet_num); + int ret = libwifi_parse_reassoc_resp(&bss, &frame); + if (ret != 0) { + printf("Failed to parse reassociation response: %d\n", ret); + pcap_dump(args, header, packet); + return; + } + + if (got_radiotap && parse_radiotap_header) { + parse_radiotap(packet); + } + + print_bss_info(&bss); + } +} +void parse_data_eapol(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + if (frame.frame_control.type == TYPE_DATA) { + if (libwifi_check_wpa_handshake(&frame) > 0) { + printf("=== EAPOL ===\n"); + printf("WPA Handshake\n"); + int part = libwifi_check_wpa_message(&frame); + printf("WPA Handshake Message: %s\n", libwifi_get_wpa_message_string(&frame)); + + struct libwifi_wpa_auth_data data = {0}; + libwifi_get_wpa_data(&frame, &data); + + printf("EAPOL: Version: %d\n", data.version); + printf("EAPOL: Type: %d\n", data.type); + printf("EAPOL: Length: %d\n", data.length); + printf("EAPOL: Descriptor: %d\n", data.descriptor); + printf("EAPOL: Key Info: Information: 0x%04x\n", data.key_info.information); + printf("EAPOL: Key Info: Key Length: %d\n", data.key_info.key_length); + printf("EAPOL: Key Info: Replay Counter: %lu\n", data.key_info.replay_counter); + printf("EAPOL: Key Info: Nonce: "); + for (size_t i = 0; i < sizeof(data.key_info.nonce); ++i) printf("%02x ", data.key_info.nonce[i]); + printf("\n"); + printf("EAPOL: Key Info: IV: "); + for (size_t i = 0; i < sizeof(data.key_info.iv); ++i) printf("%02x ", data.key_info.iv[i]); + printf("\n"); + printf("EAPOL: Key Info: RSC: "); + for (size_t i = 0; i < sizeof(data.key_info.rsc); ++i) printf("%02x ", data.key_info.rsc[i]); + printf("\n"); + printf("EAPOL: Key Info: ID: "); + for (size_t i = 0; i < sizeof(data.key_info.id); ++i) printf("%02x ", data.key_info.id[i]); + printf("\n"); + printf("EAPOL: Key Info: MIC: "); + for (size_t i = 0; i < sizeof(data.key_info.mic); ++i) printf("%02x ", data.key_info.mic[i]); + printf("\n"); + printf("EAPOL: Key Info: Key Data Length: %d\n", data.key_info.key_data_length); + if (data.key_info.key_data_length) { + printf("EAPOL: Key Info: Key Data: "); + for (size_t i = 0; i < data.key_info.key_data_length; ++i) printf("%02x ", data.key_info.key_data[i]); + printf("\n"); + } + + libwifi_free_wpa_data(&data); + + printf("\n\n"); + } + } +} + +void parse_data(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + if (frame.frame_control.type == TYPE_DATA) { + if (frame.flags & LIBWIFI_FLAGS_IS_QOS) { + printf("Receiver: " MACSTR "\n", MAC2STR(frame.header.data_qos.addr1)); + printf("Transmitter: " MACSTR "\n", MAC2STR(frame.header.data_qos.addr2)); + } else { + printf("Receiver: " MACSTR "\n", MAC2STR(frame.header.data.addr1)); + printf("Transmitter: " MACSTR "\n", MAC2STR(frame.header.data.addr2)); + } + printf("Body Length: %zu\n", frame.len - frame.header_len); + printf("Body:\n"); + hexdump(frame.body, frame.len - frame.header_len); + } +} + +void parse_packet(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) { + ++packet_num; + unsigned long data_len = header->caplen; + unsigned char *data = (unsigned char *) packet; + + struct libwifi_frame frame = {0}; + int ret = libwifi_get_wifi_frame(&frame, data, data_len, 1); + if (ret != 0) { + printf("[!] Error getting libwifi_frame: %d\n", ret); + return; + } + + memset(&bss, 0, sizeof(struct libwifi_bss)); + memset(&sta, 0, sizeof(struct libwifi_sta)); + + switch (mode) { + case MODE_BEACON: + parse_beacon(frame, args, header, packet); + break; + case MODE_PROBE_REQUEST: + parse_probe_request(frame, args, header, packet); + break; + case MODE_PROBE_RESPONSE: + parse_probe_response(frame, args, header, packet); + break; + case MODE_DEAUTH: + parse_deauth(frame, args, header, packet); + break; + case MODE_DISASSOC: + parse_disassoc(frame, args, header, packet); + break; + case MODE_ASSOC_REQUEST: + parse_assoc_request(frame, args, header, packet); + break; + case MODE_ASSOC_RESPONSE: + parse_assoc_response(frame, args, header, packet); + break; + case MODE_REASSOC_REQUEST: + parse_reassoc_request(frame, args, header, packet); + break; + case MODE_REASSOC_RESPONSE: + parse_reassoc_response(frame, args, header, packet); + break; + case MODE_EAPOL: + parse_data_eapol(frame, args, header, packet); + break; + case MODE_DATA: + parse_data(frame, args, header, packet); + break; + case MODE_ALL: + parse_beacon(frame, args, header, packet); + parse_probe_request(frame, args, header, packet); + parse_probe_response(frame, args, header, packet); + parse_deauth(frame, args, header, packet); + parse_disassoc(frame, args, header, packet); + parse_assoc_request(frame, args, header, packet); + parse_assoc_response(frame, args, header, packet); + parse_reassoc_request(frame, args, header, packet); + parse_reassoc_response(frame, args, header, packet); + parse_data_eapol(frame, args, header, packet); + parse_data(frame, args, header, packet); + default: + break; + } + + libwifi_free_bss(&bss); + libwifi_free_wifi_frame(&frame); +} + +void help(const char *name) { + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\t%s --interface [interface] [--mode] [--radiotap]\n", name); + fprintf(stderr, "\t\tor\n"); + fprintf(stderr, "\t%s --file [capture file] [--mode] [--radiotap]\n", name); + fprintf(stderr, "\n"); + fprintf(stderr, "Modes:\n"); + fprintf(stderr, "\t--beacon\n"); + fprintf(stderr, "\t--probe-req\n"); + fprintf(stderr, "\t--probe-resp\n"); + fprintf(stderr, "\t--deauth\n"); + fprintf(stderr, "\t--disassoc\n"); + fprintf(stderr, "\t--assoc-req\n"); + fprintf(stderr, "\t--assoc-resp\n"); + fprintf(stderr, "\t--reassoc-req\n"); + fprintf(stderr, "\t--reassoc-resp\n"); + fprintf(stderr, "\t--eapol\n"); +} + +void handle_args(int argc, const char *argv[]) { + char errbuf[PCAP_ERRBUF_SIZE]; + + if (argc < 4) { + help(argv[0]); + exit(EXIT_SUCCESS); + } + + if (strcmp(argv[1], "--file") == 0) { + if ((handle = pcap_open_offline(argv[2], errbuf)) == NULL) { + fprintf(stderr, "Couldn't read file %s: %s\n", argv[2], errbuf); + exit(EXIT_FAILURE); + } + } else if (strcmp(argv[1], "--interface") == 0) { + if ((handle = pcap_create(argv[2], errbuf)) == NULL) { + fprintf(stderr, "Failed to open interface \"%s\" for sniffing: %s\n", argv[2], errbuf); + exit(EXIT_FAILURE); + } + if (pcap_activate(handle) == 0) { + printf("[+] Started sniffing on %s\n", argv[2]); + } else { + fprintf(stderr, "[!] Couldn't activate capture: %s.\n", pcap_geterr(handle)); + pcap_close(handle); + exit(EXIT_FAILURE); + } + } else { + help(argv[0]); + exit(EXIT_SUCCESS); + } + + if (strcmp(argv[3], "--beacon") == 0) { + mode = MODE_BEACON; + } else if (strcmp(argv[3], "--probe-req") == 0) { + mode = MODE_PROBE_REQUEST; + } else if (strcmp(argv[3], "--probe-resp") == 0) { + mode = MODE_PROBE_RESPONSE; + } else if (strcmp(argv[3], "--deauth") == 0) { + mode = MODE_DEAUTH; + } else if (strcmp(argv[3], "--disassoc") == 0) { + mode = MODE_DISASSOC; + } else if (strcmp(argv[3], "--assoc-req") == 0) { + mode = MODE_ASSOC_REQUEST; + } else if (strcmp(argv[3], "--assoc-resp") == 0) { + mode = MODE_ASSOC_RESPONSE; + } else if (strcmp(argv[3], "--reassoc-req") == 0) { + mode = MODE_REASSOC_REQUEST; + } else if (strcmp(argv[3], "--reassoc-resp") == 0) { + mode = MODE_REASSOC_RESPONSE; + } else if (strcmp(argv[3], "--eapol") == 0) { + mode = MODE_EAPOL; + } else if (strcmp(argv[3], "--data") == 0) { + mode = MODE_DATA; + } else if (strcmp(argv[3], "--all") == 0) { + mode = MODE_ALL; + } else { + help(argv[0]); + exit(EXIT_SUCCESS); + } + + if (argc > 4) { + if (strcmp(argv[4], "--radiotap") == 0) { + parse_radiotap_header = 1; + } + } +} + +int main(int argc, const char *argv[]) { + packet_num = 0; + char errbuf[PCAP_ERRBUF_SIZE]; + + handle_args(argc, argv); + + int linktype = pcap_datalink(handle); + if (linktype == DLT_IEEE802_11_RADIO) { + got_radiotap = 1; + } else if (linktype == DLT_IEEE802_11) { + got_radiotap = 0; + } else { + fprintf(stderr, "[!] 802.11 and radiotap headers not provided (%d)\n", pcap_datalink(handle)); + pcap_close(handle); + exit(EXIT_FAILURE); + } + + if ((filter = malloc(sizeof(struct bpf_program))) == NULL) { + perror("Malloc failure"); + pcap_close(handle); + exit(EXIT_FAILURE); + } + printf("[*] Compiling and optimizing frame filter, this can take a second\n"); + if (pcap_compile(handle, filter, FILTER, 0, 0) != 0) { + fprintf(stderr, "[!] Couldn't compile filter: %s\n", pcap_geterr(handle)); + pcap_close(handle); + free(filter); + exit(EXIT_FAILURE); + } + if (pcap_setfilter(handle, filter) != 0) { + fprintf(stderr, "[!] Couldn't set filter: %s\n", pcap_geterr(handle)); + pcap_close(handle); + free(filter); + exit(EXIT_FAILURE); + } + printf("[+] Complete\n"); + + pd = pcap_dump_open(handle, PCAP_SAVEFILE); + pcap_loop(handle, -1 /*INFINITY*/, &parse_packet, (unsigned char *) pd); + + return 0; +} -- cgit 1.4.1