Thursday, 15 October 2015

Advanced WiFi Attacks Using Commodity Hardware

The WiFi protocol assumes all clients behaves fairly. This means a station will give others a chance to transmit packets, before it starts transmitting itself. It's known that with a software defined radio such as a USRP, a user can implement the WiFi protocol themselves and not follow these rules.

 A desktop computer, antenna, two USRPs on top of each other, and a signal analyzer.

An attacker can also use this equipment to create a constant jammer, which continuously transmits noise, and makes the channel completely unusable. In principle an attacker could also turn on a badly shielded microwave to jam the channel :-) However, that doesn't give the attacker control over which frequency is jammed, bandwidth of the emitted noise, nor the emitted noise pattern.

It's even possible to implement a more sophisticated selective jammer. Such a jammer is capable of only jamming specific packets (e.g. only packets sent by a certain device). While it's already known this is possible using expensive hardware such as USRPs, we found that even cheap WiFi dongles can be used to implement all these attacks. It's especially surprising that a selective jammer can be implemented on a cheap WiFi dongle, since it must be fast enough to detect and subsequently jam a packet.

Our attacks were first published at ACSAC 2014 and subsequently demonstrated at BruCON 2015. Additionally our code is available on github! You can also view my presentation at BruCON online.

Selfish Behavior

When a station wants to transmit a packet, but the channel is already in use by another device, it first waits until this transmission is done. Then it waits a random period (called the backoff period), and if no one else starts transmitting during this period, the station may send the packet. We found that it's easy to disable the random backoff period on commodity devices, meaning it will instantly transmit packets. More interestingly, we found that even the original driver and firmware for our device incorrectly calculated the backoff period, giving itself an unfair advantage over other stations! It turns out that many devices do this to gain an unfair advantage:
Over six Wi-Fi cards, neither one performs as expected. In some cases, implementation issues seem to affect the proper card operation. In other cases, manufacturers rely on backoff parameters different from the standard specification, this perhaps being done on purpose to provide an unfair advantage. [Minimized conclusion from this paper]
This raises the question what would happen if there are two stations that both behave selfishly by disabling the backoff period. In other words, what happens if two selfish stations instantly transmit all packets they have queued? You may think that the packets of both selfish stations will collide, and as a result both are lost in the collision. It turns out this is not the case! Due to the capture effect, the packet having the highest signal quality and lowest bitrate will get decoded properly. You can compare this to receiving two radio stations on the same frequency, where generally one station will "win the collision" (see this demo video). This means selfish stations will abuse the capture effect, and reduce their bitrate, in order to win the collision (and have their packet decoded correctly by the receiver). Surprisingly, we now get that selfish clients wanting to maximize their throughput, will reduce their bitrate!

One of our WiFi dongles attached to a Raspberry Pi

There is a research prototype called DOMINO which can detect and punish this type of selfish behavior. Unfortunately we discovered a critical flaw in this system. The problem is that this system bases some of its decisions on unauthenticated packets. As an attacker we can abuse this by forging packets which appear to be sent by a different station. Hence we can make DOMINO believe this client is acting selfishly, meaning it will be punished and thrown off the network. Moral of the story: only base your decisions on authenticated or hard-to-forge data.

Constant Jammer

Our WiFi dongles can also be used to implement a constant jammer. The idea is straightforward: make the radio instantly transmit packets (even if someone else is transmitting), and then send an infinite amount of packets without interruption. The second part is tedious, since we can't queue many packets due to the limited amount of memory available in the WiFi dongle. However, we can simulate an infinite amount of packets. The packets queued for transmission are stored in a linked list. By turning this queue into a circular list we can simulate an infinite amount of packets.

What's interesting here is that in principle the jammer is constantly transmitting valid WiFi packets. However, because they are sent so fast after one another, other WiFi devices are unable to detect these packets. In other words, other WiFi devices operating in monitor mode only see noise, and will not detect/show and show any WiFi traffic.

Selective Jammer

