Flipper Zero 上的 nRF24L01+ 嗅探扫描器:Nrf24_Scanner 源码解析与实战使用指南
2026/9/14 15:16:40 网站建设 项目流程

Flipper Zero 上的 nRF24L01+ 嗅探扫描器:Nrf24_Scanner 源码解析与实战使用指南

【免费下载链接】FlipperPlayground (and dump) of stuff I make or modify for the Flipper Zero项目地址: https://gitcode.com/GitHub_Trending/fl/Flipper

Nrf24_Scanner(Nrf24_Scanner.fap)是运行在 Flipper Zero 上的 nRF24L01+ 2.4GHz 无线电模块嗅探与扫描工具,它可以在 "sniff"(嗅探)模式下以 RAW 格式捕获任意地址的 Enhanced ShockBurst 数据包,也可以按照配置文件中给定的地址列表进行定向 "scan"(扫描),还支持数据包重放(resend)与 CRC 校验解码。本文以仓库 Applications/Official/source-OLDER/xMasterX/nrf24scan/README.md 为骨架,结合 nrf24scan.c 与 nrf24 驱动库源码,完整讲解它的功能模式、设置文件格式、按键操作、接线方式与底层实现原理,帮助你在拿到 .fap 文件后快速上手,并理解它是如何在 Flipper Zero 上"裸听"整个 2.4GHz 频段无线电信号的。

1. 项目概览:这是什么,能做什么

该应用是一个面向 Flipper Zero 的 nRF24L01 驱动与嗅探工具。nRF24L01 是 Nordic Semiconductor 出品的一类非常流行的 2.4GHz 无线收发芯片,大量用于无线鼠标键盘、遥控器、无人机遥控、私有无线协议设备等场景。通过外接一个 nRF24L01+ 模块,Flipper Zero 就能对这类 2.4GHz 信号进行监听与重放。

从 application.fam 可以看到它的应用元数据:应用 ID 为Nrf24_Scanner,入口函数为nrf24scan_app,属于外部应用(apptype=FlipperAppType.EXTERNAL),分类归入GPIO_Extra,并以内置私有库(fap_private_libs)的方式把nrf24.c驱动一起编译成最终的Nrf24_Scanner.fap。仓库的 Distr/Nrf24_Scanner.fap 中已附带可直接安装的编译产物。

工具的核心能力可以归纳为:

  • Sniff 嗅探:不指定目标地址,捕捉所有带正确前导码(preamble)与 CRC 的有效 RAW 数据包;
  • Scan 扫描:按设置文件中给定的 1~6 个管道地址(pipe address)定向接收 ESB/DPL 数据包;
  • 地址发现:统计出现两次及以上的唯一地址,供后续针对性扫描;
  • 数据回放:在日志列表中选中任意已捕获数据包,按下 OK 即可重发(resend);
  • PCF 与 CRC 解码:在查看模式下解码 Enhanced ShockBurst 的 Packet Control Field,并逐位扫描定位 CRC 字节。

2. 硬件接线与模块供电

应用通过 Flipper Zero 的外部 SPI 总线(furi_hal_spi_bus_handle_external)驱动 nRF24L01+,其中 CE 引脚固定映射到外部引脚gpio_ext_pb2(见 nrf24.h 中nrf24_CE_PINnrf24_HANDLE的宏定义)。具体接线方式在 README.md 中有明确说明:

Flipper Zero 引脚nRF24L01 引脚信号
2 / A7MOSI / 6SPI 主出从入
3 / A6MISO / 7SPI 主入从出
4 / A4CSN / 4片选(低有效)
5 / B3SCK / 5SPI 时钟
6 / B2CE / 3片使能(收发切换)
8 / GNDGND / 1
9 / 3V3VCC / 23.3V 供电
IRQ / 8悬空不接

该接线图最初来自 NoComp/Frog 的整理,README 中同时还给出了 UberGuidoZ 整理的同一套接法。需要注意的是,IRQ 引脚不需要连接,代码中也没有使用中断方式,而是通过轮询 STATUS 寄存器(RX_DR位)来取包,见 nrf24scan.c 中对nrf24_rxpacket的调用。

供电方面,如果模块工作不稳定,建议在 VCC 与 GND 之间并联电容:3.3µF 到 10µF 的电解电容用于应对慢速频率变化,再并联一颗 0.1µF 的陶瓷电容应对高频开关尖峰。若只做简单的 Mousejack 攻击类操作,单独一颗 10µF 电容通常就够了。接线时务必注意电容正负极方向(负极接 GND)。

