preferred-network-list-sniffer
A reconnaissance tool for capturing and displaying SSIDs from device's Preferred Network List.
https://github.com/aleksamcode/preferred-network-list-sniffer
Science Score: 44.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
✓CITATION.cff file
Found CITATION.cff file -
✓codemeta.json file
Found codemeta.json file -
✓.zenodo.json file
Found .zenodo.json file -
○DOI references
-
○Academic publication links
-
○Academic email domains
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (13.1%) to scientific vocabulary
Keywords
Repository
A reconnaissance tool for capturing and displaying SSIDs from device's Preferred Network List.
Basic Info
Statistics
- Stars: 150
- Watchers: 4
- Forks: 8
- Open Issues: 16
- Releases: 0
Topics
Metadata Files
README.md

Preferred Network List Sniffer - PNLS
Preferred Network List Sniffer (PNLS) is a Red Team Wi-Fi auditing tool with a simple web interface that is capable of intercepting SSIDs[^1] from the device's preferred network list (PNL)[^2]. This is achieved by sniffing out Probe Requests in the nearby vicinity, which are then parsed for SSID and other information and finally propagated to the web UI. The primary motivation for this project was to look into 802.11 Probe Requests and the privacy risks associated with the data they transmit.
[!WARNING] All content in this project is intended for security research purposes only.
[!NOTE]
This project is part of my ongoing research into Privacy Protection in Wi-Fi Networks.
To monitor the ongoing work on the PNLS, see the project's board.
Table of contents
How to build the PNLS
Here is what you will need in order to duplicate and deploy this project, including both the hardware and software components. Once you have your working environment ready, head over to the setup sections.
Requirements
- Raspberry Pi (RPi)
- Suitable RPi power supply (see the power supply documentation for details)
- Micro SD card (see the SD card documentation for details)
- USB Wi-Fi adapter (optional)
- Used to achieve a bigger range when capturing packets.
- HDMI cable (optional)
- Used to display the web UI from the RPi instead of connecting to it remotely using your computer.
Prerequisites
- Kali Linux OS
- Needed in order to use monitoring mode and aircrack-ng tool. You can download the Kali Linux ARM image from here.
- Alternatively, you could use another OS, but you will need to patch[^3] the kernel using the nexmon[^4] or use a wireless adapter that supports monitoring mode. Here is a link for supported USB adapters by Raspberry Pi.
- You will also have to install the aircrack-ng tool, as it only comes preinstalled on Kali Linux.
- Start your network interface in monitoring mode with:
sudo airmon-ng start wlan0[2].
[!NOTE]
The Kali image uses Re4son's kernel, which includes the drivers for external Wi-Fi cards and the Nexmon firmware for the built-in wireless card on the RPi 3 and 4 [3].
Setup
If you don't want to use Docker, head over to setup without Docker.
Using Docker
Quickly setup a development instance:
```bash
First clone this repo.
git clone https://github.com/AleksaMCode/Preferred-Network-List-Sniffer.git
Move to the project root folder.
cd Preferred-Network-List-Sniffer
Build backend and frontend image.
docker compose build
Bring up both the backend and the frontend server.
docker compose up
Move into the sniffer folder.
cd sniffer
Run the Sniffer service.
sudo python3 sniffer.py ```
Using Prebuild Docker Image
Currently, multi-platform images are not available, and the project only supports the ARM64v8 architecture. Download the latest prebuild images from the GitHub Container Registry and run them locally.
```bash
First clone this repo.
git clone https://github.com/AleksaMCode/Preferred-Network-List-Sniffer.git
Move to the project root folder.
cd Preferred-Network-List-Sniffer
Download the prebuild images.
docker pull ghcr.io/aleksamcode/pnls-backend-ghcr:latest docker pull ghcr.io/aleksamcode/pnls-frontend-ghcr:latest
Bring up both the backend and the frontend server.
docker compose up
Move into the sniffer folder.
cd sniffer
Run the Sniffer service.
sudo python3 sniffer.py ```
Without Docker
Backend: to start the ASGI and Redis servers and to run needed services, see these instructions.
Frontend: to run the React server, see these instructions.
Here is a screenshot when everything was ran "manually":
- Top Left: Redis server
- Top Right: ASGI server
- Bottom Left: Sniffer service
- Bottom Right: React server
Probe Requests
Probe Requests are management 802.11 frames that are used to connect devices to the previously associated wireless Access Points (AP). Whenever a device has enabled Wi-Fi but isn't connected to a network, it is periodically sending a burst of Probe Requests containing SSIDs from its PNL. These frames are sent unencrypted, and anyone who is Radio Frequency (RF) monitoring can capture and read them. Probes are sent to the broadcast DA address (ff:ff:ff:ff:ff:ff). Once they are sent, the device starts the Probe Timer. At the end of the timer, the device processes the received answer. If the device hasn't received an answer, it will go to the next channel and repeat the process. There are two types of Probe Requests:
Directed Probe Requests: using specific SSID from device's PNL
Null Probe Requests: using Wildcard SSID (empty SSID)
Blank Requests are sent in order to get a response from all available APs that are in range.
In addition to filtering 802.11 Probe Request frames from all the captured packets, Sniffer will also filter out the Wildcard SSIDs.
SSID Filtering
When capturing Probe Requests at places where there is a large local network with a lot of Wi-Fi clients, PNLS will inevitably capture a lot of Probe Requests that contain the SSID of the said network. The filtering of such SSIDs might be advantageous, as they are of no value to us and can cause an increase in socket load. Filtering out these SSIDs will not only reduce the load on socket connections, but it will also prevent the spam of the aforementioned SSIDs on the web UI.
When using this feature, you will need to make slight adjustments to the source code. Precisely, you will need to update the SSID_FILTER list in the settings.py file with the value you want the Sniffer to ignore. Once updated, rebuild the project and start the PNLS.
Architecture
This project uses Event-Driven architecture (EDA), which is designed atop of message-driven architectures. While this project uses a centralized solution (everything is run from the RPi), due to loosely coupled components as a result of the usage of EDA, it is possible to create a decentralized solution if needed. PNLS consists of an event publisher (sniffer), an event consumer (web application), and an event channel. Here, the event channel is implemented as Message-Oriented Middleware (MOM).
Why Asynchronous Server Gateway Interface?
The Asynchronous Server Gateway Interface (ASGI) provides a standardized interface between async-capable Python web servers and services [4]. The ASGI was chosen due to the project's need for a long-lived WebSocket connection in order to facilitate async communications between different clients. In addition, it also allows for the utilization of background coroutines during API calls. The PNLS uses the uvicorn implementation for Python in order to use the ASGI web server.
Why WebSockets?
Through the utilization of WebSocket communication protocol, we are able to facilitate full-duplex, two-way communication. While this project doesn't have the need for two-way communication, it does have a need for real-time interaction between the system components. This way, the sniffed data will be available to the end-user as soon as it is captured.
Pub-Sub Model
The project's MOM is realized through the Message Broker using Redis. In the publish-subscribe (pub-sub) model, the Sniffer is responsible for producing messages, while the web application (subscriber) registers for the specific Topic (Redis channel). When the Sniffer sends a message to a Topic, it is distributed to all subscribed consumers, allowing for asynchronous and scalable communication. PNLS uses the lightweight messaging protocol Redis Pub/Sub for message broadcasting in order to propagate short-lived messages with low latency and large throughput [5][6]. In this way, overheads associated with encoding data structures in a form that can be written to a disk have been avoided. In doing so, this solution will have potentially better performance [7]. The figure below displays the simplified system activity through the event-driven workflow.
[!NOTE] Implemented MOM does not provide persistent storage or a message queue for data accumulation, which means messages will be lost if they are published to a Topic without subscribers.
Screenshots
Below is an example of a web UI displaying published test SSIDs.
Acronyms
| PNL | Preferred Network List |
| PNLS | Preferred Network List Sniffer |
| SSID | Service Set Identifier |
| UI | User Interface |
| RPi | Raspberry Pi |
| OS | Operating System |
| AP | Access Points |
| RF | Radio Frequency |
| EDA | Event-Driven Architecture |
| MOM | Message-Oriented Middleware |
| ASGI | Asynchronous Server Gateway Interface |
| pub-sub | publish-subscribe |
References
- Nexmon Git repository
- Aircrack-ng documentation
- Kali On ARM documentation
- ASGI Documentation
- Low-latency message queue & broker software
- Redis - Pub/Sub Defined
- Stephen M. Rumble, Ankita Kejriwal, and John K. Ousterhout, “Log-Structured Memory for DRAM-Based Storage,” at 12th USENIX Conference on File and Storage Technologies (FAST)
- Enable Monitor Mode & Packet Injection on the Raspberry Pi
[^1]: A Service Set Identifier (SSID) is an 802.11 ID used to name a Wi-Fi network that consists of a maximum of 32 characters that can contain case-sensitive letters, numbers, and special characters no longer than 32 characters. [^2]: A Preferred Network List is a collection of saved SSIDs with additional settings that you created the first time you connected your device to those networks. [^3]: Broadcom never officially supported monitor mode, which limited the usefulness of the wireless cards in Raspberry Pi devices [8]. The Nexmon project is a firmware patch for the Broadcom chips in use within RPi devices. [1]. This patch will allow you to use the monitoring mode on your RPi device. [^4]: The C-based Firmware Patching Framework for Broadcom/Cypress Wi-Fi Chips that enables Monitor Mode, Frame Injection and much more.
Owner
- Name: Aleksa Majkić
- Login: AleksaMCode
- Kind: user
- Location: Banja Luka, Bosnia and Herzegovina
- Twitter: aleksamcode
- Repositories: 6
- Profile: https://github.com/AleksaMCode
I code. Sometimes.
Citation (CITATION.cff)
cff-version: 1.2.0
message: 'If you use this software, please cite it as below.'
authors:
- given-names: Aleksa
family-names: Majkić
email: aleksamcode@gmail.com
title: 'Preferred Network List Sniffer'
version: 0.2.0
type: software
date-released: 2024-01-09
url: 'https://github.com/AleksaMCode/Preferred-Network-List-Sniffer'
keywords:
- rpi
- pln
- pnls
- 802.11
- ssid
license: MIT
GitHub Events
Total
- Issues event: 3
- Watch event: 13
- Delete event: 1
- Issue comment event: 3
- Push event: 3
- Pull request event: 2
- Fork event: 1
- Create event: 1
Last Year
- Issues event: 3
- Watch event: 13
- Delete event: 1
- Issue comment event: 3
- Push event: 3
- Pull request event: 2
- Fork event: 1
- Create event: 1
Dependencies
- 1277 dependencies
- prettier ^3.1.0 development
- @testing-library/jest-dom ^5.17.0
- @testing-library/react ^13.4.0
- @testing-library/user-event ^13.5.0
- bootstrap ^5.3.2
- dateformat ^5.0.3
- framer-motion ^10.16.12
- react ^18.2.0
- react-bootstrap ^2.9.1
- react-dom ^18.2.0
- react-scripts 5.0.1
- react-toastify ^9.1.3
- web-vitals ^2.1.4
- fastapi ==0.104.1
- loguru ==0.7.2
- redis ==5.0.1
- scapy ==2.5.0
- starlette *
- uvicorn *
- websocket-client ==1.7.0
- websockets ==12.0
- yaspin ==3.0.1
- ghcr.io/aleksamcode/pnls-backend-ghcr latest
- ghcr.io/aleksamcode/pnls-frontend-ghcr latest
- redis alpine
- python 3.11.4 build
- node 20.5.1 build