欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ESP8266基于NON_OS的sniffer模式开发学习

程序员文章站 2024-03-23 09:48:52
...

最近调试测试了通过成功抓取周边手机wifi广播的Probe request帧来收集手机的MAC地址。在此记录下学习过程。

一开始的思路就是将ESP8266设置为AP模式,让手机连接上ESP8266,来获取手机wifi的MAC地址。调试完后可以读出连接上ESP8266的手机的WIFI MAC地址。相关的调试过程会在之后记录下来。但是这里的话,需要手机主动连接上ESP8266的动作。在查阅了相关的资料,手机之所以能搜索到周围的wifi热点,是因为热点会向周围广播Beacon帧,手机wifi收到后就知道了有它们的存在。当手机wifi打开后,手机wifi也会向周围主动广播Probe request帧。这就是主动搜索与被动搜索的结果。那能否通过抓取手机wifi广播的Probe request帧来抓取得到手机WiFi的MAC地址呢?

在esp8266_sd_api_guide文档说明中果然有Sniffer相关接口可以帮助实现。什么是sniffer模式?一般我们在讲的Sniffer程序是把NIC(网络适配卡,一般如以太网卡)置为一种叫promiscuous杂乱模式的状态,一旦网卡设置为这种模式,它就能是Sniffer程序能接受传输在网络上的每一个信息包。

1.void wifi_promiscuous_enable(uint8 promiscuous);
功能:开启混杂模式(sniffer)
    uint8 promiscuous :
        0:关闭混杂模式
        1:开启混杂模式

注意:
(1)仅支持在ESP8266单station模式下,开启混杂模式
(2)混杂模式下,ESP8266 station和 soft-AP接口均失效。
(3)若开启了混杂模式,请先调用wifi_station_disconnect确保没有连接
(4)混杂模式中请勿调用其他API,请先调用wifi_promiscuous_enable(0)退出snfiier。



2.void wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb);
功能:注册混杂模式下的接收数据回调函数,每收到一包数据,都会进入注册的回调函数

3.bool wifi_set_channel(uint8 channel);
功能:设置信道号,用于混杂模式
接下来,开始看代码
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();
    system_init_done_cb(system_init_done);
}

在user_init()函数中,进行sniffer_init()对sniffer函数进行初始化。

void ICACHE_FLASH_ATTR

sniffer_init(void)
{

    wifi_set_opmode(STATION_MODE);          //sniffer只能在单sta模式下开启
    os_timer_disarm(&channelchange_timer);  
    os_timer_setfn(&channelHop_timer, (os_timer_func_t *) channelchange, NULL);
    os_timer_arm(&channelchange_timer, 3000, 1);        //每隔3S钟转换wifi的扫描通道

}

//在user_init中调用,注册系统初始化完成的回调函数。
system_init_done_cb(system_init_done);    
//system_init_done是系统初始化完成的回调函数

void ICACHE_FLASH_ATTR
system_init_done(void)
{
    wifi_set_channel(1);                            //初始化为通道1
    wifi_promiscuous_enable(0);                     //先关闭混杂模式
    //注册混杂模式下的接收数据的回调函数,每收到一包数据,都会进入注册的回调函数里面。
    //  promisc_cb 即回调函数,在里面抓取MAC地址
    wifi_set_promiscuous_rx_cb(promisc_cb);                
    wifi_promiscuous_enable(1);                     //开启混杂模式
}
static void ICACHE_FLASH_ATTR
promisc_cb(uint8_t *buf, uint16_t len)
{
    if (len == 12){
        /*
         * len == 12
    	 * buf的数据是结构体RxControl,该结构体的是不太可信的,它无法表示包所属的发送和接收者, 
         * 也无法判断该包的包头长度
    	 * 对于AMPDU包,也无法判断子包的个数和每个子包的长度
    	 * 该结构体中较为有用的信息有:包长,rssi和FEC_CODING
    	 * RSSI和FEC_CODING可以用于评估是否是同一个设备所发
    	*/
        struct RxControl *sniffer = (struct RxControl*) buf;
    } else if (len == 128) {
        /*
         * len == 128
    	 * buf的数据是结构体sniffer_buf2,该结构体对应的数据包是管理包,含有112字节的数据。
    	 *sniffer_buf2.cnt为1
    	 *sniffer_buf2.len为管理包的长度
    	 */
        struct sniffer_buf2 *sniffer = (struct sniffer_buf2*) buf;
        
        if(sniffer->buf[0]==64)
		{
			/*
             * 见IEEE-802.11-2012文档上8.2.4.1.3小节的Type and Subtype fields有管理包,数据        
             * 包,控制包如何分类资料。
			 * sniffer->buf[0]==128 ---->Beacon(管理包)
			 * sniffer->buf[0]==64	---->probe request(管理包)
			 * sniffer->buf[0]==8	---->Data(数据包)
			 * sniffer->buf[0]==200	---->QoS Null(no data)(数据包)
			 * sniffer->buf[0]==148	---->Block Ack(控制包)
			 * sniffer->buf[0]==136	---->QoS Data(数据包)
			 * sniffer->buf[0]==72	---->NULL(数据包)
			 * */

				//MAC帧的目的地址
				printmac(sniffer->buf, 4);
				//MAC帧的源地址
				printmac(sniffer->buf, 10);        //就可以在这里扫描到你的手机MAC地址了
				os_printf("\n");
        }
    } else {
        /*
         *len == 10,
         *buf的数据是结构体sniffer_buf,该结构体时比较可信的,它对应的数据包是通过CRC校验正确的
         */
        struct sniffer_buf *sniffer = (struct sniffer_buf*) buf;
    }
}

 

相关标签: esp8266

上一篇: 多客户端文件上传

下一篇: