I just reviewed a paper that claimed that reactive jamming of ZigBee would only be possible with sophisticated devices that cost over $3000. First of all, there was already a paper in 2011, which implemented a reactive ZigBee jammer by modifying the FPGA of a USRP2 SDR [1]. But I also just bought a$40 ATUSB ZigBee USB dongle from Sysmocom

The ATUSB is completely Open Source (drivers, firmware, and schematics) and has native Linux support. I already blogged about jamming WiFi ACKs with modified WLAN firmware. This was based on Mathy Vanhoef’s work, who modified the Atheros ath9k_htc firmware [2].

So I wanted to implement a similar jammer for ZigBee.

## Step 1: Setup

Since the device is supported by Linux, we only need the user space tools. On Ubuntu they are in the wpan-tools package. Using these tool, we can put the ATUSB in monitor mode with something like:

  sudo iwpan dev wpan0 del
sudo iwpan phy phy0 interface add monitor0 type monitor
sudo ifconfig monitor0 up
sudo iwpan phy phy0 set channel 0 24


Now, we could, for example, listen to the monitor0 interface with Wireshark and sniff ZigBee traffic. (I also deleted the normal wpan interface to make sure that the Linux ZigBee stack does not interfere. I was not sure whether this would cause problems when modifying the firmware for jamming.)

## Step 2: Preliminaries

The ATUSB uses an Atmega32U2 microcontroller with an AT86RF231 ZigBee transceiver. An interesting feature of the AT86RF231 is that it supports high accuracy receive time stamping by issuing an RX_START interrupt when the device syncs on a frame. This can be done through a dedicated pin, which is unfortunately not connected on the ATUSB. Yet, the interrupt can also be received through the usual interrupt mechanism between RF chip and microcontroller.

It works as follows:

• The microcontroller enables the interrupts that it is interested in through the interrupt mask.
• To signal the interrupt, the transceiver toggles the IRQ pin.
• Once the microcontroller notices the interrupt, it reads the interrupt register through SPI (which also clears the register).

This way the single interrupt line can be used to signal multiple events like frame start, finished TX, and ACK received.

The goal is now to detect the RX_START interrupt and force the AT86RF231 to transmit something ASAP. The main questions are: (1) can this be done fast enough and (2) can we force the AT86RF231 to transmit even though the channel is busy.

The latter should be possible, since ZigBee (or actually IEEE 802.15.4) can use two operational modes. The usual CSMA/CA base channel access (where the frame is sent only if the channel is free) and a contention free channel access (where the device has fixed slots allocated). To support the second mode, it should be possible to send frames without CCA.

## Step 3: Modify the Firmware

The firmware of the ATUSB is available on GitHub. To compile it, one needs the AVR toolchain:

  sudo apt install avr-libc gcc-avr binutils-avr


Furthermore, flashing the firmware requires an older version (v0.7) of dfu-util. The one in the Ubuntu repositories is too recent, so it has to be compiled from source. It is available here.

After installing dfu-util and the toolchain, the firmware can be compiled and flashed with

  cd atusb/fw
make
make dfu


## Step 4: Jamming

As it turns out, jamming is rather straight forward to implement. We can just extend the interrupt service routine (ISR) and check whether we are notified about the start of the reception process. If this is the case, we use the FORCE_PLL_ON command to enter the PLL_ON state, from which we can trigger a transmission.

The only thing I did before actually triggering the transmission was to define the size of the interfering frame. The transceiver has an internal buffer for a maximum sized frame. Since we don’t care about the payload, we just set the size and the transceiver will send whatever is in the buffer.

Finally, transmission is triggered with slp_tr(), which sets (and then clears) an IO pin that is directly connected to the transceiver. Afterwards, we switch back to receive mode.

  ISR(INT0_vect)
{
if(irq == IRQ_RX_START) {
reg_write(REG_TRX_STATE, TRX_CMD_FORCE_PLL_ON);

spi_begin();
spi_send(AT86RF230_BUF_WRITE);
spi_send(17); // length of jam frame
spi_end();

slp_tr();

change_state(TRX_CMD_RX_ON);
return;
}
[...]
}


I didn’t have another ZigBee device at hand, so I used my GNU Radio IEEE 802.15.4 transceiver to send ZigBee frames with a HackRF. To check if jamming works, I used a Pluto SDR to monitor the channel.

I recorded a video that first shows the ZigBee frames, which are sent nearly back-to-back. Then, after some time, the monitor0 interface (i.e., the ATUSB dongle) is enabled and the frames get jammed.

To better show the timing, I sent rather short jamming pulses. However, the length can be changed with the above spi_send() call as annotated in the listing. It seems to work rather reliably and can deal with high frame rates.

## Selective Jamming

The AT86RF231 has another very interesting feature. Apart from the RX_START interrupt, it can be configured to also issue an address match interrupt (AMI). The actual intention is to notify the receiver only about frames targeted to this particular device. When an address is configured, this interrupt is raised immediately after the MAC header is received. Subscribing to this interrupt, we can even jam one selected device.

## References

1. Matthias Wilhelm, Ivan Martinovic, Jens B. Schmitt and Vincent Lenders, “Short Paper: Reactive Jamming in Wireless Networks – How Realistic is the Threat?,” Proceedings of 4th ACM Conference on Wireless Network Security (WiSec 2011), Hamburg, Germany, June 2011, pp. 47–52. [DOI, BibTeX, Details…]

2. Mathy Vanhoef and Frank Piessens, “Advanced Wi-Fi Attacks Using Commodity Hardware,” Proceedings of 30th Annual Computer Security Applications Conference (ACSAC 2014), New Orleans, LA, Dec 2014, pp. 256-265. [DOI, BibTeX, PDF and Details…]