crack hash with dictionary from C rand()
#1
I have some md5 hashes of passwords created from C rand() function (as following example)

void create_pass( char* randomString )
{
    sizet_t i = 0;
    size_t length = 28;

    srand(32BIT_SEED);
    strcpy(randomString,"");

    for( i = 0; i < (length/2); i++ )
    {
        *(randomString + i) = ( rand() % 25 + 65 );
    }
    for( ; i < length; i++ )
    {
        *(randomString + i) = ( rand() % 9 + 48 );
    }
}

I can reproduce the same char sequence with the correct srand seed( 32bit int), so i want to brute force the seed by generating all 28 char sequence as dict and crack the md5 hash with hashcat.

But the whole dictionary is huge ( about hundreds of gigabytes), is there any more efficient way? Thanks for help.
Reply
#2
you can use a pipe / stdin instead ( ./my_generator.bin | ./hashcat -m 0 -a 0 -O -w 4 hash.txt

it's important that this (your) password candidate generator (my_generator.bin) is optimized and very fast... of course it would work best with slow hashes (but MD5 is of course a very fast hash).

You could try to optimize it by not "printing" each and every password candidate as soon as possible, but use a large buffer instead (buffered)... the size (of each line with newline appended to each password) is fixed anyway.
Some ideas/optimization can be found also in the source code of maskprocessor or similar tools....

so my suggestion is to use pipes with an optimized generator.

you could start with something like this for the my_generator source code and adapt and/or optimize it further:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>

// Author: philsmd
// Date: October 2020
// License: public domain, credits go to philsmd and hashcat

//
// How to compile:
//

// gcc -O2 -o my_generator.bin my_generator.c


//
// Constants:
//

// here we assume that srand (time (0)) is used

#define SEED_MIN 1500000000 // or 0
#define SEED_MAX 1600000000 // or time (0)

#define BUF_SIZE 29 * 35 * 1024 // just under 1 MB

//
// Start:
//

int main ()
{
  // disable buffering:

  setbuf (stdout, NULL);

  // init large buffer:

  unsigned char buf[BUF_SIZE];

  memset (buf, 0x0a, BUF_SIZE); // little hack: set the newline char (\n) only once

  int buf_off = 0; // offset

  // main loop:

  for (size_t seed = SEED_MIN; seed < SEED_MAX; seed++)
  {
    srand (seed);

    for (int i = 0; i < 14; i++)
    {
      buf[buf_off + i] = 'A' + (rand () % 25);
    }

    for (int i = 14; i < 28; i++)
    {
      buf[buf_off + i] = '0' + (rand () %  9);
    }

    buf_off += 29;

    if (buf_off >= BUF_SIZE)
    {
      fwrite (buf, 1, BUF_SIZE, stdout);

      buf_off = 0;
    }
  }

  // final output:

  if (buf_off) fwrite (buf, 1, buf_off, stdout);

  return 0;
}
Reply
#3
(10-10-2020, 10:41 AM)philsmd Wrote: you can use a pipe / stdin instead ( ./my_generator.bin | ./hashcat -m 0 -a 0 -O -w 4 hash.txt

it's important that this (your) password candidate generator (my_generator.bin) is optimized and very fast... of course it would work best with slow hashes (but MD5 is of course a very fast hash).

You could try to optimize it by not "printing" each and every password candidate as soon as possible, but use a large buffer instead (buffered)... the size (of each line with newline appended to each password) is fixed anyway.
Some ideas/optimization can be found also in the source code of maskprocessor or similar tools....

so my suggestion is to use pipes with an optimized generator.

you could start with something like this for the my_generator source code and adapt and/or optimize it further:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>

// Author: philsmd
// Date: October 2020
// License: public domain, credits go to philsmd and hashcat

//
// How to compile:
//

// gcc -O2 -o my_generator.bin my_generator.c


//
// Constants:
//

// here we assume that srand (time (0)) is used

#define SEED_MIN 1500000000 // or 0
#define SEED_MAX 1600000000 // or time (0)

#define BUF_SIZE 29 * 35 * 1024 // just under 1 MB

//
// Start:
//

int main ()
{
  // disable buffering:

  setbuf (stdout, NULL);

  // init large buffer:

  unsigned char buf[BUF_SIZE];

  memset (buf, 0x0a, BUF_SIZE); // little hack: set the newline char (\n) only once

  int buf_off = 0; // offset

  // main loop:

  for (size_t seed = SEED_MIN; seed < SEED_MAX; seed++)
  {
    srand (seed);

    for (int i = 0; i < 14; i++)
    {
      buf[buf_off + i] = 'A' + (rand () % 25);
    }

    for (int i = 14; i < 28; i++)
    {
      buf[buf_off + i] = '0' + (rand () %  9);
    }

    buf_off += 29;

    if (buf_off >= BUF_SIZE)
    {
      fwrite (buf, 1, BUF_SIZE, stdout);

      buf_off = 0;
    }
  }

  // final output:

  if (buf_off) fwrite (buf, 1, buf_off, stdout);

  return 0;
}


Thanks for the idea of buffering stdout. Actually I have tried using stdin mode of hashcat, while the speed is heavily slowed down. And thanks for your code, it works much better, enough to solve my problem.

By the way, would moving the rand algorithm into kernel help?  I learned the algorithm of rand() here:  https://stackoverflow.com/questions/1863...ementation
It looks not so complicated, does it fit in kernel?
Reply