From 80f7774e9839bfca77ad53eee5f4a72362a3dd56 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Mon, 9 Oct 2017 00:07:08 +0100 Subject: [PATCH] implement -j option for parallel cracks using pthreads a user-defined number of jobs (N) is started, each one is assigned SECS_PER_JOB_BLOCK seeds to iterate over, after finishing the block N * SECS_PER_JOB_BLOCK jobs are skipped, and it goes on again. that way it is assured that more recent seeds get treated first. in preliminary tests with a seed 2 years ago, using 8 jobs the cracking time was reduced from 77 to 24 seconds. it is possible that adjusting SECS_PER_JOB_BLOCK to a higher value than currently speeds up cracking even more, since there will be less "interruptions" in the CPUs branch prediction. --- src/Makefile | 6 ++- src/pixiewps.c | 135 +++++++++++++++++++++++++++++++++++-------------- src/pixiewps.h | 1 + 3 files changed, 101 insertions(+), 41 deletions(-) diff --git a/src/Makefile b/src/Makefile index 3c5b232..75ac76f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,14 +3,16 @@ CCFLAGS ?= -std=c99 -O3 TARGET = pixiewps CRYPTO = crypto/sha256.c crypto/md.c crypto/md_wrap.c SOURCE = $(TARGET).c random_r.c $(CRYPTO) +LIBS = -lpthread + PREFIX ?= $(DESTDIR)/usr BINDIR = $(PREFIX)/bin all: - $(CC) $(CFLAGS) $(CCFLAGS) $(CPPFLAGS) -o $(TARGET) $(SOURCE) $(LDFLAGS) + $(CC) $(CFLAGS) $(CCFLAGS) $(CPPFLAGS) -o $(TARGET) $(SOURCE) $(LIBS) $(LDFLAGS) debug: - $(CC) $(CLFAGS) $(CCFLAGS) $(CPPFLAGS) -DDEBUG -o $(TARGET) $(SOURCE) $(LDFLAGS) + $(CC) $(CLFAGS) $(CCFLAGS) $(CPPFLAGS) -DDEBUG -o $(TARGET) $(SOURCE) $(LIBS) $(LDFLAGS) install: rm -f $(BINDIR)/$(TARGET) diff --git a/src/pixiewps.c b/src/pixiewps.c index 51aac29..18b7ab7 100644 --- a/src/pixiewps.c +++ b/src/pixiewps.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,7 @@ uint32_t ecos_rand_simple(uint32_t *seed); uint32_t ecos_rand_knuth(uint32_t *seed); uint_fast8_t crack(struct global *g, char *pin); -static const char *option_string = "e:r:s:z:a:n:m:b:o:v:SflVh?"; +static const char *option_string = "e:r:s:z:a:n:m:b:o:v:j:SflVh?"; static const struct option long_options[] = { { "pke", required_argument, 0, 'e' }, { "pkr", required_argument, 0, 'r' }, @@ -53,6 +54,7 @@ static const struct option long_options[] = { { "e-bssid", required_argument, 0, 'b' }, { "output", required_argument, 0, 'o' }, { "verbosity", required_argument, 0, 'v' }, + { "jobs", required_argument, 0, 'j' }, { "dh-small", no_argument, 0, 'S' }, { "force", no_argument, 0, 'f' }, { "length", no_argument, 0, 'l' }, @@ -65,6 +67,89 @@ static const struct option long_options[] = { { 0, 0, 0, 0 } }; +#define SECS_PER_JOB_BLOCK 1000 + +struct crack_job { + pthread_t thr; + time_t start; +}; + +static struct job_control { + int jobs; + time_t end; + uint32_t randr_enonce[4]; + struct crack_job *crack_jobs; + volatile uint32_t print_seed; +} job_control; + +static void* crack_thread(void *arg) { + struct crack_job * j = arg; + struct random_data *buf = calloc(1, sizeof(struct random_data)); + char *rand_statebuf = calloc(1, 128); + + uint32_t seed = j->start; + uint32_t limit = job_control.end; + initstate_r(seed, rand_statebuf, 128, buf); + int32_t res = 0; + + while (!job_control.print_seed) { + srandom_r(seed, buf); + unsigned i; + for (i = 0; i < 4; i++) { + random_r(buf, &res); + if ((uint32_t) res != job_control.randr_enonce[i]) + break; + } + + if (i == 4) { + job_control.print_seed = seed; + DEBUG_PRINT("Seed found"); + } + + seed--; + if(seed < j->start - SECS_PER_JOB_BLOCK) { + j->start -= SECS_PER_JOB_BLOCK * job_control.jobs; + seed = j->start; + if (seed < limit) break; + } + } + return 0; +} + +static void init_crack_jobs(int jobs, struct global *wps) { + job_control.jobs = jobs; + job_control.end = wps->end; + job_control.print_seed = 0; + memset(job_control.randr_enonce, 0, sizeof(job_control.randr_enonce)); + /* Converting enrollee nonce to the sequence may be generated by current random function */ + int i, j = 0; + for (int i = 0; i < 4; i++) { + job_control.randr_enonce[i] |= wps->e_nonce[j++]; + job_control.randr_enonce[i] <<= 8; + job_control.randr_enonce[i] |= wps->e_nonce[j++]; + job_control.randr_enonce[i] <<= 8; + job_control.randr_enonce[i] |= wps->e_nonce[j++]; + job_control.randr_enonce[i] <<= 8; + job_control.randr_enonce[i] |= wps->e_nonce[j++]; + } + job_control.crack_jobs = malloc(jobs * sizeof (struct job_control)); + time_t curr = wps->start; + for(i=0; ipke = malloc(WPS_PKEY_LEN); if (!wps->pke) @@ -578,18 +667,8 @@ usage_err: if (!(wps->e_nonce[0] & 0x80) && !(wps->e_nonce[4] & 0x80) && !(wps->e_nonce[8] & 0x80) && !(wps->e_nonce[12] & 0x80)) { - /* Converting enrollee nonce to the sequence may be generated by current random function */ - uint32_t randr_enonce[4] = { 0 }; - uint_fast8_t j = 0; - for (uint_fast8_t i = 0; i < 4; i++) { - randr_enonce[i] |= wps->e_nonce[j++]; - randr_enonce[i] <<= 8; - randr_enonce[i] |= wps->e_nonce[j++]; - randr_enonce[i] <<= 8; - randr_enonce[i] |= wps->e_nonce[j++]; - randr_enonce[i] <<= 8; - randr_enonce[i] |= wps->e_nonce[j++]; - } + init_crack_jobs(jobs, wps); + #if DEBUG { @@ -607,36 +686,14 @@ usage_err: } #endif + print_seed = collect_crack_jobs(); + struct random_data *buf = calloc(1, sizeof(struct random_data)); char *rand_statebuf = calloc(1, 128); - - seed = wps->start; - uint32_t limit = wps->end; - initstate_r(seed, rand_statebuf, 128, buf); - int32_t res = 0; - - while (1) { - srandom_r(seed, buf); - uint_fast8_t i; - for (i = 0; i < 4; i++) { - random_r(buf, &res); - if ((uint32_t) res != randr_enonce[i]) - break; - } - - if (i == 4) { - print_seed = seed; - DEBUG_PRINT("Seed found"); - } - - if (print_seed || seed == limit) { - break; - } - - seed--; - } + initstate_r(print_seed, rand_statebuf, 128, buf); if (print_seed) { /* Seed found */ + int32_t res; uint_fast8_t i = 0; uint8_t tmp_s_nonce[16]; do { diff --git a/src/pixiewps.h b/src/pixiewps.h index b1d7cae..e979928 100644 --- a/src/pixiewps.h +++ b/src/pixiewps.h @@ -134,6 +134,7 @@ char usage[] = " -l, --length : Brute-force entire pin length (experimental)\n" " -v, --verbosity : Verbosity level 1-3, 1 is quietest [3]\n" " -o, --output : Write output to file\n" + " -j, --jobs : Number of parallel threads to use [1]\n" "\n" " -h : Display this usage screen\n" " --help : Verbose help and more usage examples\n"