1 // Modified by: Michael Mehari 2 // SPDX-FileCopyrightText: 2020 UGent 3 // SPDX-FileCopyrightText: 2007 Andy Green <[email protected]> 4 // SPDX-License-Identifier: GPL-2.0-or-later 5 6 /* 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; version 2. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 */ 20 21 // Thanks for contributions: 22 // 2007-03-15 fixes to getopt_long code by Matteo Croce [email protected] 23 24 #include "inject_80211.h" 25 #include "radiotap.h" 26 27 #define BUF_SIZE_MAX (1536) 28 #define BUF_SIZE_TOTAL (BUF_SIZE_MAX+1) // +1 in case the sprintf insert the last 0 29 30 /* wifi bitrate to use in 500kHz units */ 31 static const u8 u8aRatesToUse[] = { 32 6*2, 33 9*2, 34 12*2, 35 18*2, 36 24*2, 37 36*2, 38 48*2, 39 54*2 40 }; 41 42 /* this is the template radiotap header we send packets out with */ 43 static const u8 u8aRadiotapHeader[] = 44 { 45 0x00, 0x00, // <-- radiotap version 46 0x1c, 0x00, // <- radiotap header length 47 0x6f, 0x08, 0x08, 0x00, // <-- bitmap 48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <-- timestamp 49 0x00, // <-- flags (Offset +0x10) 50 0x6c, // <-- rate (0ffset +0x11) 51 0x71, 0x09, 0xc0, 0x00, // <-- channel 52 0xde, // <-- antsignal 53 0x00, // <-- antnoise 54 0x01, // <-- antenna 55 0x02, 0x00, 0x0f, // <-- MCS 56 }; 57 58 #define OFFSET_RATE 0x11 59 #define MCS_OFFSET 0x19 60 #define GI_OFFSET 0x1a 61 #define MCS_RATE_OFFSET 0x1b 62 63 /* IEEE80211 header */ 64 static u8 ieee_hdr_data[] = 65 { 66 0x08, 0x02, 0x00, 0x00, // FC 0x0801. 0--subtype; 8--type&version; 02--toDS0 fromDS1 (data packet from DS to STA) 67 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // BSSID/MAC of AP 68 0x66, 0x55, 0x44, 0x33, 0x22, 0x22, // Source address (STA) 69 0x66, 0x55, 0x44, 0x33, 0x22, 0x33, // Destination address (another STA under the same AP) 70 0x10, 0x86, // 0--fragment number; 0x861=2145--sequence number 71 }; 72 73 static u8 ieee_hdr_mgmt[] = 74 { 75 0x00, 0x00, 0x00, 0x00, // FC 0x0000. 0--subtype; 0--type&version; 76 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // BSSID/MAC of AP 77 0x66, 0x55, 0x44, 0x33, 0x22, 0x22, // Source address (STA) 78 0x66, 0x55, 0x44, 0x33, 0x22, 0x33, // Destination address (another STA under the same AP) 79 0x10, 0x86, // 0--fragment number; 0x861=2145--sequence number 80 }; 81 82 static u8 ieee_hdr_ack_cts[] = 83 { 84 0xd4, 0x00, 0x00, 0x00, // FC 0xd400. d--subtype; 4--type&version; 85 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // mac addr of the peer 86 }; 87 88 static u8 ieee_hdr_rts[] = 89 { 90 0xb4, 0x00, 0x00, 0x00, // FC 0xb400. b--subtype; 4--type&version; 91 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // mac addr of the peer 92 0x66, 0x55, 0x44, 0x33, 0x22, 0x22, // mac addr of the peer 93 }; 94 95 // Generate random string 96 void gen_rand_str(int size, char *rand_char) 97 { 98 int i, randNum = 0; 99 100 // Seed the random number generator with packet size 101 srand(size); 102 for (i = 0; i < size; i++) 103 { 104 // First, pick a number between 0 and 25. 105 randNum = 255 * (rand() / (RAND_MAX + 1.0)); 106 107 if(randNum == 0) 108 { 109 i--; 110 continue; 111 } 112 113 // Type cast to character 114 rand_char[i] = (char) randNum; 115 } 116 rand_char[i] = '\0'; 117 } 118 119 int flagHelp = 0; 120 121 void usage(void) 122 { 123 printf( 124 "(c)2006-2007 Andy Green <[email protected]> Licensed under GPL2\n" 125 "(r)2020 Michael Tetemke Mehari <[email protected]>\n" 126 "(r)2022 Xianjun Jiao <[email protected]>" 127 "\n" 128 "Usage: inject_80211 [options] <interface>\n\nOptions\n" 129 "-m/--hw_mode <hardware operation mode> (a,g,n)\n" 130 "-r/--rate_index <rate/MCS index> (0,1,2,3,4,5,6,7)\n" 131 "-t/--packet_type (m/c/d/r for management/control/data/reserved)\n" 132 "-e/--sub_type (hex value. example:\n" 133 " 8/A/B/C for Beacon/Disassociation/Authentication/Deauth, when packet_type m\n" 134 " A/B/C/D for PS-Poll/RTS/CTS/ACK, when packet_type c\n" 135 " 0/1/2/8 for Data/Data+CF-Ack/Data+CF-Poll/QoS-Data, when packet_type d)\n" 136 "-a/--addr1 <the last byte of addr1 in hex>\n" 137 "-b/--addr2 <the last byte of addr2 in hex>\n" 138 "-i/--sgi_flag (0,1)\n" 139 "-n/--num_packets <number of packets>\n" 140 "-s/--payload_size <payload size in bytes>\n" 141 "-d/--delay <delay between packets in usec>\n" 142 "-h this menu\n\n" 143 144 "Example:\n" 145 " iw dev wlan0 interface add mon0 type monitor && ifconfig mon0 up\n" 146 " inject_80211 mon0\n" 147 "\n"); 148 exit(1); 149 } 150 151 152 int main(int argc, char *argv[]) 153 { 154 u8 buffer[BUF_SIZE_TOTAL], addr1=1, addr2=2, sub_type=1, *ieee_hdr; 155 char szErrbuf[PCAP_ERRBUF_SIZE], rand_char[1484], hw_mode = 'n', packet_type = 'd'; 156 int i, nLinkEncap = 0, r, rate_index = 0, sgi_flag = 0, num_packets = 10, payload_size = 64, packet_size, nDelay = 100000; 157 int ieee_hdr_len, payload_len; 158 pcap_t *ppcap = NULL; 159 160 while (1) 161 { 162 int nOptionIndex; 163 static const struct option optiona[] = 164 { 165 { "hw_mode", required_argument, NULL, 'm' }, 166 { "rate_index", required_argument, NULL, 'r' }, 167 { "packet_type", required_argument, NULL, 't' }, 168 { "sub_type", required_argument, NULL, 'e' }, 169 { "addr1", required_argument, NULL, 'a' }, 170 { "addr2", required_argument, NULL, 'b' }, 171 { "sgi_flag", no_argument, NULL, 'i' }, 172 { "num_packets", required_argument, NULL, 'n' }, 173 { "payload_size", required_argument, NULL, 's' }, 174 { "delay", required_argument, NULL, 'd' }, 175 { "help", no_argument, &flagHelp, 1 }, 176 { 0, 0, 0, 0 } 177 }; 178 int c = getopt_long(argc, argv, "m:r:t:e:a:b:i:n:s:d:h", optiona, &nOptionIndex); 179 180 if (c == -1) 181 break; 182 switch (c) 183 { 184 case 0: // long option 185 break; 186 187 case 'h': 188 usage(); 189 190 case 'm': 191 hw_mode = optarg[0]; 192 break; 193 194 case 'r': 195 rate_index = atoi(optarg); 196 break; 197 198 case 't': 199 packet_type = optarg[0]; 200 break; 201 202 case 'e': 203 sub_type = strtol(optarg, NULL, 16); 204 break; 205 206 case 'a': 207 addr1 = strtol(optarg, NULL, 16); 208 break; 209 210 case 'b': 211 addr2 = strtol(optarg, NULL, 16); 212 break; 213 214 case 'i': 215 sgi_flag = atoi(optarg); 216 break; 217 218 case 'n': 219 num_packets = atoi(optarg); 220 break; 221 222 case 's': 223 payload_size = atoi(optarg); 224 break; 225 226 case 'd': 227 nDelay = atoi(optarg); 228 break; 229 230 default: 231 printf("unknown switch %c\n", c); 232 usage(); 233 break; 234 } 235 } 236 237 if (optind >= argc) 238 usage(); 239 240 // open the interface in pcap 241 szErrbuf[0] = '\0'; 242 ppcap = pcap_open_live(argv[optind], 800, 1, 20, szErrbuf); 243 if (ppcap == NULL) 244 { 245 printf("Unable to open interface %s in pcap: %s\n", argv[optind], szErrbuf); 246 return (1); 247 } 248 249 nLinkEncap = pcap_datalink(ppcap); 250 switch (nLinkEncap) 251 { 252 case DLT_PRISM_HEADER: 253 printf("DLT_PRISM_HEADER Encap\n"); 254 break; 255 256 case DLT_IEEE802_11_RADIO: 257 printf("DLT_IEEE802_11_RADIO Encap\n"); 258 break; 259 260 default: 261 printf("!!! unknown encapsulation on %s !\n", argv[1]); 262 return (1); 263 } 264 265 pcap_setnonblock(ppcap, 1, szErrbuf); 266 267 // Fill the IEEE hdr 268 if (packet_type == 'd') // data packet 269 { 270 ieee_hdr_data[0] = ( ieee_hdr_data[0]|(sub_type<<4) ); 271 ieee_hdr_data[9] = addr1; 272 ieee_hdr_data[15] = addr2; 273 ieee_hdr_len = sizeof(ieee_hdr_data); 274 ieee_hdr = ieee_hdr_data; 275 } 276 else if (packet_type == 'm') // managment packet 277 { 278 ieee_hdr_mgmt[0] = ( ieee_hdr_mgmt[0]|(sub_type<<4) ); 279 ieee_hdr_mgmt[9] = addr1; 280 ieee_hdr_mgmt[15] = addr2; 281 ieee_hdr_len = sizeof(ieee_hdr_mgmt); 282 ieee_hdr = ieee_hdr_mgmt; 283 } 284 else if (packet_type == 'c') 285 { 286 payload_size = 0; 287 if (sub_type == 0xC || sub_type == 0xD) 288 { 289 ieee_hdr_ack_cts[0] = ( ieee_hdr_ack_cts[0]|(sub_type<<4) ); 290 ieee_hdr_ack_cts[9] = addr1; 291 ieee_hdr_len = sizeof(ieee_hdr_ack_cts); 292 ieee_hdr = ieee_hdr_ack_cts; 293 } 294 else if (sub_type == 0xA || sub_type == 0xB) 295 { 296 ieee_hdr_rts[0] = ( ieee_hdr_rts[0]|(sub_type<<4) ); 297 ieee_hdr_rts[9] = addr1; 298 ieee_hdr_rts[15] = addr2; 299 ieee_hdr_len = sizeof(ieee_hdr_rts); 300 ieee_hdr = ieee_hdr_rts; 301 } 302 else 303 { 304 printf("!!! sub_type %x is not supported yet!\n", sub_type); 305 return (1); 306 } 307 } 308 else 309 { 310 printf("!!! packet_type %c is not supported yet!\n", packet_type); 311 return (1); 312 } 313 314 // Generate random string 315 gen_rand_str(payload_size+4, rand_char); //4 for space reserved for crc 316 payload_len = strlen(rand_char); 317 318 packet_size = sizeof(u8aRadiotapHeader) + ieee_hdr_len + payload_len; 319 printf("mode = 802.11%c, rate index = %d, SHORT GI = %d, number of packets = %d and packet size = %d bytes, delay = %d usec\n", hw_mode, rate_index, sgi_flag, num_packets, packet_size, nDelay); 320 printf("packet_type %c sub_type %x payload_len %d ieee_hdr_len %d addr1 %02x addr2 %02x\n", packet_type, sub_type, payload_len, ieee_hdr_len, addr1, addr2); 321 322 if (packet_size > BUF_SIZE_MAX) { 323 printf("packet_size %d > %d! Quite\n", packet_size, BUF_SIZE_MAX); 324 return(1); 325 } 326 327 // Clear storage buffer 328 memset(buffer, 0, sizeof (buffer)); 329 330 // Insert default radiotap header 331 memcpy(buffer, u8aRadiotapHeader, sizeof (u8aRadiotapHeader)); 332 // Update radiotap header (i.e. hw_mode, rate, GI) 333 if(hw_mode == 'g' || hw_mode == 'a') 334 { 335 buffer[OFFSET_RATE] = u8aRatesToUse[rate_index]; 336 buffer[MCS_OFFSET] = 0x00; 337 } 338 else 339 { 340 buffer[MCS_OFFSET] = 0x07; 341 if(sgi_flag) 342 buffer[GI_OFFSET] = IEEE80211_RADIOTAP_MCS_SGI; 343 buffer[MCS_RATE_OFFSET] = rate_index; 344 } 345 // Insert IEEE DATA header 346 memcpy(buffer + sizeof(u8aRadiotapHeader), ieee_hdr, ieee_hdr_len); 347 // Insert IEEE DATA payload 348 sprintf((char *)(buffer + sizeof(u8aRadiotapHeader) + ieee_hdr_len), "%s", rand_char); 349 350 // Inject packets 351 for(i = 1; i <= num_packets; i++) 352 { 353 r = pcap_inject(ppcap, buffer, packet_size); 354 if (r != packet_size) { 355 perror("Trouble injecting packet"); 356 return (1); 357 } 358 359 printf("number of packets sent = %d\r", i); 360 fflush(stdout); 361 362 if (nDelay) 363 usleep(nDelay); 364 } 365 366 printf("\n"); 367 368 return (0); 369 } 370