【ESP8266】ESP8266 sniffer使用示例(基于NONOS SDK)

前言

想接触ESP8266 sniffer也是比较巧合,因为看到国外论坛一篇文章激发了我的兴趣,他是使用ESPduino开发环境的,但我习惯于官方SDK开发,就想着能不能找到相关API接口。一查资料,还真的有。就是ESP8266 sniffer。

根据乐鑫官网显示,2017年05月05日ESP8266 NONOS SDK已经升级到2.1.0版本了。版本都迭代更新到2.1了,发现自己对Sniffer 相关接口还没有一定的了解,所以特此写下本文记录,也方便后来者学习参考。

面向的读者

本文主要面向ESP8266开发者。建议阅读本文前请确定自己具备以下基础,否则可能会有看不懂的地方或者使用示例工程达不到预期效果的情况,包括但不限于:

  • 阅读ESP8266 NONOS SDK源码的基础能力
  • ESP8266开发环境的搭建、烧录和调试

提醒:ESP8266 NONOS SDK v2.0编译出来的二进制文件,烧写地址和以前版本有点不一样。

开发环境

  • Windows 10 x64
  • ESP8266 IDE 2.0(安信可)
  • NodeMCU(4MB Flash ESP8266)

Sniffer介绍

那么什么是snffer呢?sniffer可以翻译为混杂模式,ESP8266可以进入该模式,接收空中的 IEEE802.11 包。SDK主要提供的接口有:

接口说明
wifi_promiscuous_enable开启混杂模式
wifi_promiscuous_set_mac设置 sniffer 模式时的 MAC 地址过滤
wifi_set_promiscuous_rx_cb注册混杂模式下的接收数据回调函数,每收到一包数据,都会进入注册的回调函数。
wifi_get_channel获取信道号
wifi_set_channel设置信道号,用于混杂模式

更具体的详细说明可以看文档。

核心代码

下面放上核心代码,文件是sniffer.c,主要有两个初始化:sniffer_initsniffer_init_in_system_init_donesniffer_init是在user_init里面调用,做一些定时器的初始化,sniffer_init_in_system_init_done是放在ESP8266底层系统初始化后的回调函数(相关API:system_init_done_cb),如果不放在这里调用可能会导致sniffer功能初始化不成功。

channelHop函数和promisc_cb函数是定时器回调函数。

channelHop每调用一次会改变ESP8266扫描WiFi的channel,可在include/sniffer.h修改CHANNEL_HOP_INTERVAL数值,博主工程默认是3000ms。

promisc_cb函数则可以参考SDK文档的wifi_set_promiscuous_rx_cb API函数说明:「每收到一包数据,都会进入注册的回调函数」。该函数就是对这些数据包进行处理,然后打印出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,避免重复打印
		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);
}

另外,如果有时间的话,会考虑分析一下源文件中WiFi相关的结构体(比如struct RxControl),随后会更新本文。

示例工程

那么下面就放上我测试通过的sniffer使用示例工程。看工程学习使用是最快速的方法。使用本工程可以抓取Client和AP的MAC地址。另外博主已经能成功抓到自己手机的MAC了。

示例工程:

  • CSDN:http://download.csdn.net/detail/u012163234/9853894
  • github:https://github.com/AngelLiang/ESP8266-Demos

本工程效果图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-THBeK9Gf-1572189894912)(https://github.com/AngelLiang/ESP8266-Demos/raw/master/img/sniffer.jpg)]


本文最后编辑时间:2017年7月


好饿啊,早知道不做物联网了

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值