No description
Find a file
2026-07-06 14:41:35 +02:00
data init 2025-11-20 17:23:26 +01:00
example_data added measurement device info 2026-05-21 18:10:57 +02:00
rx init 2025-11-20 17:23:26 +01:00
tx init 2025-11-20 17:23:26 +01:00
utils init 2025-11-20 17:23:26 +01:00
.gitignore init 2025-11-20 17:23:26 +01:00
collect_all_data.py init 2025-11-20 17:23:26 +01:00
LICENSE made repo public on self-hosted git 2026-07-06 14:41:35 +02:00
README.md added measurement device info 2026-05-21 18:10:57 +02:00
requirements.txt init 2025-11-20 17:23:26 +01:00
run_demod.py init 2025-11-20 17:23:26 +01:00
run_demod_threaded.py init 2025-11-20 17:23:26 +01:00
run_rx.py init 2025-11-20 17:23:26 +01:00
run_tx.py init 2025-11-20 17:23:26 +01:00
tx_loop.py init 2025-11-20 17:23:26 +01:00

VeiledWaves

Python prototype of unidirectional covert channel using transmission signal strength of wireless NICs.

Functionality is explained in paper "VeiledWaves: A Covert Channel via Transmission Power Modulation in Wi-Fi Networks"

Dependencies

  • python (tested on 3.13.7)
  • RX:
  • TX:

Setup

RX and TX

make sure python (v3.13) is installed python --version


on RX make sure kismet is installed kismet -v

add user to kismet group sudo usermod -aG kismet username

reboot to commit changes

start kismet once kismet

visit the web interface on http://localhost:2501

  • create user (login credentials needed for next steps)
  • make sure the NICs are available under data sources

clone/download the repository to RX, unzip it

open a terminal and enter the directory cd veiled_waves

create virtual environment, activate, install dependencies

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

on TX

make sure iw is installed iw --version

get mac address and channel of TX iw dev

  • note addr, channel and channel width of the interface connected to a network denote the channel and width in accordance to the kismet documentation

clone or download the code on TX

no venv setup is needed on TX


Adjusting the configuration

on RX adjust rx/rx_settings.json

put the user and password for kismet in the corresponding JSON fields. As well as the mac address and channel of TX in mac_address and tx_channel. Make sure tx_channel stays a string.

Here you can also adjust what interfaces should be used on RX for capture and monitor. put "auto" to let the program auto select.


on TX adjust tx/tx_settings.json

Here you can also adjust the interface as well as all used transmission settings (length bits)

Transmission

on TX

make sure a continuous data transmission over WiFi is present using for example ping example.org > /dev/null &


on RX

run python run_rx.py

you can now open Kismet (http://localhost:2501) and search for TX via MAC address you should the last seen time increasing every second or so. if it does not you might need to adjust the monitoring channel. (using data from TX iw dev)

once you are sure the signal is getting captured properly


on TX run sudo python run_tx.py -m 10101 with 10101 being the bits you want to transmit over the covert channel make sure their length can be represented by the number of length bits set in tx_settings.json

once the transmission is finished on TX,

press Ctrl+C on RX to stop run_rx.py

Demodulation

After the transmission has finished there should be a new folder in the data folder of RX. Named after the time you stopped the RX script.

And a new JSON file in the data folder of TX.

Copy the JSON file of TX into the folder on RX. (use example_data as guide if needed) The received data is stored in vw_kismte.kismet (an sqlite DB)

On RX run python run_demod.py

The results of the transmission are displayed on stdout and saved into a CSV file.

Bulk Transmission

Make sure a continuous data transmission on TX is present (ping).

Start the RX script as described above.

Use the tx_loop.py script on TX. It creates random messages of default length 10 (adjustable in the script)

Stop the script with Ctrl+C once you want the transmission to stop.

Put all created JSON files into the corresponding RX folder.

It is recommended to use python run_demod_threaded.py to demodulate the data. However the results will not be properly displayed on stdout.

Analysis

The results of the transmission can be analyzed using the collect_all_data.py script.

It sums up important statistics into 2 JSON files.

  • all_info.json contains stats about the message transmission and it's success.
  • meta_info.json contains info about the environment that the measurement has taken place in.

Additionally it reduces the size of the vw_kismet.kismet database. The base database is moved to full_dataset.kismet, which should be deleted since it contains data concerning other devices that are not relevant to the covert channel. Thus taking up more space than needed.

Example Dataset

Three example measurements have been provided. They were all taken in a high noise environment on 5GHz, having TX placed at different distances from RX. Simply move the folders to data to run the scripts again or analyze them manually.

Hardware used

For the RX a ThinkPad T14 Gen 5 running Arch Linux lts kernel was used. Channel-hopping NIC: Wifi TP-Link Archer T2U PLUS [RTL8821AU] Measuring NIC: Intel Corporation Meteor Lake PCH CNVi WiFi (rev 20) Kernel modules: iwlwifi

ethtool -i wlan0
driver: iwlwifi
version: 6.18.32-1-lts
firmware-version: 89.735b75a4.0 ma-b0-gf-a0-89.uc
expansion-rom-version: 
bus-info: 0000:00:14.3

ethtool -i wlan1
driver: rtw88_8821au
version: 6.18.32-1-lts

The full output of iw list is available under example_data/iw_list_RX.txt For the TX three identical Dell Latitude 7280 running Kali Linux 6.12.13. Transmission NIC: Intel Corporation Wireless 8265 / 8275 (rev 78)

ethtool -i wlan0
driver: iwlwifi
version: 6.12.25-amd64
firmware-version: 36.ca7b901d.0 8265-36.ucode
expansion-rom-version: 
bus-info: 0000:02:00.0

The full output of iw list is available under example_data/iw_list_TX.txt

high_noise_3m_wall_inverse

This dataset has a special property. TX was placed behind a thick concrete wall. Upon initial demodulation, there is a 100% error rate. However after inspecting the length data, it appears to be correct for most measurements, just inverted. After switching the high and low values in utils/kismet_db.py function get_bin_from_signals to:

if median > avg:
classified_signals.append(0)
else:
classified_signals.append(1)

And running run_demod_threaded.py again. Most transmissions demodulate successfully. While we were not able to recreate this phenomenon, we provided the dataset for further inspection.

Credits

Encoding libraries used:

since the TX code is supposed to be on a remote system that has highly monitored connections, all libraries used for TX are directly included in the repository instead of imported via pip

Solomon Reed: https://github.com/tomerfiliba-org/reedsolomon

Hamming Code: https://github.com/TheAlgorithms/Python/blob/master/hashes/hamming_code.py (location in project: tx/hamming_code.py)