Startseite
Astronomie
Gipfelbuch
Photos
Whisky
Whiskyrechner
Passwortgenerator
Simpsons
Code
xkcd

Kleingedrucktes
Kontakt

Hashcracker

Sourcecode

#include <iostream>
#include <crypt.h>
#include <cstdio>
#include <ctime>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <omp.h>

/**********************************
FOR TESTING USE:
HASH:    X.p6jpj1uDVC0004tuJq0vDkOfGoDPI4pcDZjyGGzQoD4kUwCGGu3Kuu4Ae1r88/exKlEty5yU0CRjx7BbMHq/
SALT:    qP/K/YHB
HASH ALGORITHM:  6
Password length: 4
Keyspace: Something containing "t" "e" and "s"

Result should be "test"

Some sample keyspaces:

abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ

**********************************/

int pwdlen;    // password length
char *password;   // the password
int counter;    // password counter for stats
clock_t begin;    // clock for time measurement
int nthreads;

using namespace std;

string actual_hash;  // the actual hash which shall be matched
string salt;    // the salt used in the shadow file
char *keyspace;

struct crypt_data cryptdata;

bool checkpasswd(string pwd);

bool passwordfound = 0;

int loop(int n, char firstletter, char* password, struct crypt_data cryptdata);

int main(int argc, char** argv)
{  
  
  if(argc != 7)
  {
    cout << argv[0] << " <actual Hash> <salt> <pwd length> <hash algorithm> <ncpus> <keyspace>" << endl;
    return 1;
  }
  
  // Start the clock for performance measurement
  begin = clock();
    
  // read the actual hash from the argument list
  actual_hash = argv[1];    
    
  // read the salt from the argument list
  salt = argv[2];
  
  // read the encryption algorithm from the argument list
  string encryption(argv[4]);  // encryption method(leave blank for DES,'1'= MD5,'2' = Blowfish,'3'=NT-Hash,'5'=SHA-256,'6'=SHA-512)
  
  // create the salt-string in the way the crypt function wants it
  salt = "$"+encryption + "$" + salt;
  
  // create the actual-hash-string in the way the crypt function wants it
  actual_hash = salt + "$" + actual_hash;
  
  // read the password length from the argument list
  pwdlen = atoi(argv[3]);
  
  // initialize the counter of checked passwords
  counter = 0;
  
  // read the desired number of threads from the argument list
  nthreads = atoi(argv[5]);
  
  // initialize open mp threads
  omp_set_num_threads(nthreads);
  
  // read the keyspace from the argument list
  keyspace = argv[6];
  
  // calculate maximum number of passwords that have to be checked
  unsigned long numpwd = pow(strlen(keyspace),pwdlen);

  // write maximum number of passwords that have to be checked
  cout << "Checking "<< numpwd << " passwords..."<<endl;
  
  // first letter of prospective password (to enable parallelization)
  char firstletter;
  
  // define conditions for open mp parallelization
  #pragma omp parallel for private(firstletter, password, passwordfound, cryptdata) shared(keyspace, pwdlen, counter) default(none)
  
  // cycle through the first letter and using multiple threads
  for(int k=0; k<strlen(keyspace); k++) {

  // what does that structure do?
    struct crypt_data cryptdata;
  cryptdata.initialized = 0;
  
  // allocate memory for the password that will be checked
        password = new char [pwdlen];
  
  // set the first letter of the password
  firstletter = keyspace[k];

  // start the password-create-loop
    loop(pwdlen-1,firstletter,password,cryptdata);
  }
       
  // we arrive here only when no password has been found
  clock_t end = clock();
  
  // calculate and write elapsed seconds
  double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC / nthreads;
  cout << "No password found"<< "\nStats: "<< numpwd<< " passwords in "<< elapsed_secs << " seconds\n"<<counter/elapsed_secs << " passwords per second"<< endl;
  
  return 1; 
  
}


int loop(int n, char firstletter, char* password, struct crypt_data cryptdata)
{  // loops through the possible combination of charachters in the keyspace
  // this function will call itself until the password has the desired length

  // the string for the password that will be checked
  string chkpwd;
  
  
  // until we arrive at the last charachter...
  if(n>=0)
  {
    for ( int i=0; i<strlen(keyspace); i++)
    {
      // set the n-th charachter of the password ...
      password[n] = keyspace[i];
      
      // ... and call this very function again
      loop(n-1, firstletter,password, cryptdata);
      
    }
    
    if(n==0)
    {  // in the last iteration...
      
      // ...build password. Start with the first letter...          
      chkpwd=firstletter;
      
      // ... and append the others
      for(int j=1;j<pwdlen;j++)
      {
         chkpwd += password[j];
      }
      
      // find out the thread-id
      const int id = omp_get_thread_num();
  
      // increase number of checked passwords
      counter ++;
  
      // string for the hash that correspons to the password that is being checked right now
      string checkhash;

      // check whether prospective password's hash fits:
      checkhash = crypt_r(chkpwd.c_str(), salt.c_str(), &cryptdata);

      passwordfound = ( checkhash == actual_hash );
      
      // if the password has been found ...
      if ( passwordfound )
      {
  
        // ... print password, statistics about the performance and exit
        cout << chkpwd << " " << id << "\n";
        clock_t end = clock();
        double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC / nthreads;
        printf("****** Thread %i: Password found: %s ****** \n",id,chkpwd.c_str());
  
        printf("Thread %i: Stats: %i passwords in %f seconds\n",id,counter, elapsed_secs);
        printf("Thread %i: %f passwords per second",id, counter/elapsed_secs);

        exit(0);
      }
      
      // clear password for the next run
      chkpwd.clear();
    }
  }
  
}

Performance:

Setup

Compiler:gcc 4.8.2
Compiled:g++ -O3 -g -lcrypt -lgomp -fopenmp
CPU:Intel Core i5-2500K
RAM:2 x 8GB Corsair XMS3 DDR3-1333 DIMM CL9 Dual Kit

Results

Hash AlgorithmPasswords per second per thread
MD-5up to 5000
SHA512ca. 330