3. 安装与运行方式

把 Nrf24_Scanner.fap 复制到 SD 卡的apps/GPIO_Extra(或自定义应用目录)下,按上述接线连接好 nRF24L01+ 模块后,即可在 Flipper Zero 的应用菜单中找到[NRF24] Scanner并启动。从源码看,应用启动时会自动创建ext/nrf24scan目录(SCAN_APP_PATH_FOLDER,见 nrf24scan.c),并尝试自动加载该目录下的sniff.txt设置文件,若文件不存在则回退到默认嗅探配置(默认地址00 55、CRC 2 字节)。

也就是说,你不需要在 SD 卡上预先放置任何文件,插上模块直接运行即可进入 sniff 模式;配置文件只是用来精细定制扫描目标。

4. 两种工作模式:Sniff 与 Scan

应用核心的状态机定义在 nrf24scan.c:

  • what_doing:0 = 设置界面,1 = 查看日志列表,2 = 查看地址/解码视图;
  • what_to_do:0 = 仅查看(view),1 = 嗅探(view & sniff),2 = 扫描(view & read),3 = 按选中地址定向读取(view & read selected addr)。

4.1 Sniff 模式(默认)

启动后默认进入嗅探模式:捕获所有带有效前导码和 CRC 的 RAW 包。由于是 RAW 格式读取,负载长度最大为 23 字节,更长的数据包无法被捕获(这个限制来自 nRF24L01 自身 FIFO 在 promiscuous 模式下的行为)。设置里可以指定最小负载长度(Min Payl),用于过滤掉过短的碎片。

嗅探时应用将芯片配置为"近似混杂模式":关闭自动应答、关闭动态负载、掩蔽全部中断并关闭 CRC(见 nrf24scan.c 中对REG_CONFIGREG_EN_AAREG_FEATURE的写入)。捕获到数据后,应用会对数据包做逐位左移(bit-shift)扫描并反复校验 CRC(nrf24scan.c),这能大幅提高抓到有效包的几率,但代价是垃圾包的数量也会明显增加——这是因为无法精确定位包边界,只能靠 CRC 命中来判定。整个逐位滑动过程的计算量由calc_crc承担,它会按 8 位 CRC(多项式0x07)或 16 位 CRC(多项式0x1021)增量计算校验值。

在嗅探过程中,所有出现两次及以上的唯一地址会被统计进 "Found > 1" 列表(上限MAX_FOUND_RECORDS= 70 条,每个地址记录addr_size、地址字节与出现次数total,见 nrf24scan.c)。嗅探结束后可以切换到按这些发现地址扫描,或单独扫描某个数据包对应的地址,甚至可以扫描一组仅最低有效字节(LSB)不同的地址族(pipe 0~5)。

4.2 Scan 模式

扫描模式就是按设置文件中给定的 MAC 地址(最多 6 个 pipe)与包类型(ESB/DPL)定向读取数据包。在prepare_nrf24中,地址数量决定启用哪些接收管道:addr_count > 1时启用 RX_P1,>2 时启用 RX_P2,以此类推,并通过REG_EN_RXADDR一次性使能(nrf24scan.c)。注意 nRF24L01 的硬件特性:P2~P5 的地址只有 1 个字节是独立可配的,其余高位字节与 P1 相同,这正是设置文件中 P2~P5 只写 1 字节 LSB 的原因。

切换 sniff/scan 只需在设置界面把光标移到 "Start sniff / Start scan (pipes: N)" 一栏,用左右方向键在what_to_do各取值间循环即可(nrf24scan.c)。

4.3 通道轮换

设置项 "Next Ch time" 控制自动扫频:设为一个正数秒后,应用会周期性把通道号 +1,并在超过 125 时回绕到 0(MAX_CHANNEL= 125,见 nrf24scan.c)。该逻辑在事件循环中通过furi_get_tick()start_time的时间差触发重新start_scanning()(nrf24scan.c)。若设为 0 则关闭自动轮换,锁定在固定通道。

5. 设置文件格式详解

