Sniffle 是一款使用 TI CC1352/CC26x2 硬件进行蓝牙 5 和 4.x(LE)嗅探的工具。
Sniffle 拥有许多实用功能,包括:
如果您不想费心为固件搭建构建环境,可以直接使用 UniFlash/DSLite 刷写预构建的固件二进制文件。 预构建的固件二进制文件附在本项目的 GitHub releases 页面的发行版中。使用预构建固件时,请确保使用与发行版标签对应的 Python 代码,而不是 master 分支,以避免与落后于 master 分支的固件出现兼容性问题。
各类 Linux 发行版包管理器提供的 arm-none-eabi-gcc 通常缺少某些头文件,或者需要对链接器配置进行一些更改。为减少麻烦,建议使用上面链接的 ARM GCC。您只需下载并解压预构建的可执行文件即可。
TI SDK 以可执行二进制文件的形式提供,一旦您接受许可协议,它就会提取大量源代码。在 Linux 和 Mac 上,默认安装目录在 ~/ti/ 内。这工作正常,我的 makefile 也期望该路径,因此我建议在此处直接使用默认路径。TI SysConfig 工具也是如此。
解压 SDK 后,您需要编辑一个 makefile 以匹配您的构建环境。在 ~/ti/simplelink_cc13xx_cc26xx_sdk_8_30_01_01(或 SDK 安装到的任何位置)中有一个名为 imports.mak 的 makefile。要构建 Sniffle,需要在此处设置的唯一路径是 GCC、XDC、cmake 和 SysConfig。我们不需要 CCS 编译器。请参见下面的差异示例,并根据您的安装位置进行调整。```
diff --git a/imports.mak b/imports.mak
index b2cf5bf59..389d1a7c3 100644
--- a/imports.mak
+++ b/imports.mak
@@ -18,14 +18,14 @@
-XDC_INSTALL_DIR ?= /home/username/ti/xdctools_3_62_01_15_core -SYSCONFIG_TOOL ?= /home/username/ti/ccs1270/ccs/utils/sysconfig_1.21.1/sysconfig_cli.sh +XDC_INSTALL_DIR ?= $(HOME)/ti/xdctools_3_62_01_15_core +SYSCONFIG_TOOL ?= $(HOME)/ti/sysconfig_1.21.1/sysconfig_cli.sh
-CMAKE ?= /home/username/cmake-3.21.3/bin/cmake +CMAKE ?= cmake PYTHON ?= python3
TICLANG_ARMCOMPILER ?= /home/username/ti/ccs1270/ccs/tools/compiler/ti-cgt-armllvm_3.2.2.LTS-0 -GCC_ARMCOMPILER ?= /home/username/arm-none-eabi-gcc/12.3.Rel1-0 +GCC_ARMCOMPILER ?= $(HOME)/arm_tools/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi IAR_ARMCOMPILER ?= /home/username/iar9.50.2
As of SDK version 8.30.01.01, to compile with recent versions of GCC (and binutils),
a small modification to the SDK is needed to avoid linking errors
"Unknown destination type (ARM/Thumb)" and "dangerous relocation: unsupported relocation".```
diff --git a/kernel/tirtos7/packages/ti/sysbios/family/arm/m3/Hwi_asm_gcc.s b/kernel/tirtos7/packages/ti/sysbios/family/arm/m3/Hwi_asm_gcc.s
index 187cfd744..4cbf0d384 100644
--- a/kernel/tirtos7/packages/ti/sysbios/family/arm/m3/Hwi_asm_gcc.s
+++ b/kernel/tirtos7/packages/ti/sysbios/family/arm/m3/Hwi_asm_gcc.s
@@ -236,6 +236,7 @@ lab$1:
@ user code has set the PRIMASK and not cleared it, or when single
@ stepping with interrupts disabled.
+.type ti_sysbios_family_arm_m3_Hwi_interruptsAreDisabledButShouldNotBe, %function
ti_sysbios_family_arm_m3_Hwi_interruptsAreDisabledButShouldNotBe:
b ti_sysbios_family_arm_m3_Hwi_interruptsAreDisabledButShouldNotBe
diff --git a/kernel/tirtos7/packages/ti/sysbios/family/arm/v8m/Hwi_asm_gcc.s b/kernel/tirtos7/packages/ti/sysbios/family/arm/v8m/Hwi_asm_gcc.s
index 717f49c9a..1c83ed725 100644
--- a/kernel/tirtos7/packages/ti/sysbios/family/arm/v8m/Hwi_asm_gcc.s
+++ b/kernel/tirtos7/packages/ti/sysbios/family/arm/v8m/Hwi_asm_gcc.s
@@ -226,6 +226,7 @@ lab$1:
@ user code has set the PRIMASK and not cleared it, or when single
@ stepping with interrupts disabled.
+.type ti_sysbios_family_arm_v8m_Hwi_interruptsAreDisabledButShouldNotBe, %function
ti_sysbios_family_arm_v8m_Hwi_interruptsAreDisabledButShouldNotBe:
b ti_sysbios_family_arm_v8m_Hwi_interruptsAreDisabledButShouldNotBe
进行此修改后,您需要重新编译SDK。``` cd ~/ti/simplelink_cc13xx_cc26xx_sdk_8_30_01_01 make build-gcc -j5
### 获取 DSLite
DSLite 是 TI 基于 XDS110 调试器的命令行编程和调试服务器工具。CC26xx 和 CC13xx Launchpad 板均包含 XDS110 调试器。遗憾的是,TI 并未提供独立的命令行 DSLite 下载。获取 DSLite 的最简单方法是安装 TI 的 [UniFlash](http://www.ti.com/tool/download/UNIFLASH)。它可用于 Linux、Mac 和 Windows 平台。DSLite 可执行文件位于 UniFlash 安装目录下的 `deskdb/content/TICloudAgent/linux/ccs_base/DebugServer/bin/DSLite`。在 Linux 上,UniFlash 的默认安装目录在 `~/ti/` 内。
你应该将 DSLite 可执行文件目录添加到你的 `$PATH` 中。
## 固件构建
在安装并配置好 GCC、DSLite 和 SDK 后,构建 Sniffle 应该很简单。只需进入 `fw` 目录并运行 `make`。如果你没有将 SDK 安装到默认目录,可能需要编辑 makefile 中的 `SIMPLELINK_SDK_INSTALL_DIR`。
如果为 CC26x2R 以外的 Launchpad 变体构建或安装固件,必须指定 `PLATFORM=xxx`,可以将其作为 make 的参数,或在调用 make 之前定义环境变量。支持的 `PLATFORM` 值可在固件 makefile 中找到。在为目标平台构建之前,务必执行 `make clean`。
## 固件安装(TI Launchpad 板)
要使用 DSLite 将 Sniffle 安装到(已插入的)CC26x2R Launchpad 上,请在 `fw` 目录内运行 `make load`。对于其他 Launchpad 型号,必须如上所述在 make 命令中指定 `PLATFORM` 参数。你也可以使用 UniFlash GUI 烧写编译好的 `sniffle.hex` 文件。
## 固件安装(SONOFF USB 加密狗)
要将 Sniffle 安装到 SONOFF CC2652P 加密狗(配备 CP2102N USB/UART 桥接器)上,可以使用 [JelmerT/cc2538-bsl](https://github.com/JelmerT/cc2538-bsl) 工具,通过内置 ROM 引导加载程序烧写固件,命令如下:```
python3 cc2538-bsl.py -p /dev/ttyUSB0 --bootloader-sonoff-usb -ewv sniffle_cc1352p1_cc2652p1.hex
截至2025年1月10日,cc2538-bsl 中存在一个错误,导致其在刷新后无法重置 Sonoff 加密狗中的 CC2562P 芯片。该修复位于拉取请求 173 中,但尚未合并。在此期间等待拉取请求合并时,你可以使用我的分支:https://github.com/sultanqasim/cc2538-bsl。
2022年,由于新冠疫情导致的芯片短缺,部分 Sonoff CC2652P 加密狗使用了 CP2102(非 N 型)USB/UART 桥接芯片,其波特率上限为 921600。如果你拥有这样的加密狗,则需要刷新使用较慢波特率 921600 的不同固件映像。该特殊慢波特率版本的名称为 sniffle_cc1352p1_cc2652p1_1M.hex(构建变体 CC2652P1F_1M)。你还需要使用选项 -b 921600 调用 Sniffle 实用程序,以覆盖默认的 2000000 波特率。
警告: 请勿使用引导加载程序刷新错误的构建变体,否则可能导致设备变砖并无法再次进入引导加载程序。对于 Sonoff CC2652P 设备,请使用 sniffle_cc1352p1_cc2652p1.hex 文件(CC2652P1F 构建变体)或 sniffle_cc1352p1_cc2652p1_1M.hex 文件(CC2652P1F_1M 构建变体)以使用 921600 波特率。如果刷错了变体并锁定了引导加载程序,可能可以使用 JTAG/SWD 恢复设备。
Electronic Cats 提供了一个 Catnip Uploader 工具用于加载固件。详细信息请参考仓库。下载该工具并执行以下命令:```bash
[ec@sniffle]$ git clone https://github.com/ElectronicCats/CatSniffer-Tools.git [ec@sniffle]$ cd CatSniffer-Tools/catnip_uploader [ec@sniffle]$ pip install -r requirements.txt
[ec@sniffle]$ python3 catnip_uploader.py releases [INFO] Fetching assets from https://api.github.com/repos/ElectronicCats/CatSniffer-Firmware/releases/latest [INFO] Release: board-v3.x-v1.1.0 [INFO] Fetching assets from https://api.github.com/repos/nccgroup/Sniffle/releases/latest [INFO] Release: v1.10.0 [INFO] Found local release: releases_board-v3.x-v1.1.0 [SUCCESS] Local release is up to date: board-v3.x-v1.1.0 [SUCCESS] Available releases: 0: sniffer_fw_CC1352P_7_v1.10.hex 1: airtag_scanner_CC1352P_7_v1.0.hex 2: nccgroup_v1.10.0_sniffle_cc1352p7_1M.hex 3: airtag_spoofer_CC1352P_7_v1.0.hex 4: sniffle_CC1352P_7_v1.7.hex
[ec@sniffle]$ python3 catnip_uploader.py load 2 COMPORT
您需要将*COMPORT*更改为适合您板子的路径。
使用命令 `python3 catnip_uploader.py load 2 COMPORT`,您将加载
`2: nccgroup_v1.10.0_sniffle_cc1352p7_1M.hex` 固件。
**要加载固件,Catsniffer V3 需要 SerialPassthroughwithboot**。
**警告:**请勿通过引导加载程序刷写错误的构建变体,否则您可能会损坏设备并锁定无法再次进入引导加载程序。如果您使用 `catnip_uploader.py` 脚本来获取并安装固件,它只会提供兼容的固件。但是,如果您选择手动编译和安装固件,请确保使用正确的构建变体。对于 CatSniffer v3 设备,请使用 `sniffle_cc1352p7_1M.hex` 文件(`CC1352P74_1M` 构建变体)。CatSniffer v1.x/v2.x 设备使用不同的芯片变体(CC1352P1),需要不同的固件构建(`CC1352P1F3_1M` 变体,`sniffle_cc1352p1_cc2652p1_1M.hex` 镜像)。Sniffle 尚未在 CatSniffer v1.x/v2.x 设备上测试,但只要刷写正确的构建变体,它们很可能可以工作。如果刷写了错误的变体并锁定了引导加载程序,可以通过 JTAG/SWD 恢复设备。
## 嗅探器使用```
[skhan@serpent python_cli]$ ./sniff_receiver.py --help
usage: sniff_receiver.py [-h] [-s SERPORT] [-b BAUDRATE] [-c {37,38,39}] [-p] [-r RSSI]
[-m MAC] [-i IRK] [-S STRING] [-a] [-A] [-e] [-H] [-l] [-q]
[-Q PRELOAD] [-n] [-C] [-d] [-o OUTPUT]
Host-side receiver for Sniffle BLE5 sniffer
options:
-h, --help show this help message and exit
-s SERPORT, --serport SERPORT
Sniffer serial port name
-b BAUDRATE, --baudrate BAUDRATE
Sniffer serial port baud rate
-c {37,38,39}, --advchan {37,38,39}
Advertising channel to listen on
-p, --pause Pause sniffer after disconnect
-r RSSI, --rssi RSSI Filter packets by minimum RSSI
-m MAC, --mac MAC Filter packets by advertiser MAC
-i IRK, --irk IRK Filter packets by advertiser IRK
-S STRING, --string STRING
Filter for advertisements containing the specified string
-a, --advonly Passive scanning, don't follow connections
-A, --scan Active scanning, don't follow connections
-e, --extadv Capture BT5 extended (auxiliary) advertising
-H, --hop Hop primary advertising channels in extended mode
-l, --longrange Use long range (coded) PHY for primary advertising
-q, --quiet Don't display empty packets
-Q PRELOAD, --preload PRELOAD
Preload expected encrypted connection parameter changes
-n, --nophychange Ignore encrypted PHY mode changes
-C, --crcerr Capture packets with CRC errors
-d, --decode Decode advertising data
-o OUTPUT, --output OUTPUT
PCAP output file name
Launchpad板上的XDS110调试器会创建两个串行端口。在Linux上,它们通常被命名为ttyACM0和ttyACM1。创建的两个串行端口中的第一个用于与Sniffle通信。默认情况下,Python CLI使用匹配TI XDS110 USB VID:PID组合的第一个CDC-ACM设备,或它看到的第一个Sonoff加密狗进行通信。如果你使用不同的USB串行适配器或有其他USB CDC-ACM设备连接,可能需要用-s命令行选项覆盖此设置。
对于-r(RSSI过滤器)选项,如果嗅探器非常接近或几乎接触到发送设备,-40的值通常效果很好。RSSI过滤器在繁忙的RF环境中忽略无关广告非常有用。RSSI过滤器仅在捕获广告时激活,因为你总是希望捕获正在跟踪的连接的数据信道流量。当MAC过滤激活时,你可能不想使用RSSI过滤器,因为如果RSSI太低,可能会丢失感兴趣的MAC地址的广告。
要跟随广告并进行可靠的连接嗅探,你需要使用-m选项设置MAC过滤器。你应该指定外围设备的MAC地址,而不是中央设备。要确定要嗅探哪个MAC地址,可以在将嗅探器靠近目标的情况下运行带RSSI过滤的嗅探器。这将显示来自目标设备的广告,包括其MAC地址。需要注意的是,许多BLE设备使用随机化的MAC地址进行广告,而不是其标签上写的"真实"固定MAC。
大多数新BLE设备使用可解析私有地址(RPA)而不是固定的静态或公共地址。虽然你可以为特定的RPA设置MAC过滤器,但设备会定期更改其RPA。如果已知身份解析密钥(IRK),则可以解析RPA(将其与特定设备关联)。当提供IRK时,Sniffle支持自动RPA解析。这避免了每次RPA更改时都需要更新MAC过滤器。你可以使用-i选项为Sniffle指定IRK;IRK应以十六进制格式提供,最高有效字节(MSB)在前。指定IRK允许Sniffle像使用MAC过滤器一样与广告商进行信道跳频。基于IRK的MAC过滤功能(-i)与静态MAC过滤功能(-m)互斥。
还有一个便捷功能,可以自动识别其广告或扫描响应包含指定字符串(字节序列)的广告商的MAC地址。这对于IRK未知但广告包含足够唯一静态字符串用于识别的RPA设备很有用。此功能使用-S选项,字符串使用标准转义序列指定。例如,要查找广告包含十六进制字节序列DE AD BE EF的广告商,指定-S "\xDE\xAD\xBE\xEF"。要查找包含字符串"hello"的广告商,只需指定-S "hello"。当使用字符串搜索功能时,最初将接受所有MAC地址,直到找到包含搜索字符串的广告。之后,将使用相应广告商的MAC地址设置MAC过滤器,并且任何RSSI过滤器将自动禁用。
要启用跟踪蓝牙5扩展广告中的辅助指针,启用-e选项。为了提高扩展广告捕获的性能和可靠性,此选项禁用了在主广告信道上的跳频,即使设置了MAC过滤器也是如此。如果不确定连接是通过传统广告还是扩展广告建立的,可以启用-H标志与-e结合,以使用传统广告执行主信道跳频,并定时监听扩展广告辅助数据包。当结合使用-e和-H时,与单独在主(传统)或辅助(扩展)广告信道上跳频相比,连接检测的可靠性可能会降低。
要嗅探主广告信道上的长距离PHY,指定-l选项。请注意,在长距离模式下不支持主广告信道之间的跳频,因为所有长距离广告都使用BT5扩展机制。在扩展机制下,所有三个主信道上的辅助指针指向同一个辅助数据包,因此在主信道之间跳频是不必要的。
要在跟随连接时不打印空数据包到屏幕上,使用-q标志。这使得更容易实时观察有意义的通信,但可能会掩盖连接跟踪不稳定或丢失的情况。
对于加密连接,即使加密密钥未知,Sniffle也支持检测连接参数更新,并尝试测量新参数。但是,如果你知道加密连接参数更新中预期的新的连接间隔和Instant delta,可以使用--preload/-Q选项指定它们以提高性能/可靠性。预期的Interval:DeltaInstant对应以冒号分隔的整数形式提供。Interval是一个整数,表示1.25 ms的倍数(如LL_CONNECTION_UPDATE_IND中所定义)。DeltaInstant是从传输连接更新数据包到应用新参数之间的连接事件数。根据蓝牙规范对中央设备的要求,DeltaInstant必须大于或等于6。如果预期有多个加密参数更新,可以提供多个参数对,用逗号分隔(例如6:7,39:8)。如果设备发送不改变PHY的加密PHY更新PDU,或发出没有PHY变化的加密LE功率控制PDU,可以使用--nophychange/-n选项。
要停止嗅探器,按Ctrl-C。
如果由于某种原因嗅探器固件死锁,即使禁用了过滤器也拒绝捕获任何流量,您应该重置嗅探器MCU。在Launchpad板上,重置按钮位于微型USB端口旁边。
usage: scanner.py [-h] [-s SERPORT] [-b BAUDRATE] [-c {37,38,39}] [-r RSSI] [-l] [-d] [-o OUTPUT]
Scanner utility for Sniffle BLE5 sniffer
options: -h, --help show this help message and exit -s SERPORT, --serport SERPORT Sniffer serial port name -b BAUDRATE, --baudrate BAUDRATE Sniffer serial port baud rate -c {37,38,39}, --advchan {37,38,39} Advertising channel to listen on -r RSSI, --rssi RSSI Filter packets by minimum RSSI -l, --longrange Use long range (coded) PHY for primary advertising -d, --decode Decode advertising data -o OUTPUT, --output OUTPUT PCAP output file name
扫描仪的命令行参数与嗅探器相同。扫描工具的目的是收集附近正在广播的设备列表,并对观察到的设备主动发出扫描请求,而不会像嗅探工具那样出现快速滚动的数据洪流。硬件/固件将进入主动扫描模式,报告接收到的广播,对可扫描的广播发出扫描请求,并报告接收到的扫描响应。扫描工具将仅记录和报告观察到的MAC地址一次,而不会使显示混乱。当您完成捕获广播后,按Ctrl-C停止扫描并报告结果。扫描仪将显示每个目标的最新广播和扫描响应。扫描结果将按RSSI降序排列。
## 使用示例
在信道38上嗅探所有广播,忽略RSSI < -50,即使看到CONNECT_REQ也停留在广播信道上。```
./sniff_receiver.py -c 38 -r -50 -a
嗅探来自MAC 12:34:56:78:9A:BC的广播包,即使看到CONNECT_REQs,也停留在广播频道上,将广播包保存到data1.pcap。```
./sniff_receiver.py -m 12:34:56:78:9A:BC -a -o data1.pcap
嗅探广告和连接,寻找第一个看到且满足条件的MAC地址,该MAC地址
RSSI >= -40。RSSI过滤器将自动禁用,一旦一个MAC地址
已经被锁定。将捕获的数据保存到`data2.pcap`。```
./sniff_receiver.py -m top -r -40 -o data2.pcap
嗅探来自外设的广播和连接,使用大端序IRK 4E0BEA5355866BE38EF0AC2E3F0EBC22。预加载两次预期的加密连接参数更新:第一次的间隔为6,发生在嗅探器观察到加密的LL_CONNECTION_UPDATE_IND之后的第6个连接事件时刻。第二次预期的加密连接更新的间隔为39,DeltaInstant也为6。``` ./sniff_receiver.py -i 4E0BEA5355866BE38EF0AC2E3F0EBC22 -Q 6:6,39:6
嗅探附近(RSSI >= -55)设备的蓝牙5扩展广播和连接。```
./sniff_receiver.py -r -55 -e
嗅探来自具有指定MAC地址的设备的传统和扩展广播及连接。将捕获的数据保存到 data3.pcap。```
./sniff_receiver.py -eH -m 12:34:56:78:9A:BC -o data3.pcap
使用长距离主PHY在通道38上嗅探扩展广播和连接。```
./sniff_receiver.py -le -c 38
在信道39上主动扫描RSSI大于-50的广播。``` ./scanner.py -c 39 -r -50
## 获取 IRK
如果你有一部已 root 的 Android 手机,你可以在 Bluedroid 配置文件中找到 IRK(以及 LTK)。在 Android 8.1 上,该文件位于 `/data/misc/bluedroid/bt_config.conf`。`LE_LOCAL_KEY_IRK` 指定了 Android 设备自身的 IRK,而文件中每个已配对设备的 `LE_KEY_PID` 的前 16 字节则指示了该配对设备的 IRK。请注意,该文件中存储的密钥是小端序(little endian),因此**该文件中密钥的字节顺序需要反转。**例如,小端序 IRK `22BC0E3F2EACF08EE36B865553EA0B4E` 在通过 `-i` 选项传递给 Sniffle 时需要更改为 `4E0BEA5355866BE38EF0AC2E3F0EBC22`(大端序,big endian)。
你也可以通过 Android 或 iOS 上捕获的 HCI Snoop 日志来找到 IRK 和 LTK,而无需 root 设备:
* Android: <https://novelbits.s3.us-east-2.amazonaws.com/Developer+Guides/Android+Bluetooth+Debugging+Guide.pdf>
* iOS: <https://novelbits.s3.us-east-2.amazonaws.com/Developer+Guides/iOS+Bluetooth+Debugging+Guide.pdf>
## Wireshark 插件
Sniffle 包含一个 Wireshark 插件,可以通过在 Wireshark GUI 中选择“Sniffle”捕获接口来自动启动 Sniffle。
要安装 Sniffle 插件,首先在“关于 Wireshark”对话框(*帮助* > *关于 Wireshark* > *文件夹* > *个人 Extcap 路径*)中找到你的个人 Extcap 文件夹的位置。在运行近期版本 Wireshark(4.2.0 及以上)的 POSIX(Linux 和 Mac OS)系统上,该文件夹位于 `~/.local/lib/wireshark/extcap`。在 Windows 下,可以在 `%USERPROFILE%\AppData\Roaming\Wireshark\extcap` 找到。
在 POSIX 系统上,你可以直接将 Sniffle extcap 插件符号链接到 Wireshark 的个人 extcap 目录:```
mkdir -p ~/.local/lib/wireshark/extcap
ln -s $(pwd)/python_cli/sniffle_extcap.py ~/.local/lib/wireshark/extcap
在 macOS 上,Wireshark 可能会尝试使用 Xcode 的 Python,而不是您的 shell 配置文件所指定的 PATH 中的 Python。因此,如果 Xcode Python 没有安装 PySerial,Sniffle 插件可能不会出现在 extcap 接口中。要解决此问题,您可以编辑 sniffle_extcap.py 的 shebang 行,直接指向安装了 PySerial 的 Python,例如 Homebrew 的 Python(位于 /opt/homebrew/bin/python3),而不是 /usr/bin/env python3。
在 Windows 上,您可以将 python_cli 目录中的以下文件和目录复制到您的个人 Extcap 文件夹中:```
sniffle/
sniffle_extcap.py
sniffle_extcap.bat
在Windows上,如果安装目录未包含在PATH中,则可能需要编辑 `sniffle_extcap.bat` 来指定Python解释器的位置,例如:```
@echo off
C:\my_python_install\python.exe "%~dp0sniffle_extcap.py" %*
安装插件后,请重启 Wireshark 或选择 捕获 > 刷新接口 以启用 Sniffle 接口。
虽然最初的 2019 版 Sniffle 固件只是一个被动监听器,但后续固件版本增加了以各种方式主动发送数据包的功能。当前 Sniffle 固件支持同时作为 GAP 中心和外围设备,包括主动扫描、传统和扩展广播、发起连接,以及以中心或外围角色被连接。scanner.py 脚本执行主动扫描。initiator.py 脚本发起与外围设备的连接,然后作为已连接的中心设备运行。advertiser.py 脚本执行传统广播并接受来自其他设备的连接请求,从而过渡到已连接的外围角色。
Sniffle 的发送功能与传统基于 HCI 的蓝牙控制器略有不同,因为它允许你非常底层地控制链路层上发送的确切 PDU。这种底层控制允许主机端代码实现额外功能,例如链路层模糊测试或链路层中继攻击。
我还没有花时间正式记录 Sniffle 固件的 API,尽管在查看其主机端实现 sniffle_hw.py 时,其功能是相当自解释的。主动扫描(发送扫描请求)由 cmd_scan 激活。连接发起由 cmd_connect 触发,但使用 initiate_conn 包装器更为简单。广播(可选择可连接)由 cmd_advertise 激活用于传统广播,或 cmd_advertise_ext 用于扩展广播。
自 2024 年中 TI 问题 EXT_EP-11735 修复后,XDS110 调试器(包含在 TI Launchpad 板上)能够合理处理高速率(如 Sniffle 使用的 2M 波特率),且没有过度延迟。然而,最新的 XDS110 固件在此类波特率下仍使用缓冲的 DMA 驱动 UART 操作,因此仍然可能引入高达 30 ms 的延迟。这种延迟对于嗅探器使用无关紧要,但对于更主动的操作(如主机端代码充当 GATT 客户端或服务器,或执行中继攻击)可能有害。下面描述的针对中断式操作修改 XDS110 固件版本 3.0.0.28 的方法仍可大大减少此类时间敏感操作的延迟。应该可以对最新的 XDS110 固件进行类似的修改,但我还没有花时间对其进行逆向工程以找到需要更改的正确位。
在 2024 年中及更早,TI XDS110 调试器(包含在 Launchpad 板上)的固件在其 USB 到 UART 桥接器中存在不良行为,在高波特率下,尤其是 Sniffle 固件频繁进行小写入时,可能会出现严重延迟。此问题存在多年,并且在 2024 年 4 月随 UniFlash 8.6.0 捆绑的 XDS110 固件 3.0.0.28 中仍然存在。根本原因是,在基于 DMA 的操作中,XDS110 固件将 UART 数据累积在一个大小与波特率成比例的缓冲区中,并等待该缓冲区填满后再传输数据。存在一种逻辑,如果过去 15 毫秒内没有新数据到达,则刷新此缓冲区,但当 Sniffle 每几毫秒从连接事件中频繁添加小数据包时,此刷新逻辑从未被触发。由于这种次优行为,嗅探到的数据可能会在主机上以延迟的突发方式出现。
XDS110 固件还具有另一种 UART 操作模式,其中每次 UART 接收都会触发中断,导致数据立即传递到主机。这种基于中断的操作模式具有更低的延迟。然而,固件仅对低于 230400 的波特率使用该模式。作为对 DMA 模式下频繁小数据块高延迟的解决方法,你可以修改固件以在高波特率(如 Sniffle 使用的 2M 波特率)下也使用基于中断的 USB-UART 桥接。在固件 3.0.0.28(包含于 Uniflash 8.6.0)中,你可以将偏移量 0x0A14 处的字节从 61 3F 十六进制编辑为 00 1F。这将把切换至基于 DMA 的 UART 操作的波特率从 230400 更改为 0x200000(2097152)。
请注意,上述偏移量和字节修改仅适用于固件 3.0.0.28,对于不同固件版本会有所不同。将无效固件刷写到调试器上可能会损坏它,我们不对可能发生的任何损坏承担责任。
以下命令可用于在 Linux 上修改 XDS110 固件,以实现高波特率下的低延迟 UART:``` cd ~/ti/uniflash_8.6.0/deskdb/content/TICloudAgent/linux/ccs_base/common/uscif/xds110/ cp firmware_3.0.0.28.bin firmware_3.0.0.28_fastuart.bin printf '\x00\x1f' | dd of=firmware_3.0.0.28_fastuart.bin bs=1 seek=$((0x0A14)) conv=notrunc sha256sum firmware_3.0.0.28_fastuart.bin
在刷写之前,验证修改后固件的SHA256哈希值是否为`c226f2e9cb2b9f0bc111ca11f2903d58d4065293468623428c0e8eeb22086dcf`。验证完成后,运行以下命令来刷写修改后的XDS110调试器固件:```
./xdsdfu -m
./xdsdfu -f firmware_3.0.0.28_fastuart.bin -r
Sniffle 可用于执行蓝牙 LE 流量的链路层中继。进行中继时,一个 Sniffle 设备充当 BLE 中心(使用 relay_master.py),另一个 Sniffle 设备充当 BLE 外设(使用 relay_slave.py)。Master 和 slave 分别是 BLE 中心和外设的历史术语。中继主设备从真实外设捕获广播和扫描响应数据,然后将其传递给中继从设备。中继从设备模拟真实外设发送广播和扫描响应,并接受连接。接受连接后,中继从设备通知中继主设备,后者随后发起与真实外设的连接。从此时起,所有链路层数据包都在中继主设备和从设备之间转发。
中继主设备脚本提供了请求中继两侧更快连接间隔以降低延迟的功能。如果使用 XDS110 作为 USB/UART 桥接器,请注意,除非按上述方法修改 XDS110 固件,否则它会引入额外的中继延迟。
请注意,中继主设备脚本会创建一个绑定到所有接口(0.0.0.0)的网络监听器,并且中继设备之间通信所用的网络协议不提供安全性。请仅在受信任的网络环境中使用这些脚本。
中继主设备(中心)和从设备(外设)脚本的使用方法如下所示。目前,中继脚本不支持扩展广播。``` usage: relay_master.py [-h] [-s SERPORT] [-c {37,38,39}] [-m MAC] [-i IRK] [-S STRING] [-P] [-q] [-Q PRELOAD] [-f] [-p] [-F] [-o OUTPUT]
Relay master script for Sniffle BLE5 sniffer
options: -h, --help show this help message and exit -s, --serport SERPORT Sniffer serial port name -c, --advchan {37,38,39} Advertising channel to listen on -m, --mac MAC Specify target MAC address -i, --irk IRK Specify target IRK -S, --string STRING Specify target by advertisement search string -P, --public Supplied MAC address is public -q, --quiet Don't show empty packets -Q, --preload PRELOAD Preload expected encrypted connection parameter changes -f, --fastslave Relay slave should request a fast connection interval -p, --pause Wait for key press on master before relaying -F, --fastmaster Relay master should specify a fast connection interval -o, --output OUTPUT PCAP output file name
(空)```
usage: relay_slave.py [-h] [-s SERPORT] [-M MASTERADDR] [-q]
Relay slave script for Sniffle BLE5 sniffer
options:
-h, --help show this help message and exit
-s, --serport SERPORT
Sniffer serial port name
-M, --masteraddr MASTERADDR
IP address of relay master
-q, --quiet Don't show empty packets