Arguably the most impressive result is that our cheap dongle can be used to implement a selective (also called reactive) jammer. Such a jammer decodes the header of a packet still in the air, and based on information in the header, decides whether to jam the remaining content or not. This is not an easy feat to accomplish. The selective jammer must be fast enough to decode the header, make the decision to jam the packet, put the antenna in transmit mode, and finally jam the packet. All this needs to be done in just a few microseconds (an average WiFi packet takes ~200 microseconds to transmit)!

Jamming the end of the packet is easy, simply inject a packet like we did for the continuous jammer. But there is no support or API to be notified when a packet is in the progress of being received. How do we get around this? The important realization is that there are two chips inside our WiFi device. The first one is the radio which processes the incoming physical signal, and uses Direct Memory Access (DMA) to write the packet to memory. The second chip is the main CPU which is responsible for communicating with the host over USB and controlling the radio chip. Hence we can use the main CPU to constantly monitor the memory where the packet will be saved. Once we detect that the radio chip is writing bytes to this memory location, we know a frame is being received:

When the memory is modified, we know a frame is being received.

With this clever trick we can detect when a frame is being received. Our jammer then reads the MAC address(es) in the header, and compares it to the MAC address of the station we are targeting. If they match, the remaining content of the packet is jammed. This will cause the CRC (called the ICV in WiFi) of the packet to be wrong, meaning the packet will be dropped by the receiver.

The code of the reactive jammer is public, feel free to play around with it (against a test network).

Channel-Based Man-in-the-Middle Attack

As an example, we show how these low-layer attacks can be used to reliably manipulate encrypted traffic. Note that our goal is not to decrypt traffic. Instead, we want to be able to reliably drop, modify, and inject packets. This ability is typically required in order to launch actual (cryptographic) attacks against an higher-layer protocol. Previously when targeting wireless traffic, it was not clear how to do this: there were no known methods to obtain a (reliable) man-in-the-middle position between a client and access point if encryption is used.

In order to intercept (not decrypt) all traffic of an encrypted wireless network, we cannot simply create a rogue Access Point (AP) with a different MAC address. When a client connects to the access point, not only are the credentials verified (e.g. shared password), but also the MAC addresses of the client and access point. Hence the client and AP will detect that an attacker was forwarding packets under different MAC addresses. Setting up a rouge AP with the same mac address as the real AP is futile: the client will simply directly communicate with the real AP (unless they are out of range of each other).

Our solution is to clone the access point on a different channel, but with the same MAC address as the real access point. We forward all frames to the real AP. In other words, we forward packets between both channels. Using the constant jammer we force clients to switch to the channel where our rogue AP is located. Since we did not modify the MAC address of the AP, and also didn't modify the MAC address of the client, the client will successfully connect to the (rogue) AP. We now have a (channel-based) man-in-the-middle position, allowing reliable manipulation of encrypted traffic.

Demonstration of the Channel-Based MiTM attack against WPA-TKIP