设置文件默认名为addresses.txt(README 中的示例写为 addr.txt,以源码实现为准),存放于 SD 卡ext/nrf24scan/目录。程序启动时会优先尝试加载sniff.txt(嗅探专用设置),启动后也可以在设置界面通过 "Load" 菜单用文件浏览器选择其他.txt文件加载。

文件为纯文本、每行一个参数,#开头的行会被跳过。格式如下(与源码 nrf24scan.c 中的注释定义一致):

Rate: 0/1/2 # 速率(Mbps):0 = 250Kbps,1 = 1Mbps,2 = 2Mbps Ch: 0..125 # 默认通道号 ESB: 0/1 # 1 = Enhanced ShockBurst DPL: 0/1 # 1 = 动态负载长度(Dynamic Payload Length) CRC: 0/1/2 # CRC 长度(字节),0 = 关闭 Payload: 1..32 # 负载字节数;在 sniff 模式下表示最小负载长度 P0: AABBCCDDEE # 管道 0 地址,十六进制,最多 5 字节,LSB 在后 P1: AABBCCDDEE # 管道 1 地址,十六进制,最多 5 字节,LSB 在后 P2: LL # 管道 2 地址,仅 1 字节 LSB(高位与 P1 相同) P3: LL # 管道 3 地址,仅 1 字节 LSB P4: LL # 管道 4 地址,仅 1 字节 LSB P5: LL # 管道 5 地址,仅 1 字节 LSB

要点说明:

  • 地址字节序为 LSB last(MSB first),即十六进制串按从高位到低位的顺序书写;管道 2~5 只写 1 字节,因为 nRF24L01 硬件规定它们复用 P1 的高位地址;
  • 地址长度由 P0 推导ConvertHexToArray根据 P0 行实际解析出的字节数设置addr_len(2~5 字节),其余管道以同一长度解释(nrf24scan.c);
  • 其余设置(通道、速率、CRC 等)都可以在界面上交互式调整,长按 OK 可将当前配置保存回addresses.txt
  • 若文件含SNIFF关键字,则整份文件被当作嗅探配置加载(sniff_loaded = 1),此时Payload行解释为最小负载长度,P0/P1 最多解析 3 字节(嗅探用地址前缀)。

5.1 仓库自带的示例文件

Distr/nrf24scan/addresses.txt 演示了多管道配置:

Rate: 1 Ch: 2 ESB: 1 DPL: 0 CRC: 2 Payload: 4 P0: C8C8C0 P1: C8C8C1 P2: C2 P3: C3 P4: E5

这是一份针对以C8 C8为公共前缀的地址族进行扫描的配置:P0 为C8C8C0,P1 为C8C8C1,P2~P4 分别只给出 LSBC2C3E5,组合成C8C8C2C8C8C3C8C8E5等 5 个监听管道。地址长度由 P0 推导为 3 字节。

Distr/nrf24scan/addr-WCO1.txt 是单地址示例:通道 120、1Mbps、ESB+DPL、CRC 2 字节、负载 4 字节,目标地址C8C8E5

Distr/nrf24scan/sniff.txt 是嗅探配置示例:

SNIFF ESB: 1 CRC: 2 P0: 00AA P1: 0055

包含SNIFF关键字,定义了嗅探地址前缀00AA/0055,ESB 开启、CRC 2 字节。

5.2 日志文件与缓冲区

接收到的数据包保存在内存环形缓冲中(MAX_LOG_RECORDS= 200 条,每条LOG_REC_SIZE= 34 字节)。设置项Log控制自动落盘方式(nrf24scan.c):

  • No:不自动保存;
  • Yes:缓冲区满 99 条时写入一个新文件log.txt(已存在则自动编号为log-01.txtlog-02.txt…最多到 99,见write_to_log_file的循环命名逻辑,nrf24scan.c);
  • Append:追加到上一次的日志文件末尾;
  • Clear:仅清空缓冲区不保存。

日志文件每行是一串十六进制字节。每行前两个字节是元数据:第一个字节高位 0x80 表示 RAW 嗅探包,低 7 位为通道号;第二个字节的高 5 位为负载长度(0 表示 32),低 3 位在非 RAW 模式下为管道号(pipe 0~5),RAW 模式下低 2 位表示地址长度减 2、bit2 表示是否 ESB(详见 nrf24scan.c 的注释)。长按 OK 也可以随时手动把当前缓冲区写入文件。

6. 屏幕界面与按键操作

6.1 设置主界面(6 行菜单)

