Wifi sniffers, barat i fàcil
Introducció
La física de WiFi
WiFi Sniffers ha estat al voltant de la mateixa manera que WiFi. El concepte és senzill: imagineu-vos que teniu una llanterna a les fosques. Bril·la la llum en un radi de 360 graus al seu voltant i qualsevol persona que estigui dins dels seus voltants podrà veure la llum. Ara, imagineu -vos que la llum emesa per la llanterna és invisible i pot passar per objectes sòlids: això és exactament el que són els senyals WiFi, tot i que immensament sobredimensionats.
De fet, els senyals WiFi són una forma de radiació electromagnètica (EMR), la mateixa que la llum, els raigs X i fins i tot les làmpades de calor. La seva freqüència relativament baixa li permet penetrar objectes sòlids, en cas contrari, no podreu connectar -vos al vostre wifi si hi ha una paret entre vosaltres i el punt d’accés.
concepte
Com que s’està intercanviant informació mitjançant aquests senyals WiFi, això suposa un interès per a possibles actors maliciosos o simplement persones curioses. Amb el maquinari i el coneixement mínim del tema, és possible capturar i registrar tots els senyals wifi que es troben als voltants, i això és el que explorarem avui.
Preparació
Materials
Per fer el nostre sniffer wifi, només necessitem un ordinador que pugui accedir a WiFi i que tingui un adaptador capaç d’entrar en mode promiscu. Al meu last post, vaig introduir el "mini ordinador" SOC ESP32 per Espressif. Són extraordinàriament barats, petits i poderosos. Podeu comprar un here per uns 7 dòlars USD.
Programari
Per escriure el sniffer, utilitzarem la esp-idf eina cadena (refer to this post to see why). Utilitzo el VSCode IDE com a editor de text, però quin editor utilitzeu és preferència personal i no fa cap diferència.
Escriure el codi
El codi d’aquest projecte és molt senzill i només un POC, de manera que és mínim i no és útil. En els projectes ESP-IDF, comencem amb un punt d’entrada a la nostra funció app_main()
. Abans de fer res, hem de fer uns quants passos de configuració requisits previs per inicialitzar els mètodes WiFi i de trucada:
- Inicieu el bucle d'esdeveniments ESP32
- Inicialitzeu el flaix NVS
- Inicialitzar la interfície de xarxa
- Configura la interfície de xarxa
Passos 1 i 2
Aquests passos són molt senzills i força estàndard per a projectes d’aquest tipus: aquí teniu el codi que explicaré a continuació. Recordeu -ho, tot això es troba a la nostra funció d’entrada.
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
El pas 1 es troba completament en una sola línia de codi de la línia 1- La resta inicialitza el flaix NVS. Aquí hi ha una comprovació condicional que, en cas d’error, esborra la memòria flash i intenta inicialitzar -la de nou. La funció ESP_ERROR_CHECK()
que veieu al llarg d'aquest fragment és una funció integrada que accepta un codi de devolució i llança un error si el codi de devolució és qualsevol cosa, excepte l'èxit.
Passos 3 i 4
Ara que estem preparats per utilitzar l’ESP32, hem de configurar els components de xarxa. He extret aquests passos en una funció separada, que només s’anomena de la funció principal per tal d’organitzar el codi una mica millor:
static void setup_wifi(void) {
// Initializ
ESP_LOGI(TAG, "Beginning wifi setup");
ESP_ERROR_CHECK(esp_netif_init());
// Interface defaults
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
assert(sta_netif);
// Default config
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
esp_wifi_set_ps(WIFI_PS_MAX_MODEM);
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
// Setup callback
wifi_promiscuous_cb_t callback = &wifi_callback;
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(callback));
// Set station mode and start
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_start());
// Config filters and stuff
wifi_promiscuous_filter_t filter = {.filter_mask =
WIFI_PROMIS_FILTER_MASK_MGMT};
esp_wifi_set_promiscuous_filter(&filter);
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
ESP_LOGI(TAG, "Wifi started successfully");
wifi_mode_t ptr;
ESP_ERROR_CHECK(esp_wifi_get_mode(&ptr));
const char *c = wifi_mode_to_string(ptr);
ESP_LOGI(TAG, "Mode: %s", c);
}
Per tal d’utilitzar realment aquests paquets, hem de crear una funció de devolució, que s’anomena sempre que es capti un fotograma que coincideixi amb el filtre, que fem a la línia 15-16.
A la línia 23, vaig establir un filtre només per capturar fotogrames de gestió, que és només un tipus de missatge: ho faig sense cap altra raó que reduir el soroll creat per aquest programa, en cas contrari, hi hauria milers de paquets per segon que colpegen la interfície. Aquest codi és força explicatiu, però és possible que no noti que anomeno una funció anomenada wifi_mode_to_string
. Això es deu al fet que el membre wifi_mode_t
és un enum i el gran llenguatge C no és capaç d’imprimir la representació de cadenes d’un enum, de manera que hem de mapar -lo manualment:
const char *wifi_mode_to_string(wifi_mode_t mode) {
switch (mode) {
case WIFI_MODE_NULL:
return "WIFI_MODE_NULL";
case WIFI_MODE_STA:
return "WIFI_MODE_STA";
case WIFI_MODE_AP:
return "WIFI_MODE_AP";
case WIFI_MODE_APSTA:
return "WIFI_MODE_APSTA";
case WIFI_MODE_NAN:
return "WIFI_MODE_NAN";
case WIFI_MODE_MAX:
return "WIFI_MODE_MAX";
default:
return "UNKNOWN_MODE";
}
}
posar -ho tot junt
Ara tot està configurat, només hem de crear la funció de trucada WiFi i les dades de registre que obtenim. En la nostra funció de trucada, ja que es tracta d’un POC, no hem de fer res més que imprimir els fotogrames
void wifi_callback(void *buf, wifi_promiscuous_pkt_type_t type) {
const uint16_t data_length = 256;
ESP_LOGI(TAG, "Printing first %d bytes of received packet with type %s\n",
data_length, wifi_pkt_type_to_string(type));
unsigned char *char_buf = (unsigned char *)buf;
for (int i = 0; i < data_length; i++) {
printf("%02X ", char_buf[i]); // 1 byte = 0x00, two hex chars
if (i % 16 == 15) { // Organize it by groups of 16 bytes because im spoiled by wireshark
printf("\n");
}
}
}
executant
Ara simplement naveguem al directori de treball del projecte i construïm el projecte, compilem -lo, el flaixem a l’ESP32 i, finalment, establim una connexió UART per poder veure la sortida. Ho podem fer amb una ordre senzilla:
idfx build && idfx flash COM11 monitor
I aquí és el que sembla la sortida
Conclusió
Com s'ha apuntat al principi, això és només un POC, i és no útil realment de qualsevol manera pràctica. Hi ha eines establertes i fantàstiques ja creades per a aquest propòsit, com ara Wireshark i Air*-ng suite.
L’objectiu d’aquest post és proporcionar una explicació i una visió general simplificades del que és l’enrenou WiFi i el fàcil que es pot aconseguir. Com a tal, espero que he pogut explicar les coses bé: no sóc fantàstic per escriure publicacions del bloc, però estic intentant millorar, així que si us plau, tingueu amb mi.