The channel-based man-in-the-middle attack can be used to break WPA-TKIP (people commonly, but incorrectly, refer to TKIP as WPA, and EAS-CCMP as WPA2). The TKIP protocol was supposed to be a temporarily replacement of WEP, designed to run on old hardware. Unfortunately, for backwards compatibility, many networks still support both TKIP and the newer EAS-CCMP. If both these protocols are supported, the older TKIP protocol is used to encrypt all broadcast packets. Without going into detail, the channel-based man-in-the-middle allows us to apply existing TKIP attacks to broadcast packets. Hence you should configure your network so only (EAS-)CCMP is enabled!


  1. Would it be possible to send a copy of the source for unfair channel usage & constant jamming implementation? Please contact me on user "theblackrabbit" ( [email protected] )

    Much appreciated!

  2. You can request the code by sending a mail to my KU Leuven email address (you should be able to easily find it). Include a brief explanation why you want to use the constant jammer.

  3. Interesting, it is about time to find a card that has support for 'bpf' in firmware with auto-response (fairly common for 'off-loaded' features like ns, arp while the host/computer is sleeping) and craft a nifty huge response when the address fields match, reduces the whole delay of capturing in monitor mode, inspection on cpu and then sending it back off with TX, have you experimented with disabling csma ? All wifi chips have ED and CS detection thresholds as a 'programmable' configuration.

  4. Amazing writings from you. I have learned a lot from this article. Your videos were also great.

  5. Hi. Many thanks for the work done.
    I try to work with modwifi and it does not work ...

    What equipment do I use:
    1. TLWN722N v.1 + notebook HP, Host Debian jessie + VMware 12.5 + Xubuntu-Modwifi (official image)

    2. TLWN722N v.1 (another adapter, but also v.1 - atheros chip) + PC Asus, Host Windows 7 + VMware 12.5 + Xubuntu-Modwifi

    (official image)

    3. TLWN722N v.1 + notebook HP, Host Debian jessie + Virtualbox + Xubuntu I installed the system with the kernel 4.4 +

    modwifi-4.4-1.tar.gz (installed in the official manual, the drivers (fw) are replaced!)

    In all cases, the situation is identical to each other.
    When connecting (by transferring from the host machine to the guest):

    [ 87.396805] usb 2-1: new full-speed USB device number 2 using uhci_hcd
    [ 88.457141] usb 2-1: New USB device found, idVendor=0e0f, idProduct=0003
    [ 88.457171] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    [ 88.457197] usb 2-1: Product: VMware Virtual USB Mouse
    [ 88.457221] usb 2-1: Manufacturer: VMware
    [ 88.567773] hidraw: raw HID events driver (C) Jiri Kosina
    [ 88.587309] usbcore: registered new interface driver usbhid
    [ 88.587332] usbhid: USB HID core driver
    [ 88.590842] usb 2-2: new full-speed USB device number 3 using uhci_hcd
    [ 88.603026] input: VMware VMware Virtual USB Mouse as /devices/pci0000:00/0000:00:11.0/0000:02:00.0/usb2/2-1/2-

    [ 88.613990] hid-generic 0003:0E0F:0003.0001: input,hidraw0: USB HID v1.10 Mouse [VMware VMware Virtual USB Mouse] on

    [ 88.731601] usb 2-2: New USB device found, idVendor=0e0f, idProduct=0002
    [ 88.731610] usb 2-2: New USB device strings: Mfr=0, Product=1, SerialNumber=0
    [ 88.731614] usb 2-2: Product: VMware Virtual USB Hub
    [ 88.740782] hub 2-2:1.0: USB hub found
    [ 88.742689] hub 2-2:1.0: 7 ports detected
    [ 1264.563100] usb 1-1: new high-speed USB device number 6 using ehci-pci
    [ 1264.898240] usb 1-1: New USB device found, idVendor=0cf3, idProduct=9271
    [ 1264.898269] usb 1-1: New USB device strings: Mfr=16, Product=32, SerialNumber=48
    [ 1264.898308] usb 1-1: Product: USB2.0 WLAN
    [ 1264.898334] usb 1-1: Manufacturer: ATHEROS
    [ 1264.898358] usb 1-1: SerialNumber: 12345
    [ 1264.916641] usb 1-1: ath9k_htc: Firmware htc_9271.fw requested
    [ 1265.269131] usb 1-1: ath9k_htc: Transferred FW: htc_9271.fw, size: 51040
    [ 1265.545357] ath9k_htc 1-1:1.0: ath9k_htc: HTC initialized with 33 credits
    [ 1266.457978] ath9k_htc 1-1:1.0: ath9k_htc: FW Version: 1.4
    [ 1266.458102] ath: EEPROM regdomain: 0x809c
    [ 1266.458123] ath: EEPROM indicates we should expect a country code
    [ 1266.458174] ath: doing EEPROM country->regdmn map search
    [ 1266.458201] ath: country maps to regdmn code: 0x52
    [ 1266.458240] ath: Country alpha2 being used: CN
    [ 1266.458252] ath: Regpair used: 0x52
    [ 1266.543701] ieee80211 phy0: Atheros AR9271 Rev:1
    [ 1266.543942] cfg80211: Calling CRDA for country: CN
    [ 1266.548917] systemd-udevd[2725]: renamed network interface wlan0 to wlan1
    [ 1266.562933] IPv6: ADDRCONF(NETDEV_UP): wlan1: link is not ready
    [ 1266.681207] cfg80211: Regulatory domain changed to country: CN
    [ 1266.681247] cfg80211: DFS Master region: unset
    [ 1266.681384] cfg80211: (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)
    [ 1266.681445] cfg80211: (2402000 KHz - 2482000 KHz @ 40000 KHz), (N/A, 2000 mBm), (N/A)
    [ 1266.681453] cfg80211: (5735000 KHz - 5835000 KHz @ 40000 KHz), (N/A, 3000 mBm), (N/A)
    [ 1266.681454] cfg80211: (57240000 KHz - 59400000 KHz @ 2160000 KHz), (N/A, 2800 mBm), (N/A)
    [ 1266.681455] cfg80211: (59400000 KHz - 63720000 KHz @ 2160000 KHz), (N/A, 4400 mBm), (N/A)
    [ 1266.681457] cfg80211: (63720000 KHz - 65880000 KHz @ 2160000 KHz), (N/A, 2800 mBm), (N/A)

  6. [email protected]:~/modwifi/tools$ sudo rfkill unblock wifi
    [sudo] password for modwifi:
    [email protected]:~/modwifi/tools$ sudo iw wlan1 set type monitor
    [email protected]:~/modwifi/tools$ sudo ifconfig wlan1 up
    [email protected]:~/modwifi/tools$ sudo iw wlan1 set channel 11
    [email protected]:~/modwifi/tools$ sudo ./reactivejam -i wlan1 -s "dom"
    Jamming 02:1b:11:76:5c:80 SSID dom

    >> Press CTRL+C to exit <<

    =========== JAMMING =============
    =========== JAMMING =============
    =========== JAMMING =============

    Determined the MAC AP correctly!
    At this time in the second terminal:

    [ 1568.321135] ath9k_htc: Reactively jamming 2:1b:11:76:5c:80 for 30000 miliseconds
    [ 1598.217716] ath9k_htc: Reactively jamming 2:1b:11:76:5c:80 for 30000 miliseconds
    [ 1628.110949] ath9k_htc: Reactively jamming 2:1b:11:76:5c:80 for 30000 miliseconds
    [ 1658.003324] ath9k_htc: Reactively jamming 2:1b:11:76:5c:80 for 30000 miliseconds
    [ 1687.906342] ath9k_htc: Reactively jamming 2:1b:11:76:5c:80 for 30000 miliseconds
    [ 1717.805230] ath9k_htc: Reactively jamming 2:1b:11:76:5c:80 for 30000 miliseconds

    [email protected]:~/modwifi/tools$ ip -s link ls wlan1
    3: wlan1: mtu 1500 qdisc mq state UNKNOWN mode DEFAULT group default

    qlen 1000
    link/ieee802.11/radiotap 14:cc:20:19:38:cc brd ff:ff:ff:ff:ff:ff
    RX: bytes packets errors dropped overrun mcast
    732832 1618 0 1604 0 0
    TX: bytes packets errors dropped carrier collsns
    0 0 0 0 0 0
    [email protected]:~/modwifi/tools$

    The TX statistics remain equal to 0.
    The access point continues to work successfully.
    Jamming not work :(

    1. Hi yar1k,

      Some general remarks.

      First, the reactive jammer only targets beacons. Missed beacons will not show up in the TX statistics. I also doubt they will show up in the RX statistics.

      Second, the jammer should be physically close to the victim, and the access point should be relatively far away. This is to assure the jammer can overpower the signal of the access point (in reference to the victim).

      Finally, to confirm if the reactive jammer is working, I recommend using another WiFi interface. Put it in monitor mode, and right next to the victim. Then see whether beacons are received or corrupted.

      - Mathy