启动后默认显示设置界面,共 6 个菜单项(menu_selected_max= 5,枚举见 nrf24scan.c),上下方向键移动光标:

菜单项左右键调整短按 OK长按 OK
Load/Save 文件切换 Save/Load 状态保存设置 / 打开文件浏览器加载
Ch±1(长按重复时 ±10,越界回绕)切换 ESB / DPL / 关闭切换 AA(自动应答)开关
Rate / Min Payl / Payload调整速率或负载循环切换速率 0/1/2
Next Ch time±1 秒(重复时 ±10)循环切换 CRC 0/1/2
Log循环 No → Yes → Append → Clear手动写盘并清空缓冲
Start sniff/scan/view循环 what_to_do 0~3开始嗅探/扫描(进入日志视图)

其中:

  • Ch:通道号 0~125;
  • Rate:250Kbps / 1Mbps / 2Mbps;
  • Next Ch time:自动跳频间隔秒数,off 表示关闭;
  • Log:日志自动保存模式;
  • Start sniff / Start scan:启动对应模式。若配置有误(例如 nRF24 读写校验失败),界面会显示 "nRF24L01+ r/w ERROR!"(NRF_ERROR标志,由地址回读比对触发,见 nrf24scan.c)。

在 Ch 菜单项上长按 OK 可切换 "AA"(Auto Ack)显示与划掉状态,表示是否禁用自动应答。当 ESB 开启时,芯片会自动发送 ACK 确认帧——这意味着我们自己的接收器也会尝试应答,嗅探时可能造成冲突,必要时建议关闭。

6.2 日志列表视图

开始扫描/嗅探后进入日志视图:

  • 上/下键翻页浏览记录,每屏 8 条;左右键横向滚动查看超出屏幕宽度的数据;
  • 每条记录行首有索引号,当前选中行以>标记,发送过的包以*(成功)或!(失败)标记;
  • 第一行显示当前模式(Sniff/View/Read)、通道号与已捕获包数量;
  • 短按 OK:进入地址/解码视图;
  • 长按 OK:重发(resend)当前选中的数据包。发送结果通过 LED 反馈:蓝色闪烁表示发送成功,红色闪烁表示失败(nrf24scan.c)。

6.3 地址与解码视图

在日志列表中短按 OK 后进入解码视图:

  • 列表区显示所有被发现地址("Found > 1")及出现次数,或在 sniff 模式下显示嗅探地址前缀(Sniff prefix);
  • 底部显示选中包的通道、长度与 RAW/ESB/DPL 标记;
  • 左键<:切换 PCF 解码开关(view_log_decode_PCF);
  • 右键>:循环切换 CRC 解码长度 0 / 1 / 2 字节(view_log_decode_CRC);
  • 解码要求ESB 选项关闭(针对非 ESB 包做 CRC 定位扫描)。

6.4 PCF 与 CRC 解码输出含义

开启 PCF 解码后,每条记录会额外显示解析出的字段:

  1. pipe 号:数据来源管道 0~5;
  2. 负载长度:十六进制表示;若为固定长度包则显示33(即 0x33,表示负载长度非动态);
  3. PID + NO_ACK:2 位 PID(数据包标识)左移 1 位,加上 1 位 NO_ACK 标志。

开启 CRC 解码后,应用会在整包数据中滑动计算 CRC-8(多项式 0x07)或 CRC-16(多项式 0x1021)并定位匹配位置:匹配到的 CRC 字节会在屏幕上加下划线标出,同时该记录行号的冒号:会变成=,表示 CRC 校验已通过(见 nrf24scan.c 的绘制逻辑)。

7. 用 Python 离线验证 ESB 包解码

仓库在 nrf24_packet_decoder.py 中提供了一个独立的 Python 示例,用于演示 nRF24L01+ Enhanced ShockBurst 数据包的解码流程,可以直接在 PC 上运行:

python3 nrf24_packet_decoder.py

脚本内置了若干组示例比特流(packets元组),输出每个包的十六进制、前导码、地址、负载长度、PID、NO_ACK、CRC 及校验结果(CRC valid / mismatch)。其核心逻辑与固件中的校验算法一致:

  • 地址长度通过统计 8 位字段数量推断,出现 6 位字段(PCF)即判定为 ESB 包,否则为非 ESB 包(parse_packet);
  • CRC-8 使用多项式0x107(等价于固件中的0x07),CRC-16 使用0x11021(等价于固件中的0x1021),初始值分别为0xFF/0xFFFF
  • ESB 包的 PCF 为 9 位:6 位负载长度 + 2 位 PID + 1 位 NO_ACK。

