前言
想接觸ESP8266 sniffer也是比較巧合咐吼,因?yàn)榭吹絿庹搲黄恼录ぐl(fā)了我的興趣吹缔,他是使用ESPduino開發(fā)環(huán)境的,但我習(xí)慣于官方SDK開發(fā)锯茄,就想著能不能找到相關(guān)API接口厢塘。一查資料,還真的有肌幽。就是ESP8266 sniffer晚碾。
根據(jù)樂鑫官網(wǎng)顯示,2017年05月05日ESP8266 NONOS SDK已經(jīng)升級(jí)到2.1.0版本了喂急。版本都迭代更新到2.1了格嘁,發(fā)現(xiàn)自己對(duì)Sniffer 相關(guān)接口還沒有一定的了解,所以特此寫下本文記錄廊移,也方便后來者學(xué)習(xí)參考糕簿。
建議
建議閱讀本文前請(qǐng)確定自己具備以下基礎(chǔ),否則可能會(huì)有看不懂的地方狡孔,包括但不限于:
- 閱讀ESP8266 NONOS SDK源碼的基礎(chǔ)能力
- ESP8266開發(fā)環(huán)境的搭建懂诗、燒錄和調(diào)試
Sniffer介紹
那么什么是snffer呢?sniffer可以翻譯為混雜模式苗膝,ESP8266可以進(jìn)入該模式殃恒,接收空中的 IEEE802.11 包。SDK主要提供的接口有:
接口 | 說明 |
---|---|
wifi_promiscuous_enable | 開啟混雜模式 |
wifi_promiscuous_set_mac | 設(shè)置 sniffer 模式時(shí)的 MAC 地址過濾 |
wifi_set_promiscuous_rx_cb | 注冊(cè)混雜模式下的接收數(shù)據(jù)回調(diào)函數(shù)辱揭,每收到一包數(shù)據(jù)离唐,都會(huì)進(jìn)入注冊(cè)的回調(diào)函數(shù)。 |
wifi_get_channel | 獲取信道號(hào) |
wifi_set_channel | 設(shè)置信道號(hào)问窃,用于混雜模式 |
更具體的詳細(xì)說明可以看文檔亥鬓。
核心代碼
下面放上核心代碼,文件是sniffer.c
泡躯,主要有兩個(gè)初始化:sniffer_init
和sniffer_init_in_system_init_done
贮竟,sniffer_init
是在user_init
里面調(diào)用,做一些定時(shí)器的初始化较剃,sniffer_init_in_system_init_done
是放在ESP8266底層系統(tǒng)初始化后的回調(diào)函數(shù)(相關(guān)API:system_init_done_cb
)咕别,如果不放在這里調(diào)用可能會(huì)導(dǎo)致sniffer功能初始化不成功。
channelHop
函數(shù)和promisc_cb
函數(shù)是定時(shí)器回調(diào)函數(shù)写穴。
channelHop
每調(diào)用一次會(huì)改變ESP8266掃描WiFi的channel惰拱,可在include/sniffer.h
修改CHANNEL_HOP_INTERVAL
數(shù)值,博主工程默認(rèn)是3000ms啊送。
promisc_cb
函數(shù)則可以參考SDK文檔的wifi_set_promiscuous_rx_cb
API函數(shù)說明:「每收到一包數(shù)據(jù)偿短,都會(huì)進(jìn)入注冊(cè)的回調(diào)函數(shù)」。該函數(shù)就是對(duì)這些數(shù)據(jù)包進(jìn)行處理馋没,然后打印出Client的MAC和AP的MAC昔逗。
//省略……
void ICACHE_FLASH_ATTR
channelHop(void *arg)
{
// 1 - 13 channel hopping
uint8 new_channel = wifi_get_channel() % 12 + 1;
os_printf("** hop to %d **\t Client MAC\t\t AP MAC\r\n", new_channel);
wifi_set_channel(new_channel);
}
//省略……
static void ICACHE_FLASH_ATTR
promisc_cb(uint8_t *buf, uint16_t len)
{
if (len == 12){
struct RxControl *sniffer = (struct RxControl*) buf;
} else if (len == 128) {
struct sniffer_buf2 *sniffer = (struct sniffer_buf2*) buf;
} else {
struct sniffer_buf *sniffer = (struct sniffer_buf*) buf;
int i=0;
// Check MACs
// 如果MAC地址和上一次一樣就返回
if(0==os_memcmp(temp_mac, &sniffer->buf[4], 6)){
return;
}
// 緩存上次的MAC,避免重復(fù)打印
for (i=0; i<6; i++){
temp_mac[i] = sniffer->buf[i+4];
}
#if SNIFFER_TEST
os_printf("-> %3d: %d", wifi_get_channel(), len);
printmac(sniffer->buf, 4);
printmac(sniffer->buf, 10);
os_printf("\n");
#endif
// 判斷client
for (i=0; i<6; i++) if (sniffer->buf[i+4] != client[i]) return;
printmac(sniffer->buf, 4);
os_printf("\r\n");
os_printf("\trssi:%d\r\n", sniffer->rx_ctrl.rssi);
os_printf("\tchannel:%d\r\n", sniffer->rx_ctrl.channel);
os_printf("\trate:%d\r\n", sniffer->rx_ctrl.rate);
os_printf("\tsig_mode:%d\r\n",sniffer->rx_ctrl.sig_mode);
// 判斷AP
//for (i=0; i<6; i++) if (sniffer->buf[i+10] != ap[i]) return;
//printmac(sniffer->buf, 10);
//os_timer_disarm(&channelHop_timer);
}
}
void ICACHE_FLASH_ATTR
sniffer_init(void)
{
// Promiscuous works only with station mode
wifi_set_opmode(STATION_MODE);
//省略……
os_timer_disarm(&channelHop_timer);
os_timer_setfn(&channelHop_timer, (os_timer_func_t *) channelHop, NULL);
os_timer_arm(&channelHop_timer, CHANNEL_HOP_INTERVAL, 1);
}
void ICACHE_FLASH_ATTR
sniffer_init_in_system_init_done(void)
{
// Set up promiscuous callback
wifi_set_channel(1);
wifi_promiscuous_enable(0);
wifi_set_promiscuous_rx_cb(promisc_cb);
wifi_promiscuous_enable(1);
}
user_main.c
初始化代碼如下:
void ICACHE_FLASH_ATTR
system_init_done(void)
{
sniffer_init_in_system_init_done();
}
void ICACHE_FLASH_ATTR
user_init()
{
uart_init(115200, 115200);
os_printf("\r\n\r\nSDK version:%s\n", system_get_sdk_version());
sniffer_init();
// Continue to 'sniffer_system_init_done'
system_init_done_cb(system_init_done);
}
另外篷朵,如果有時(shí)間的話勾怒,會(huì)考慮分析一下源文件中WiFi相關(guān)的結(jié)構(gòu)體(比如struct RxControl
),隨后會(huì)更新本文声旺。
示例工程
那么下面就放上我測(cè)試通過的sniffer使用示例工程笔链。看工程學(xué)習(xí)使用是最快速的方法腮猖。使用本工程可以抓取Client和AP的MAC地址鉴扫。另外博主已經(jīng)能成功抓到自己手機(jī)的MAC了。
示例工程:
- CSDN:http://download.csdn.net/detail/u012163234/9853894
- github:https://github.com/AngelLiang/ESP8266-sniffer-demo
本工程效果圖:
![效果圖](https://github.com/AngelLiang/ESP8266-sniffer-demo/raw/master/img/demo.jpg)
本文最后編輯時(shí)間:2017年6月
本文首發(fā)于CSDN:http://blog.csdn.net/yannanxiu/article/details/72778688