{"id":13540274,"url":"https://github.com/nccgroup/sniffle","last_synced_at":"2025-04-12T19:47:50.025Z","repository":{"id":38417605,"uuid":"202839525","full_name":"nccgroup/Sniffle","owner":"nccgroup","description":"A sniffer for Bluetooth 5 and 4.x LE","archived":false,"fork":false,"pushed_at":"2025-01-11T15:55:14.000Z","size":661,"stargazers_count":954,"open_issues_count":23,"forks_count":136,"subscribers_count":47,"default_branch":"master","last_synced_at":"2025-04-12T19:47:36.477Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.nccgroup.trust/us/our-research/sniffle-a-sniffer-for-bluetooth-5/?research=Public+tools","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nccgroup.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-17T05:26:18.000Z","updated_at":"2025-04-11T11:50:46.000Z","dependencies_parsed_at":"2023-01-21T02:01:55.706Z","dependency_job_id":"b4633eac-44cc-4e29-aafb-8a4d2ea1de64","html_url":"https://github.com/nccgroup/Sniffle","commit_stats":{"total_commits":279,"total_committers":6,"mean_commits":46.5,"dds":"0.30107526881720426","last_synced_commit":"2b31ab7ed9a3288c4fd0e9d4084dede45ab165b5"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nccgroup%2FSniffle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nccgroup%2FSniffle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nccgroup%2FSniffle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nccgroup%2FSniffle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nccgroup","download_url":"https://codeload.github.com/nccgroup/Sniffle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248625497,"owners_count":21135513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T09:01:44.621Z","updated_at":"2025-04-12T19:47:50.003Z","avatar_url":"https://github.com/nccgroup.png","language":"Python","funding_links":[],"categories":["\u003ca id=\"79499aeece9a2a9f64af6f61ee18cbea\"\u003e\u003c/a\u003e浏览嗅探\u0026\u0026流量拦截\u0026\u0026流量分析\u0026\u0026中间人","\u003ca id=\"7bf0f5839fb2827fdc1b93ae6ac7f53d\"\u003e\u003c/a\u003e工具","\u003ca name=\"bluetooth_security_tools\"\u003e\u003c/a\u003eBluetooth Security Tools"],"sub_categories":["\u003ca id=\"99398a5a8aaf99228829dadff48fb6a7\"\u003e\u003c/a\u003e未分类-Network","\u003ca id=\"32739127f0c38d61b14448c66a797098\"\u003e\u003c/a\u003e嗅探\u0026\u0026Sniff","Scanners \u0026 Sniffers"],"readme":"# Sniffle\n\n**Sniffle is a sniffer for Bluetooth 5 and 4.x (LE) using TI CC1352/CC26x2 hardware.**\n\nSniffle has a number of useful features, including:\n\n* Support for BT5/4.2 extended length advertisement and data packets\n* Support for BT5 Channel Selection Algorithms #1 and #2\n* Support for all BT5 PHY modes (regular 1M, 2M, and coded modes)\n* Support for sniffing only advertisements and ignoring connections\n* Support for channel map, connection parameter, and PHY change operations\n* Support for advertisement filtering by MAC address and RSSI\n* Support for BT5 extended advertising (non-periodic)\n* Support for capturing advertisements from a target MAC on all three primary\n  advertising channels using a single sniffer. **This makes connection detection\n  nearly 3x more reliable than most other sniffers that only sniff one advertising\n  channel.**\n* Easy to extend host-side software written in Python\n* PCAP export compatible with the Ubertooth\n* Wireshark compatible plugin\n\n## Prerequisites\n\n* Any of the following hardware devices (functionally equivalent for Sniffle)\n    * TI CC26x2R Launchpad Board: \u003chttps://www.ti.com/tool/LAUNCHXL-CC26X2R1\u003e\n    * TI CC2652RB Launchpad Board: \u003chttps://www.ti.com/tool/LP-CC2652RB\u003e\n    * TI CC1352R Launchpad Board: \u003chttps://www.ti.com/tool/LAUNCHXL-CC1352R1\u003e\n    * TI CC1352P Launchpad Board: \u003chttps://www.ti.com/tool/LAUNCHXL-CC1352P\u003e\n    * TI CC2652R7 Launchpad Board: \u003chttps://www.ti.com/tool/LP-CC2652R7\u003e\n    * TI CC1352P7 Launchpad Board: \u003chttps://www.ti.com/tool/LP-CC1352P7\u003e\n    * TI CC2651P3 Launchpad Board: \u003chttps://www.ti.com/tool/LP-CC2651P3\u003e\n    * TI CC1354P10 Launchpad Board: \u003chttps://www.ti.com/tool/LP-EM-CC1354P10\u003e\n    * SONOFF CC2652P USB Dongle Plus: \u003chttps://itead.cc/product/sonoff-zigbee-3-0-usb-dongle-plus/\u003e\n    * EC Catsniffer V3 CC1352 \u0026 RP2040 \u003chttps://github.com/ElectronicCats/CatSniffer\u003e\n* ARM GNU Toolchain for AArch32 bare-metal target (arm-none-eabi): \u003chttps://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads\u003e\n* TI SimpleLink Low Power F2 SDK 7.41.00.17: \u003chttps://www.ti.com/tool/download/SIMPLELINK-LOWPOWER-F2-SDK/7.41.00.17\u003e\n* TI DSLite Programmer Software: see below\n* Python 3.9+ with PySerial installed\n\n**If you don't want to go through the effort of setting up a build\nenvironment for the firmware, you can just flash prebuilt firmware binaries\nusing UniFlash/DSLite.** Prebuilt firmware binaries are attached to releases\non the GitHub releases tab of this project. When using prebuilt firmware, be\nsure to use the Python code corresponding to the release tag rather than master\nto avoid compatibility issues with firmware that is behind the master branch.\n\n### Installing GCC\n\nThe `arm-none-eabi-gcc` provided through various Linux distributions' package\nmanager often lacks some header files or requires some changes to linker\nconfiguration. For minimal hassle, I suggest using the ARM GCC linked above.\nYou can just download and extract the prebuilt executables.\n\n### Installing the TI SDK\n\nThe TI SDK is provided as an executable binary that extracts a bunch of source\ncode once you accept the license agreement. On Linux and Mac, the default\ninstallation directory is inside`~/ti/`. This works fine and my makefiles\nexpect this path, so I suggest just going with the default here. The same\napplies for the TI SysConfig tool.\n\nOnce the SDK has been extracted, you will need to edit one makefile to match\nyour build environment. Within `~/ti/simplelink_cc13xx_cc26xx_sdk_7_41_00_17`\n(or wherever the SDK was installed) there is a makefile named `imports.mak`.\nThe only paths that need to be set here to build Sniffle are for GCC, XDC,\ncmake and SysConfig. We don't need the CCS compiler. See the diff below as\nan example, and adapt for wherever you installed things.\n\n```\ndiff --git a/imports.mak b/imports.mak\nindex d3900b5b6..e7108c3df 100644\n--- a/imports.mak\n+++ b/imports.mak\n@@ -18,14 +18,14 @@\n # will build using each non-empty *_ARMCOMPILER cgtool.\n #\n \n-XDC_INSTALL_DIR        ?= /home/username/ti/xdctools_3_62_01_15_core\n-SYSCONFIG_TOOL         ?= /home/username/ti/ccs1230/ccs/utils/sysconfig_1.18.1/sysconfig_cli.sh\n+XDC_INSTALL_DIR        ?= $(HOME)/ti/xdctools_3_62_01_15_core\n+SYSCONFIG_TOOL         ?= $(HOME)/ti/sysconfig_1.18.1/sysconfig_cli.sh\n \n-CMAKE                  ?= /home/username/cmake-3.21.3/bin/cmake\n+CMAKE                  ?= cmake\n PYTHON                 ?= python3\n \n TICLANG_ARMCOMPILER    ?= /home/username/ti/ccs1230/ccs/tools/compiler/ti-cgt-armllvm_3.2.0.LTS-0\n-GCC_ARMCOMPILER        ?= /home/username/arm-none-eabi-gcc/9.2019.q4.major-0\n+GCC_ARMCOMPILER        ?= $(HOME)/arm_tools/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi\n IAR_ARMCOMPILER        ?= /home/username/iar9.40.2\n \n # Uncomment this to enable the TFM build\n```\n\n### Obtaining DSLite\n\nDSLite is TI's command line programming and debug server tool for XDS110\ndebuggers. The CC26xx and CC13xx Launchpad boards both include XDS110 debuggers.\nUnfortunately, TI does not provide a standalone command line DSLite download.\nThe easiest way to obtain DSLite is to install [UniFlash](http://www.ti.com/tool/download/UNIFLASH)\nfrom TI. It's available for Linux, Mac, and Windows. The DSLite executable will\nbe located at `deskdb/content/TICloudAgent/linux/ccs_base/DebugServer/bin/DSLite`\nrelative to the UniFlash installation directory. On Linux, the default UniFlash\ninstallation directory is inside `~/ti/`.\n\nYou should place the DSLite executable directory within your `$PATH`.\n\n## Firmware Building\n\nOnce the GCC, DSLite, and the SDK is installed and operational, building\nSniffle should be straight forward. Just navigate to the `fw` directory and\nrun `make`. If you didn't install the SDK to the default directory, you may\nneed to edit `SIMPLELINK_SDK_INSTALL_DIR` in the makefile.\n\nIf building for or installing on a some variant of Launchpad other than CC26x2R,\nyou must specify `PLATFORM=xxx`, either as an argument to make, or by defining\nit as an environment variable prior to invoking make. Supported values for `PLATFORM`\ncan be found in the firmware makefile. Be sure to perform a `make clean` before\nbuilding for a different platform.\n\n## Firmware Installation (TI Launchpad Board)\n\nTo install Sniffle on a (plugged in) CC26x2R Launchpad using DSLite, run\n`make load` within the `fw` directory. For any other Launchpad models, you must\nspecify the `PLATFORM` argument to make as descirbed above. You can also flash\nthe compiled `sniffle.hex` binary using the UniFlash GUI.\n\n## Firmware Installation (SONOFF USB Dongle)\n\nTo install Sniffle on a SONOFF CC2652P dongle (equipped with a CP2102N USB/UART\nbridge), use the [JelmerT/cc2538-bsl](https://github.com/JelmerT/cc2538-bsl) utility\nto flash the firmware using the built-in ROM bootloader with the following command:\n\n```\npython3 cc2538-bsl.py -p /dev/ttyUSB0 --bootloader-sonoff-usb -ewv sniffle_cc1352p1_cc2652p1.hex\n```\n\nAs of January 10, 2025, there is a bug in `cc2538-bsl` that prevents it from\nresetting the CC2562P chip in the Sonoff dongle after flashing. The fix for this\nis in pull request [173](https://github.com/JelmerT/cc2538-bsl/pull/173), which\nhas yet to be merged. In the interim, while waiting for the pull request to be\nmerged, you can use my fork at \u003chttps://github.com/sultanqasim/cc2538-bsl\u003e.\n\nIn 2022, due to COVID-19 pandemic chip shortages, some Sonoff CC2652P dongles were\nbuilt with CP2102 (non-N) USB/UART bridge chips that are capped at 921600 baud. If\nyou have one of these, you will need to flash a different firmware image that uses\na slower baud rate of 921600. This special slower baud rate build is named\n`sniffle_cc1352p1_cc2652p1_1M.hex` (build variant `CC2652P1F_1M`). You will also\nneed to invoke Sniffle utilities with the option `-b 921600` to override the\ndefault baud rate of 2000000.\n\n**WARNING:** Do not flash the wrong build variant using the bootloader, or you\nrisk bricking the device and locking yourself out of the bootloader. For Sonoff\nCC2652P devices, use the `sniffle_cc1352p1_cc2652p1.hex` file (`CC2652P1F` build\nvariant) or the sniffle_cc1352p1_cc2652p1_1M.hex` file (`CC2652P1F_1M` build\nvariant) for a 921600 baud rate. If you flash the wrong variant and lock yourself\nout of the bootloader, it may be possible to recover the device using JTAG/SWD.\n\n## Firmware Installation (Catsniffer V3)\n\nElectronic Cats provides a Catnip Uploader tool for loading firmware. For detailed information,\nrefer to the [repository](https://github.com/ElectronicCats/CatSniffer-Tools/tree/main).\nDownload the tool and follow these commands:\n\n```bash\n# Fetch the CatSniffer tools and their dependencies\n[ec@sniffle]$ git clone https://github.com/ElectronicCats/CatSniffer-Tools.git\n[ec@sniffle]$ cd CatSniffer-Tools/catnip_uploader\n[ec@sniffle]$ pip install -r requirements.txt\n\n# Download the available firmwares\n[ec@sniffle]$ python3 catnip_uploader.py releases\n[INFO] Fetching assets from https://api.github.com/repos/ElectronicCats/CatSniffer-Firmware/releases/latest\n[INFO] Release: board-v3.x-v1.1.0\n[INFO] Fetching assets from https://api.github.com/repos/nccgroup/Sniffle/releases/latest\n[INFO] Release: v1.10.0\n[INFO] Found local release: releases_board-v3.x-v1.1.0\n[SUCCESS] Local release is up to date: board-v3.x-v1.1.0\n[SUCCESS] Available releases:\n0: sniffer_fw_CC1352P_7_v1.10.hex\n1: airtag_scanner_CC1352P_7_v1.0.hex\n2: nccgroup_v1.10.0_sniffle_cc1352p7_1M.hex\n3: airtag_spoofer_CC1352P_7_v1.0.hex\n4: sniffle_CC1352P_7_v1.7.hex\n\n# Install the firmware\n[ec@sniffle]$ python3 catnip_uploader.py load 2 COMPORT\n```\n\nYou need to change the *COMPORT* to the appropriate path for your board.\nUsing the command `python3 catnip_uploader.py load 2 COMPORT`, you will load\nthe `2: nccgroup_v1.10.0_sniffle_cc1352p7_1M.hex` firmware.\n**To load the firmware Catsniffer V3 requires SerialPassthroughwithboot**.\n\n**WARNING:** Do not flash the wrong build variant using the bootloader, or you\nrisk bricking the device and locking yourself out of the bootloader. If you\nuse the `catnip_uploader.py` script to fetch and install the firmware, it will\nonly present compatible firmware. However, if you choose to compile and install\nthe firmware manually, be sure you use the correct build variant. For CatSniffer\nv3 devices, use the `sniffle_cc1352p7_1M.hex` file (`CC1352P74_1M` build variant).\nCatSniffer v1.x/v2.x devices use a different chip variant (CC1352P1) that needs a\ndifferent firmware build (`CC1352P1F3_1M` variant, `sniffle_cc1352p1_cc2652p1_1M.hex`\nimage). Sniffle has not been tested on CatSniffer v1.x/v2.x devices but they will\nprobably work as long as you flash the appropriate build variant. If you flash the\nwrong variant and lock yourself out of the bootloader, it may be possible to recover\nthe device using JTAG/SWD.\n\n## Sniffer Usage\n\n```\n[skhan@serpent python_cli]$ ./sniff_receiver.py --help\nusage: sniff_receiver.py [-h] [-s SERPORT] [-b BAUDRATE] [-c {37,38,39}] [-p] [-r RSSI]\n                         [-m MAC] [-i IRK] [-S STRING] [-a] [-A] [-e] [-H] [-l] [-q]\n                         [-Q PRELOAD] [-n] [-C] [-d] [-o OUTPUT]\n\nHost-side receiver for Sniffle BLE5 sniffer\n\noptions:\n  -h, --help            show this help message and exit\n  -s SERPORT, --serport SERPORT\n                        Sniffer serial port name\n  -b BAUDRATE, --baudrate BAUDRATE\n                        Sniffer serial port baud rate\n  -c {37,38,39}, --advchan {37,38,39}\n                        Advertising channel to listen on\n  -p, --pause           Pause sniffer after disconnect\n  -r RSSI, --rssi RSSI  Filter packets by minimum RSSI\n  -m MAC, --mac MAC     Filter packets by advertiser MAC\n  -i IRK, --irk IRK     Filter packets by advertiser IRK\n  -S STRING, --string STRING\n                        Filter for advertisements containing the specified string\n  -a, --advonly         Passive scanning, don't follow connections\n  -A, --scan            Active scanning, don't follow connections\n  -e, --extadv          Capture BT5 extended (auxiliary) advertising\n  -H, --hop             Hop primary advertising channels in extended mode\n  -l, --longrange       Use long range (coded) PHY for primary advertising\n  -q, --quiet           Don't display empty packets\n  -Q PRELOAD, --preload PRELOAD\n                        Preload expected encrypted connection parameter changes\n  -n, --nophychange     Ignore encrypted PHY mode changes\n  -C, --crcerr          Capture packets with CRC errors\n  -d, --decode          Decode advertising data\n  -o OUTPUT, --output OUTPUT\n                        PCAP output file name\n```\n\nThe XDS110 debugger on the Launchpad boards creates two serial ports. On\nLinux, they are typically named `ttyACM0` and `ttyACM1`. The first of the\ntwo created serial ports is used to communicate with Sniffle. By default,\nthe Python CLI communicates using the first CDC-ACM device it sees matching\nthe TI XDS110 USB VID:PID combo, or the first Sonoff dongle it sees. You\nmay need to override this with the `-s` command line option if you are using\na different USB serial adapter or have additional USB CDC-ACM devices connected.\n\nFor the `-r` (RSSI filter) option, a value of -40 tends to work well if the\nsniffer is very close to or nearly touching the transmitting device. The RSSI\nfilter is very useful for ignoring irrelevant advertisements in a busy RF\nenvironment. The RSSI filter is only active when capturing advertisements,\nas you always want to capture data channel traffic for a connection being\nfollowed. You probably don't want to use an RSSI filter when MAC filtering\nis active, as you may lose advertisements from the MAC address of interest\nwhen the RSSI is too low.\n\nTo hop along with advertisements and have reliable connection sniffing, you\nneed to set up a MAC filter with the `-m` option. You should specify the\nMAC address of the peripheral device, not the central device. To figure out\nwhich MAC address to sniff, you can run the sniffer with RSSI filtering while\nplacing the sniffer near the target. This will show you advertisements from\nthe target device including its MAC address. It should be noted that many BLE\ndevices advertise with a randomized MAC address rather than their \"real\" fixed\nMAC written on a label.\n\nMost new BLE devices use Resolvable Private Addresses (RPAs) rather than fixed\nstatic or public addresses. While you can set up a MAC filter to a particular\nRPA, devices periodically change their RPA. RPAs can can be resolved (associated\nwith a particular device) if the Identity Resolving Key (IRK) is known. Sniffle\nsupports automated RPA resolution when the IRK is provided. This avoids the need\nto keep updating the MAC filter whenever the RPA changes. You can specify an\nIRK for Sniffle with the `-i` option; the IRK should be provided in hexadecimal\nformat, with the most significant byte (MSB) first. Specifying an IRK allows\nSniffle to channel hop with an advertiser the same way it does with a MAC filter.\nThe IRK based MAC filtering feature (`-i`) is mutually exclusive with the static\nMAC filtering feature (`-m`).\n\nThere is also a convenience feature to automatically identify the MAC address\nof the advertiser whose advertisement or scan response contains a specified\nstring (series of bytes). This is useful for devices with RPAs where the IRK is\nunknown, but the advertisement contains a sufficiently unique static string suitable\nfor identification. This feature uses the `-S` option, with the string specified\nusing standard escape sequences. For example, to look for an advertiser whose\nadvertisement contains the hex byte sequence DE AD BE EF, specify\n`-S \"\\xDE\\xAD\\xBE\\xEF\"`. To look for an advertiser with the string \"hello\",\nsimply specify `-S \"hello\"`. When the string search feature is used, initially\nall MAC addresses will be accepted till an advertisement containing the search\nstring is found. After that, a MAC filter will be set up with the corresponding\nadvertiser's MAC address, and any RSSI filter would be automatically disabled.\n\nTo enable following auxiliary pointers in Bluetooth 5 extended advertising,\nenable the `-e` option. To improve performance and reliability in extended\nadvertising capture, this option disables hopping on the primary advertising\nchannels, even when a MAC filter is set up. If you are unsure whether a\nconnection will be established via legacy or extended advertising, you can\nenable the `-H` flag in conjunction with `-e` to perform primary channel\nhopping with legacy advertisements, and scheduled listening to extended\nadvertisement auxiliary packets. When combining `-e` and `-H`, the\nreliability of connection detection may be reduced compared to hopping on\nprimary (legacy) or secondary (extended) advertising channels alone.\n\nTo sniff the long range PHY on primary advertising channels, specify the `-l`\noption. Note that no hopping between primary advertising channels is supported\nin long range mode, since all long range advertising uses the BT5 extended\nmechanism. Under the extended mechanism, auxiliary pointers on all three\nprimary channels point to the same auxiliary packet, so hopping between\nprimary channels is unnecessary.\n\nTo not print empty data packets on screen while following a connection, use\nthe `-q` flag. This makes it easier to observe meaningful communications in\nreal time, but may obscure when connection following is flaky or lost.\n\nFor encrypted connections, Sniffle supports detecting connection parameter\nupdates even when the encryption key is unknown, and it attempts to measure\nthe new parameters. However, if you know the new connection interval and Instant\ndelta to expect in encrypted connection parameter updates, you can specify them\nwith the `--preload`/`-Q` option to improve performance/reliability.\nThe expected Interval:DeltaInstant pair should be provided as colon separated\nintegers. Interval is an integer representing multiples of 1.25 ms (as defined\nin LL\\_CONNECTION\\_UPDATE\\_IND). DeltaInstant is the number of connection events\nbetween when the connection update packet is transmitted and when the new\nparameters are applied. DeltaInstant must be greater than or equal to 6, as per\nthe Bluetooth specification's requirements for central devices. If multiple\nencrypted parameter updates are expected, you can provide multiple parameter\npairs, separated by commas (eg. `6:7,39:8`). If you have a device that issues\nencrypted PHY update PDUs that don't change the PHY, or puts out encrypted LE\npower control PDUs without any PHY changes, you can use the `--nophychange`/`-n`\noption.\n\nTo stop the sniffer, press Ctrl-C.\n\nIf for some reason the sniffer firmware locks up and refuses to capture any\ntraffic even with filters disabled, you should reset the sniffer MCU. On\nLaunchpad boards, the reset button is located beside the micro USB port.\n\n## Scanner Usage\n\n```\nusage: scanner.py [-h] [-s SERPORT] [-b BAUDRATE] [-c {37,38,39}] [-r RSSI] [-l] [-d] [-o OUTPUT]\n\nScanner utility for Sniffle BLE5 sniffer\n\noptions:\n  -h, --help            show this help message and exit\n  -s SERPORT, --serport SERPORT\n                        Sniffer serial port name\n  -b BAUDRATE, --baudrate BAUDRATE\n                        Sniffer serial port baud rate\n  -c {37,38,39}, --advchan {37,38,39}\n                        Advertising channel to listen on\n  -r RSSI, --rssi RSSI  Filter packets by minimum RSSI\n  -l, --longrange       Use long range (coded) PHY for primary advertising\n  -d, --decode          Decode advertising data\n  -o OUTPUT, --output OUTPUT\n                        PCAP output file name\n\n```\n\nThe scanner command line arguments work the same as the sniffer. The purpose of\nthe scanner utility is to gather a list of nearby devices advertising, and\nactively issue scan requests for observed devices, without having the deluge\nof fast scrolling data you get with the sniffer utility. The hardware/firmware\nwill enter an active scanning mode where it will report received advertisements,\nissue scan requests for scannable ones, and report received scan responses.\nThe scanner utility will record and report observed MAC addresses only once\nwithout spamming the display. Once you're done capturing advertisements, press\nCtrl-C to stop scanning and report the results. The scanner will show the last\nadvertisement and scan response from each target. Scan results will be sorted\nby RSSI in descending order.\n\n## Usage Examples\n\nSniff all advertisements on channel 38, ignore RSSI \u003c -50, stay on advertising\nchannel even when CONNECT\\_REQs are seen.\n\n```\n./sniff_receiver.py -c 38 -r -50 -a\n```\n\nSniff advertisements from MAC 12:34:56:78:9A:BC, stay on advertising channel\neven when CONNECT\\_REQs are seen, save advertisements to `data1.pcap`.\n\n```\n./sniff_receiver.py -m 12:34:56:78:9A:BC -a -o data1.pcap\n```\n\nSniff advertisements and connections for the first MAC address seen with\nRSSI \u003e= -40. The RSSI filter will be disabled automatically once a MAC address\nhas been locked onto. Save captured data to `data2.pcap`.\n\n```\n./sniff_receiver.py -m top -r -40 -o data2.pcap\n```\n\nSniff advertisements and connections from the peripheral with big endian IRK\n4E0BEA5355866BE38EF0AC2E3F0EBC22. Preload two expected encrypted connection\nparameter updates; the first with an Interval of 6, occuring at an instant 6\nconnection events after an encrypted LL\\_CONNECTION\\_UPDATE\\_IND is observed\nby the sniffer. The second expected encrypted connection update has an Interval\nof 39, and DeltaInstant of 6 too.\n\n```\n./sniff_receiver.py -i 4E0BEA5355866BE38EF0AC2E3F0EBC22 -Q 6:6,39:6\n```\n\nSniff BT5 extended advertisements and connections from nearby (RSSI \u003e= -55) devices.\n\n```\n./sniff_receiver.py -r -55 -e\n```\n\nSniff legacy and extended advertisements and connections from the device with the\nspecified MAC address. Save captured data to `data3.pcap`.\n\n```\n./sniff_receiver.py -eH -m 12:34:56:78:9A:BC -o data3.pcap\n```\n\nSniff extended advertisements and connections using the long range primary PHY on\nchannel 38.\n\n```\n./sniff_receiver.py -le -c 38\n```\n\nActively scan on channel 39 for advertisements with RSSI greater than -50.\n\n```\n./scanner.py -c 39 -r -50\n```\n\n## Obtaining the IRK\n\nIf you have a rooted Android phone, you can find IRKs (and LTKs) in the Bluedroid\nconfiguration file. On Android 8.1, this is located at `/data/misc/bluedroid/bt_config.conf`.\nThe `LE_LOCAL_KEY_IRK` specifies the Android device's own IRK, and the first 16\nbytes of `LE_KEY_PID` for every bonded device in the file indicate the bonded\ndevice's IRK. Be aware that keys stored in this file are little endian, so\n**the byte order of keys in this file will need to be reversed.** For example,\nthe little endian IRK 22BC0E3F2EACF08EE36B865553EA0B4E needs to be changed to\n4E0BEA5355866BE38EF0AC2E3F0EBC22 (big endian) when being passed to Sniffle with\nthe `-i` option.\n\nYou can also find the IRK and LTK through HCI Snoop logs captured on Android or iOS\nwithout rooting the device:\n\n* Android: \u003chttps://novelbits.s3.us-east-2.amazonaws.com/Developer+Guides/Android+Bluetooth+Debugging+Guide.pdf\u003e\n* iOS: \u003chttps://novelbits.s3.us-east-2.amazonaws.com/Developer+Guides/iOS+Bluetooth+Debugging+Guide.pdf\u003e\n\n## Wireshark Plugin\n\nSniffle includes a Wireshark plugin that makes it possible to launch Sniffle automatically\nfrom the Wireshark GUI by selecting the 'Sniffle' capture interface.\n\nTo install the Sniffle plugin, first find the location of your Personal Extcap folder in the\n'About Wireshark' dialog (*Help* \u003e *About Wireshark* \u003e *Folders* \u003e *Personal Extcap path*).\nOn POSIX (Linux and Mac OS) systems running recent versions of Wireshark (4.2.0+), this\nfolder is located at `~/.local/lib/wireshark/extcap`. Under Windows, it can be found at\n`%USERPROFILE%\\AppData\\Roaming\\Wireshark\\extcap`.\n\nOn POSIX systems, you can just symlink the Sniffle extcap plugin into the Wireshark personal\nextcap directory:\n\n```\nmkdir -p ~/.local/lib/wireshark/extcap\nln -s $(pwd)/python_cli/sniffle_extcap.py ~/.local/lib/wireshark/extcap\n```\n\nOn Mac OS, Wireshark may try to use the Xcode Python rather than the Python in your PATH specified\nby your shell profile. Thus, the Sniffle plugin may fail to show up in extcap interfaces if PySerial\nis not installed for the Xcode Python. To fix this, you can edit the shebang line of\n`sniffle_extcap.py` to directly point to the Python with PySerial installed, for example the\nHomebrew Python at `/opt/homebrew/bin/python3`, rather than `/usr/bin/env python3`.\n\nOn Windows, you can copy the following files and directories from the `python_cli` directory into\nyour Personal Extcap folder:\n\n```\nsniffle/\nsniffle_extcap.py\nsniffle_extcap.bat\n```\n\nOn Windows, it may be necessary to edit `sniffle_extcap.bat` to specify the location of\nthe python interpreter if the installation directory is not included in the PATH, e.g.:\n\n```\n@echo off\nC:\\my_python_install\\python.exe \"%~dp0sniffle_extcap.py\" %*\n```\n\nOnce the plugin has been installed, restart Wireshark or choose *Capture* \u003e *Refresh Interfaces*\nto enable the Sniffle interface.\n\n## Transmit Functionality\n\nWhile the original 2019 Sniffle firmware was purely a passive listener, later firmware versions\nadded various features to actively transmit packets in various ways. Current Sniffle firmware\nsupports acting as both a GAP central and peripheral device, including active scanning, legacy\nand extended advertising, initiating connections, and being connected in a central or\nperipheral role. The `scanner.py` script performs active scanning. The `initiator.py`\nscript initiates a connection to a peripheral and then acts as a connected central. The\n`advertiser.py` script performs legacy advertising and accepts connection requests from other\ndevices, transitioning to a connected peripheral role.\n\nThe transmit functionality of Sniffle is a little different from a traditional HCI-based Bluetooth\ncontroller, because it gives you very low level control of the exact PDUs being sent at the link\nlayer. This low-level control allows the host-side code to implement additional functionality,\nsuch as link layer fuzz testing or link layer relay attacks.\n\nI have not yet taken the time to formally document the Sniffle firmware's API, though it is fairly\nself-explanatory when looking at its host-side implementation in `sniffle_hw.py`. Active scanning\n(that transmits scan requests) is activated by `cmd_scan`. Connection initiation is triggered by\n`cmd_connect`, though it's easiest to use the `initiate_conn` wrapper. Advertising (optionally\nconnectable) is activated by `cmd_advertise` for legacy advertising, or `cmd_advertise_ext` for\nextended advertising.\n\n## XDS110 UART Latency\n\nSince the fixing of TI issue [EXT_EP-11735](https://sir.ext.ti.com/jira/browse/EXT_EP-11735) in\nmid-2024, the XDS110 debugger (included on TI Launchpad boards) handles high baud rates such as\n2M (as used by Sniffle) in a reasonable manner without excessive latency. However, the latest\nXDS110 firmware still uses buffered DMA-driven operation of UART at such baud rates, and as\nsuch can still introduce latency up to 30 ms. This latency is inconsequential for use as a sniffer,\nbut may be detrimental to more active operations such as host-side code acting as a GATT client\nor server, or performing relay attacks. The modification of XDS110 firmware version 3.0.0.28\ndesrcribed below for interrupt-based operation can still greatly reduce latency for such\ntime-sensitive operations. It should be possible to make a similar modification to the latest\nXDS110 firmware, but I haven't taken the time to reverse engineer it and find the right bits\nto change.\n\nIn mid-2024 and earlier, the firmware of the TI XDS110 debugger (included on Launchpad boards)\nhad an undesirable behaviour in its USB to UART bridge, where at high baud rates, there can be severe\nlatency, especially with frequent small writes as done by the Sniffle firmware. This issue was\npresent for years, and was still present in April 2024 with the XDS110 firmware 3.0.0.28\nbundled with UniFlash 8.6.0. The root cause was that in DMA based operation, the XDS110 firmware\naccumulated UART data in a buffer whose size was proportional to baud rate, and waited for this\nbuffer to fill before transferring the data. There was logic to flush this buffer if no new data\narrived over the last 15 milliseconds, but this flushing logic was never triggered when Sniffle\nwas frequently adding small packets from connection events every few milliseconds. As a result of\nthis suboptimal behaviour, sniffed data could appear in delayed bursts on the host.\n\nThe XDS110 firmware also has an alternate mode for UART operation, where every UART receive\ntriggers an interrupt that results in data immediately being passed to the host. This\ninterrupt-based mode of operation has much lower latency. However, the firmware only uses it for\nbaud rates below 230400. As a workaround to the high latency of DMA mode operation with frequent\nsmall data chunks, you can modify the firmware to use interrupt-based USB-UART bridging even at\nhigh baud rates (like 2M baud as used by Sniffle). In firmware 3.0.0.28 (included with Uniflash\n8.6.0), you can hex edit the bytes at offset 0x0A14 from 61 3F to 00 1F. This will change the\nbaud rate for switching to DMA-based UART operation from 230400 to 0x200000 (2097152).\n\nBe aware that the offsets and byte modifications described above are only for firmware 3.0.0.28,\nand will be different for different firmware versions. Flashing invalid firmware onto your debugger\nmay damage it, and we assume no responsibility for any damage that may occur.\n\nThe following commands can be used on Linux to modify the XDS110 firmware for low latency UART\nat high baud rates:\n\n```\ncd ~/ti/uniflash_8.6.0/deskdb/content/TICloudAgent/linux/ccs_base/common/uscif/xds110/\ncp firmware_3.0.0.28.bin firmware_3.0.0.28_fastuart.bin\nprintf '\\x00\\x1f' | dd of=firmware_3.0.0.28_fastuart.bin bs=1 seek=$((0x0A14)) conv=notrunc\nsha256sum firmware_3.0.0.28_fastuart.bin\n```\n\nBefore flashing, verify that the SHA256 sum of the modified firmware is\n`c226f2e9cb2b9f0bc111ca11f2903d58d4065293468623428c0e8eeb22086dcf`. After verifying this,\nrun the following commands to flash the modified XDS110 debugger firmware:\n\n```\n./xdsdfu -m\n./xdsdfu -f firmware_3.0.0.28_fastuart.bin -r\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnccgroup%2Fsniffle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnccgroup%2Fsniffle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnccgroup%2Fsniffle/lists"}