WHAD (Wireless HAcking Devices)

repository·main·Indexed 43 days ago

https://github.com/whad-team/whad-client

A wireless protocols hacking framework providing command-line tools and a Python library for exploring wireless devices. Version 1.2.17 features a two-layer abstraction model using Devices and Connectors, supporting hardware such as Ubertooth One, Yard Stick One, and nRF52840. It includes specialized BLE tools for scanning, GATT simulation via hooking exceptions, and a profile-based model for implementing BLE Peripherals and Centrals.

Tokens
72.6K
Snippets
281
Records
371
Agent score
56%

What's inside WHAD

  1. What is WHAD and its core philosophy

    main

    WHAD (Wireless HAcking Devices) is a framework designed to unify how wireless hacking hardware communicates with computers. Instead of hardware-specific tools, WHAD aims to make diverse hardware devices compatible with generic tools by moving high-level logic from the device to the host computer.

    Key principles:

    • Hardware handles hardware tasks: Devices focus on physical layer operations (transceiving bytes to/from air frames).
    • Host handles logic: Attacks, protocol stacks, and high-level operations are implemented in the WHAD framework on the computer.
    • Generic Compatibility: Any operation implemented in WHAD can be performed by any compatible device that supports the required capabilities.
  2. Use the winject CLI tool for wireless data injection

    main

    winject is a generic injection tool used to transmit arbitrary data across various wireless protocols and modulations. It supports domains natively handled by WHAD, including PHY (raw demodulation), Bluetooth Low Energy (BLE), IEEE 802.15.4, Nordic ESB, and Logitech Unifying.

    It can be used to inject:

    • Scapy packets: High-level protocol definitions.
    • Raw buffers: Hexadecimal bytestrings for raw modulation.
    • PCAP traffic: Replaying captured traffic by piping from tools like wplay.
    winject [OPTIONS] DOMAIN [DOMAIN OPTIONS] [PACKETS]
  3. Supported Hardware and Virtual Devices for WHAD

    main

    WHAD supports devices through two primary methods: running custom firmware on hardware or using an adaptation layer for existing virtual/hardware devices.

    Hardware Devices (Custom Firmware)

    These devices require flashing WHAD-compatible firmware (like Butterfly) to support specific protocols:

    • Makerdiary nRF52840 MDK USB Dongle: Supports BLE, Dot15d4, ESB, PHY, and Unifying.
    • Nordic nRF52840 Dongle: Supports BLE, Dot15d4, ESB, PHY, and Unifying.
    • SeeedStudio LoRa-e5-Mini: Supports PHY.
    • STM32WL55 Nucleo board: Supports PHY.
    • Espressif ESP32-WROOM: Supports BLE (Experimental).

    Virtual Devices (Adaptation Layer)

    These devices are supported via an adaptation layer without needing custom firmware:

    • Bluetooth HCI adapter: BLE
    • APIMote: Dot15d4
    • Bastille RFStorm: ESB, PHY, Unifying
    • ATMEL RZUSBSTICK: Dot15d4
    • Yard Stick One: PHY
    • Ubertooth One: BLE
  4. Use wble-central for BLE GATT client operations

    main

    wble-central is a command-line tool that provides a Bluetooth Low Energy (BLE) scanner and a GATT client. It allows you to detect surrounding BLE devices, connect to remote devices, and interact with their services and characteristics. This tool requires a device supporting the Bluetooth Low Energy domain.

    Basic Usage Pattern: wble-central [OPTIONS] ([COMMAND] ([COMMAND ARGS]))

    wble-central [OPTIONS] ([COMMAND] ([COMMAND ARGS]))
  5. Use wble-periph to create a BLE GATT server

    main

    The wble-periph tool allows you to act as a Bluetooth Low Energy (BLE) GATT server. You can define custom services, characteristics, and advertisement data. It can be used via an interactive shell to manually build a profile or by importing a JSON profile file.

    To use wble-periph, you must specify a WHAD interface (e.g., hci0) using the --interface (or -i) flag.

    wble-periph [OPTIONS] ([COMMAND] ([COMMAND ARGS]))
  6. Persistence of LoRaWAN end nodes in LWApplication

    main

    The whad.lorawan.app.LWApplication class automatically handles data persistence for end nodes. Information such as EUI, device address, and encryption keys are saved to a JSON file.

    • Filename: The file is named after the application's EUI.
    • Location: Stored in the current working folder.
    • Lifecycle: The file is automatically loaded when the application starts and saved when the application is stopped.
  7. Create a protocol stack layer

    main

    A protocol stack layer in Whad is a class that inherits from whad.common.stack.Layer. Each layer must have a unique textual alias defined using the @alias decorator. This alias is used by the protocol stack to reference the specific class. Layers receive data from lower layers, process it, and forward it to upper layers. Data flow is automatically managed by the base Layer class.

    To implement a layer, override the configure(self, options={}) method to initialize the layer's state using the provided options dictionary.

    from whad.common.stack import Layer, alias
    
    @alias('ether')
    class Ethernet(Layer):
        def configure(self, options={}):
            if 'something' in options:
                self.state.something = options['something']
  8. How WHAD interfaces and connectors work together

    main

    WHAD uses a layered abstraction model to separate physical hardware capabilities from high-level user tasks:

    1. Hardware Interfaces

    An interface is the hardware transceiver that converts bytes into air frames (and vice versa).

    • Discovery Protocol: Every interface supports a discovery protocol that allows the host to identify the device's capabilities, supported domains, firmware version, and source code location.
    • Communication: Interfaces exchange data with the host via the extensible WHAD protocol.
    • Time-critical tasks: Some interfaces handle tasks like channel hopping or connection-specific procedures that require hardware-level timing.

    2. Connectors

    A connector is an abstract class that sits on top of an interface to provide a higher-level API.

    • Abstraction: It maps an interface to a specific domain and role, exposing high-level functions to the user.
    • Validation: A connector verifies that the underlying interface supports the required domain and capabilities before executing commands.
    • Specialization: Connectors can inherit from one another, allowing for specialized layers of abstraction (e.g., a specific protocol connector inheriting from a more general domain connector).
  9. Define a custom LoRaWAN Channel Plan

    main

    A ChannelPlan specifies the RF channels, frequencies, and data rates used for uplink and downlink communication. You define a custom plan by subclassing whad.lorawan.channel.ChannelPlan and passing configuration to its constructor.

    Channel Parameters

    Channels (both Uplink and Downlink) require:

    1. Index: The channel index.
    2. Frequency: The frequency in Hz.
    3. Data Rate Index: An index pointing to an entry in the datarates array.

    Data Rate Parameters

    DataRate objects require:

    1. Spreading Factor (sf): A value from 7 to 12.
    2. Bandwidth (bw): Must be 125000, 250000, or 500000.

    RX2 Configuration

    The rx2 parameter allows setting the default second RX window configuration using a Downlink object.

    from whad.lorawan.channel import ChannelPlan, Uplink, Downlink, DataRate
    
    class MyChannelPlan(ChannelPlan):
        def __init__(self):
            super().__init__(
                channels = [
                    # Uplink (index, frequency, datarate_index)
                    Uplink(1, 868100000, 5),
                    # Downlink (index, frequency, datarate_index)
                    Downlink(1, 868100000, 5),
                ],
                datarates = [
                    # DataRate(sf, bw)
                    DataRate(12, 125000),
                    DataRate(11, 125000),
                ],
                # rx2 configuration
                rx2=Downlink(10, 869525000, 0)
            )
  10. Manage layer state with custom LayerState

    main

    Each layer maintains its own state, which is accessible via the self.state property. By default, self.state is an instance of whad.common.stack.LayerState (which behaves like a dictionary with property-based access).

    To implement custom logic for state management (e.g., specialized methods for adding/removing items), create a class inheriting from whad.common.stack.LayerState and associate it with your layer using the @state(YourStateClass) decorator.

    from whad.common.stack import Layer, LayerState, alias, state
    
    class EthernetState(LayerState):
        def __init__(self):
            super().__init__()
            self.macs = []
    
        def add_mac_address(self, mac):
            if mac not in self.macs:
                self.macs.append(mac)
    
    @state(EthernetState)
    @alias('ether')
    class Ethernet(Layer):
        @source('phy')
        def on_packet_received(self, packet):
            # Use custom methods defined in EthernetState
            self.state.add_mac_address(packet.getlayer(Ether).src)
  11. Understand the WHAD communication protocol

    main

    The WHAD protocol uses Protocol Buffers to ensure compact, efficient, and extensible message exchanges between devices and computers.

    Core Design Principles

    • Genericity: The protocol allows the host to discover device capabilities and adapt features accordingly.
    • Extensibility: New wireless protocols or modulations can be added easily while maintaining backward compatibility.
    • Efficiency: Messages are designed to be as compact as possible for high throughput.
    • Stability: Backward compatibility is prioritized to ensure older protocol versions remain supported.

    Detailed protocol specifications are maintained in the dedicated WHAD Protocol documentation.

  12. Write Python extractors for wextract

    main

    Extractors in wextract are passed as positional arguments and must be valid Python expressions.

    Key concepts for writing extractors:

    • The p variable: Every expression has access to p, which is a Scapy packet object. You can use standard Scapy dot notation to access layers and fields (e.g., p.layer_name.field_name).
    • WHAD Metadata: WHAD automatically attaches metadata to packets. This metadata is accessible via the p object (e.g., p.metadata.rssi to access signal strength).
    • Error Handling: If an expression is invalid or an extractor raises an exception, an error message is printed to stderr.