1a6085186SLina Ceballos<!-- 2a2a0d4bdSXianjun JiaoAuthor: Michael Mehari, Xianjun Jiao 3ea75aaf6SJiao XianjunSPDX-FileCopyrightText: 2019 UGent 4a6085186SLina CeballosSPDX-License-Identifier: AGPL-3.0-or-later 5a6085186SLina Ceballos--> 67273ec43Smmehari 7a2a0d4bdSXianjun Jiao## 802.11 packet injection and fuzzing 87273ec43Smmehari 9a2a0d4bdSXianjun JiaoThe Linux wireless networking stack (i.e. driver, mac80211, cfg80211, net_dev, user app) is a robust implementation supporting a plethora of wireless devices. As robust as it is, it also has a drawback when it comes to single-layer testing and manual/total control mode (fuzzing). 107273ec43Smmehari 117273ec43SmmehariPing and Iperf are well established performance measurement tools. However, using such tools to measure 802.11 PHY performance can be misleading, simply because they touch multiple layers in the network stack. 127273ec43Smmehari 13a2a0d4bdSXianjun JiaoLuckily, the mac80211 Linux subsystem provides packet injection functionality when the NIC is in the monitor mode and it allows us to have finer control for physical layer testing and/or fuzzing. 147273ec43Smmehari 15a2a0d4bdSXianjun JiaoBesides the traditional fuzzing tool (like scapy), we have adapted a [packetspammer](https://github.com/gnychis/packetspammer) application, which is originally written by Andy Green <[email protected]> and maintained by George Nychis <[email protected]>, to show how to inject packets and control the FPGA behavior. 167273ec43Smmehari 17fdbf6a5aSJiao Xianjun### Build inject_80211 on board 187273ec43SmmehariUserspace program to inject 802.11 packets through mac80211 supported (softmac) wireless devices. 197273ec43Smmehari 204ec04889SJiao XianjunLogin/ssh to the board and setup internet connection according to the Quick Start. Then 21fdbf6a5aSJiao Xianjun``` 22fdbf6a5aSJiao Xianjuncd openwifi/inject_80211 23fdbf6a5aSJiao Xianjunmake 24fdbf6a5aSJiao Xianjun``` 25a2a0d4bdSXianjun Jiao### Customize the packet content 26a2a0d4bdSXianjun JiaoTo customize the packet, following piece of the inject_80211.c needs to be changed: 27a2a0d4bdSXianjun Jiao``` 28a2a0d4bdSXianjun Jiao/* IEEE80211 header */ 29*90a96182SXianjun Jiaostatic u8 ieee_hdr_data[] = 30a2a0d4bdSXianjun Jiao{ 31*90a96182SXianjun Jiao 0x08, 0x02, 0x00, 0x00, 32*90a96182SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 33*90a96182SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x22, 34*90a96182SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x33, 35*90a96182SXianjun Jiao 0x10, 0x86, 36*90a96182SXianjun Jiao}; 37*90a96182SXianjun Jiao 38*90a96182SXianjun Jiaostatic u8 ieee_hdr_mgmt[] = 39*90a96182SXianjun Jiao{ 40*90a96182SXianjun Jiao 0x00, 0x00, 0x00, 0x00, 41*90a96182SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 42*90a96182SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x22, 43*90a96182SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x33, 44*90a96182SXianjun Jiao 0x10, 0x86, 45*90a96182SXianjun Jiao}; 46*90a96182SXianjun Jiao 47*90a96182SXianjun Jiaostatic u8 ieee_hdr_ack_cts[] = 48*90a96182SXianjun Jiao{ 49*90a96182SXianjun Jiao 0xd4, 0x00, 0x00, 0x00, 50*90a96182SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 51*90a96182SXianjun Jiao}; 52*90a96182SXianjun Jiao 53*90a96182SXianjun Jiaostatic u8 ieee_hdr_rts[] = 54*90a96182SXianjun Jiao{ 55*90a96182SXianjun Jiao 0xb4, 0x00, 0x00, 0x00, 56*90a96182SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 57*90a96182SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x22, 58a2a0d4bdSXianjun Jiao}; 59a2a0d4bdSXianjun Jiao``` 60a2a0d4bdSXianjun JiaoNote: The byte/bit order might not be intuitive when comparing with the standard. 61a2a0d4bdSXianjun Jiao 62a2a0d4bdSXianjun Jiao### FPGA behavior control 63a2a0d4bdSXianjun Jiao- ACK and retransmission after FPGA sends packet 64a2a0d4bdSXianjun Jiao 65a2a0d4bdSXianjun JiaoIn openwifi_tx of sdr.c, many FPGA behaviors can be controled. Generally they are controled by the information from upper layer (Linux mac80211), but you can override them in driver (sdr.c) 66a2a0d4bdSXianjun Jiao 67a2a0d4bdSXianjun JiaoIf 802.11 ACK is expected from the peer after the packet is sent by FPGA, variable **pkt_need_ack** should be overridden to 1. In this case, the FPGA will try to receive ACK, and report the sending status (ACK is received or not) to upper layer (Linux mac80211) 68a2a0d4bdSXianjun Jiao 69a2a0d4bdSXianjun JiaoThe maximum times of transmission for the packet can be controled by variable **retry_limit_raw**. If no ACK is received after the packet is sent, FPGA will try retransmissions automatically if retry_limit_raw>1. 70a2a0d4bdSXianjun Jiao 71a2a0d4bdSXianjun Jiao- ACK after FPGA receives packet in monitor mode 72a2a0d4bdSXianjun Jiao 73a2a0d4bdSXianjun JiaoEven in monitor mode, openwifi FPGA still sends ACK after the packet is received, if the conditions are met: MAC address is matched, it is a data frame, etc. To disable this automatic ACK generation, the register 11 of xpu should be set to 16: 74a2a0d4bdSXianjun Jiao``` 75a2a0d4bdSXianjun Jiaosdrctl dev sdr0 set reg xpu 11 16 76a2a0d4bdSXianjun Jiao``` 77fdbf6a5aSJiao Xianjun 7810ae6518SJiao Xianjun### Options of program inject_80211 797273ec43Smmehari``` 807273ec43Smmehari-m/--hw_mode <hardware operation mode> (a,g,n) 817273ec43Smmehari-r/--rate_index <rate/MCS index> (0,1,2,3,4,5,6,7) 82*90a96182SXianjun Jiao-t/--packet_type (m/c/d/r for management/control/data/reserved) 83*90a96182SXianjun Jiao-e/--sub_type (hex value. example: 84*90a96182SXianjun Jiao 8/A/B/C for Beacon/Disassociation/Authentication/Deauth, when packet_type m 85*90a96182SXianjun Jiao A/B/C/D for PS-Poll/RTS/CTS/ACK, when packet_type c 86*90a96182SXianjun Jiao 0/1/2/8 for Data/Data+CF-Ack/Data+CF-Poll/QoS-Data, when packet_type d) 87*90a96182SXianjun Jiao-a/--addr1 <the last byte of addr1 in hex> 88*90a96182SXianjun Jiao-b/--addr2 <the last byte of addr2 in hex> 897273ec43Smmehari-i/--sgi_flag (0,1) 907273ec43Smmehari-n/--num_packets <number of packets> 917273ec43Smmehari-s/--payload_size <payload size in bytes> 927273ec43Smmehari-d/--delay <delay between packets in usec> 937273ec43Smmehari-h this menu 947273ec43Smmehari``` 957273ec43Smmehari 967273ec43Smmehari### Example: 9764ce2ec9SJiao XianjunLogin/ssh to the board, Then 987273ec43Smmehari``` 9964ce2ec9SJiao Xianjuncd openwifi 10064ce2ec9SJiao Xianjun./wgd.sh 10164ce2ec9SJiao Xianjun./monitor_ch.sh sdr0 11 102e42aed84SJiao Xianjun(Above will turn sdr0 into the monitor mode and monitor on channel 11) 1036681d84fSXianjun Jiao./inject_80211/inject_80211 -m n -r 0 -n 10 -s 64 sdr0 104e42aed84SJiao Xianjun(Above will inject 10 802.11n packets at 6.5Mbps bitrate and 64bytes size via NIC sdr0) 10564ce2ec9SJiao Xianjun``` 106e42aed84SJiao XianjunWhen above injection command is running, you could see the injected packets with wireshark (or other packet sniffer) on another WiFi device monitoring channel 11. 107e42aed84SJiao Xianjun 10864ce2ec9SJiao XianjunOr add extra virtual monitor interface on top of sdr0, and inject packets: 10964ce2ec9SJiao Xianjun``` 11064ce2ec9SJiao Xianjuniw dev sdr0 interface add mon0 type monitor && ifconfig mon0 up 1116681d84fSXianjun Jiao./inject_80211/inject_80211 -m n -r 0 -n 10 -s 64 mon0 # Inject 10 802.11n packets at 6.5Mbps bitrate and 64bytes size 1127273ec43Smmehari``` 1137273ec43Smmehari 1147273ec43Smmehari### Link performance test 1157273ec43Smmehari 1167273ec43SmmehariTo make a profound experimental analysis on the physical layer performance, we can rely on automation scripts. 1177273ec43Smmehari 1187273ec43SmmehariThe following script will inject 100 802.11n packets at different bitrates and payload sizes. 1197273ec43Smmehari 1207273ec43Smmehari``` 1217273ec43Smmehari#!/bin/bash 1227273ec43Smmehari 1237273ec43SmmehariHW_MODE='n' 1247273ec43SmmehariCOUNT=100 1257273ec43SmmehariDELAY=1000 1267273ec43SmmehariRATE=( 0 1 2 3 4 5 6 7 ) 1277273ec43SmmehariSIZE=( $(seq -s' ' 50 100 1450) ) # paload size in bytes 1287273ec43SmmehariIF="mon0" 1297273ec43Smmehari 1307273ec43Smmeharifor (( i = 0 ; i < ${#PAYLOAD[@]} ; i++ )) do 1317273ec43Smmehari for (( j = 0 ; j < ${#RATE[@]} ; j++ )) do 1327273ec43Smmehari inject_80211 -m $HW_MODE -n $COUNT -d $DELAY -r ${RATE[$j]} -s ${SIZE[$i]} $IF 1337273ec43Smmehari sleep 1 1347273ec43Smmehari done 1357273ec43Smmeharidone 1367273ec43Smmehari 1377273ec43Smmehari``` 1387273ec43Smmehari 1397273ec43SmmehariOn the receiver side, we can use tcpdump to collect the pcap traces. 1407273ec43Smmehari 1417273ec43Smmehari``` 142a2a0d4bdSXianjun Jiaoiw dev sdr0 interface add mon0 type monitor && ifconfig mon0 up 1437273ec43Smmeharitcpdump -i mon0 -w trace.pcap 'wlan addr1 ff:ff:ff:ff:ff:ff and wlan addr2 66:55:44:33:22:11' 1447273ec43Smmehari``` 1457273ec43Smmehari 1467273ec43SmmehariWlan addresses *ff:ff:ff:ff:ff:ff* and *66:55:44:33:22:11* are specific to our injector application. 1477273ec43Smmehari 1487273ec43SmmehariNext, we analyze the collected pcap traces using the analysis tool provided. 1497273ec43Smmehari 1507273ec43Smmehari``` 1517273ec43Smmeharianalyze_80211 trace.pcap 1527273ec43Smmehari``` 1537273ec43Smmehari 1547273ec43SmmehariAn excerpt from a sample analysis looks the following 1557273ec43Smmehari 1567273ec43Smmehari``` 1577273ec43SmmehariHW MODE RATE(Mbps) SGI SIZE(bytes) COUNT Duration(sec) 1587273ec43Smmehari======= ========== === =========== ===== ============= 1597273ec43Smmehari802.11n 6.5 OFF 54 100 0.11159 1607273ec43Smmehari802.11n 13.0 OFF 54 100 0.11264 1617273ec43Smmehari802.11n 19.5 OFF 54 100 0.11156 1627273ec43Smmehari802.11n 26.0 OFF 54 100 0.11268 1637273ec43Smmehari802.11n 39.0 OFF 54 100 0.11333 1647273ec43Smmehari802.11n 52.0 OFF 54 100 0.11149 1657273ec43Smmehari802.11n 58.5 OFF 54 100 0.11469 1667273ec43Smmehari802.11n 65.0 OFF 54 100 0.11408 1677273ec43Smmehari``` 1687273ec43Smmehari 169