这正好印证了固件 calc_crc 的 CRC 实现与check_packet的逐位校验逻辑:由于嗅探模式下包边界未知,固件对所有可能的地址长度(3~5 字节)与负载长度组合逐一尝试,直到 CRC 命中。

8. 源码级原理补充:数据流向与关键调用链

整个应用的数据流可以概括为:

  1. nrf24scan_app(入口)初始化 GUI、存储、通知服务,分配日志与地址统计缓冲区,调用nrf24_init()完成 SPI 初始化(nrf24scan.c);
  2. 用户按 OK 开始扫描 →start_scanning()prepare_nrf24(false)按当前模式写入各寄存器(速率、CRC、地址、EN_RXADDR、DYNPD 等)→nrf24_set_rx_mode()进入接收;
  3. 主循环每 100ms 轮询事件队列,同时调用nrf24_read_newpacket()读取数据包(nrf24scan.c),收到包后 LED 白色闪烁提示;
  4. 嗅探模式下,check_packet对 RAW 数据做 CRC 滑动校验,有效则存入log_arr缓冲,同时更新found地址统计表;
  5. 用户长按 OK →nrf24_send_packet():根据记录元数据重建发送参数(地址、负载长度、ESB/AA 开关),调用nrf24_txpacket发出(nrf24scan.c);
  6. 退出(长按 Back)时,若启用了日志保存,会把残留缓冲区写盘,并调用nrf24_deinit()释放 SPI 总线。

nrf24 驱动库 nrf24.c 与 nrf24.h 提供底层寄存器读写(nrf24_write_reg/nrf24_read_reg)、收发(nrf24_rxpacket/nrf24_txpacket)以及嗅探辅助函数(nrf24_init_promisc_mode/nrf24_sniff_address/nrf24_find_channel),这些函数同样被仓库中其他 nRF24 相关应用复用。从源码结构看,nrf24_set_mac负责按 "MSB first" 顺序写入 2~5 字节地址,而 P2~P5 的短地址写法则由扫描器应用自己组合(P1 高位 + LSB)完成。

9. 常见问题与使用建议

  • 模块无响应/读写错误:检查 7 根连线是否与上文表格一一对应,特别是 CSN、CE 是否接反;确认模块为 3.3V 供电,不要接 5V;在 VCC/GND 间加 10µF 电容稳定供电。
  • 垃圾包过多:这是嗅探模式逐位滑动的固有代价。可以通过提高 "Min Payl"(最小负载长度)过滤过短的无意义数据,或改用定向 scan 模式按已知地址监听。
  • 抓不到某些设备:确认目标设备的速率(250K/1M/2M)与 CRC 设置是否与捕获配置一致;RAW 模式下负载超过 23 字节的包无法捕获。
  • ESB 包的 ACK 冲突:nRF24L01 在 ESB 下会自动回 ACK,可能造成碰撞。对只读场景可关闭 ESB(AA)以获得更干净的 RAW 数据。
  • 配置文件不生效:注意文件必须放在ext/nrf24scan/目录,且每行格式严格为参数: 值;P0 的字节数决定整个地址族的地址长度,P0 缺失或过短(不足 2 字节)会导致加载失败(错误码显示为 "LOAD ERROR#x")。

10. 总结

Nrf24_Scanner 把 nRF24L01+ 的"近似混杂模式"、CRC 滑动校验、多管道定向扫描与数据回放整合进了一个 128×64 屏幕即可完整操作的应用中。其价值在于:不需要知道目标协议的任何细节,只要它跑在 2.4GHz 的 nRF24 系列芯片上,就能通过嗅探-发现地址-定向扫描-回放验证的完整链路,快速还原并复现一条无线数据流。配合仓库自带的设置示例、Python 解码脚本与完整 C 源码,无论是把玩无线鼠标键盘协议,还是研究私有 2.4GHz 遥控协议,它都是一套开箱即用且可以深度二次开发的参考实现。

【免费下载链接】FlipperPlayground (and dump) of stuff I make or modify for the Flipper Zero项目地址: https://gitcode.com/GitHub_Trending/fl/Flipper

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询