Skip to content

Commit

Permalink
Improvement in glibc PRNG cracking
Browse files Browse the repository at this point in the history
The code is based on a precomputed initial seed table, instead of re-seeding from scratch everytime the whole state. On my x86 test machine this new code seems to be ~60% faster.

Some further testing and tuning may be needed.

Credits to @1yura.
  • Loading branch information
wiire-a committed Jan 9, 2018
1 parent c14f122 commit 7738fda
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 5 deletions.
8 changes: 3 additions & 5 deletions src/pixiewps.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

#define GLIBC_MAX_GEN 4
#include "random/glibc_random.c"
#include "random/glibc_random_lazy.c"
#include "random/glibc_random_yura.c"

static uint32_t ecos_rand_simplest(uint32_t *seed);
static uint32_t ecos_rand_simple(uint32_t *seed);
Expand Down Expand Up @@ -107,15 +107,13 @@ static struct job_control {

static void crack_thread_rtl(struct crack_job *j)
{
struct glibc_lazyprng glibc_lazyprng;
uint32_t seed = j->start;
uint32_t limit = job_control.end;
uint32_t tmp[4];

while (!job_control.nonce_seed) {
glibc_lazyseed(&glibc_lazyprng, seed);
if (glibc_rand1(&glibc_lazyprng) == job_control.randr_enonce[0]) {
if (!memcmp(glibc_randfill(&glibc_lazyprng, tmp), job_control.randr_enonce, WPS_NONCE_LEN)) {
if (glibc_fast_seed(seed) == job_control.randr_enonce[0]) {
if (!memcmp(glibc_fast_nonce(seed, tmp), job_control.randr_enonce, WPS_NONCE_LEN)) {
job_control.nonce_seed = seed;
DEBUG_PRINT("Seed found (%10u)", seed);
}
Expand Down
60 changes: 60 additions & 0 deletions src/random/glibc_random_yura.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Based on the code of user @1yura.
*
* See glibc_random.c for a better understanding of the code.
*/

#include <stdint.h>

static const uint32_t glibc_seed_tbl[31 + 3] = {
0x0128e83b, 0x00dafa31, 0x009f4828, 0x00f66443, 0x00bee24d, 0x00817005, 0x00cb918f,
0x00a64845, 0x0069c3cf, 0x00a76dbd, 0x0090a848, 0x0057025f, 0x0089126c, 0x007d9a8f,
0x0048252a, 0x006fb2d4, 0x006ccc15, 0x003c5744, 0x005a998f, 0x005df917, 0x0032ed77,
0x00492688, 0x0050e901, 0x002b5f57, 0x003acd0b, 0x00456b7a, 0x0025413d, 0x002f11f4,
0x003b564d, 0x00203f14, 0x002589fc, 0x003283f8, 0x001c17e4, 0x001dd823
};

static inline uint32_t *glibc_fast_nonce(uint32_t seed, uint32_t *dest)
{
uint32_t word0 = 0, word1 = 0, word2 = 0, word3 = 0;

for (int j = 0; j < 31; j++) {
word0 += seed * glibc_seed_tbl[j + 3];
word1 += seed * glibc_seed_tbl[j + 2];
word2 += seed * glibc_seed_tbl[j + 1];
word3 += seed * glibc_seed_tbl[j + 0];

/* This does: seed = (16807LL * seed) % 0x7fffffff
using the sum of digits method which works for mod N, base N+1 */
const uint64_t p = 16807ULL * seed;
const uint64_t m = (p >> 31) + (p & 0x7fffffff);

/* The result might still not fit in 31 bits, if not, repeat
(conditional seems to make it slightly faster) */
seed = (m & 0xffffffff80000000) ? ((m >> 31) + (m & 0x7fffffff)) : m;
}
dest[0] = word0 >> 1;
dest[1] = word1 >> 1;
dest[2] = word2 >> 1;
dest[3] = word3 >> 1;
return dest;
}

static inline uint32_t glibc_fast_seed(uint32_t seed)
{
uint32_t word0 = 0;

for (int j = 0; j < 31; j++) {
word0 += seed * glibc_seed_tbl[j + 3];

/* This does: seed = (16807LL * seed) % 0x7fffffff
using the sum of digits method which works for mod N, base N+1 */
const uint64_t p = 16807ULL * seed;
const uint64_t m = (p >> 31) + (p & 0x7fffffff);

/* The result might still not fit in 31 bits, if not, repeat
(conditional seems to make it slightly faster) */
seed = (m & 0xffffffff80000000) ? ((m >> 31) + (m & 0x7fffffff)) : m;
}
return word0 >> 1;
}

0 comments on commit 7738fda

Please sign in to comment.