Brute Force cracking MD5 hashes in multi threads

 

 

In this tutorial, we will show how to break MD5 hashes in multiple threads.


On the Internet, there is a lot of of instructions on MD5 brute force cracking, according to which it is possible to break passwords, but what if we want to divide the computing power into multiple threads and thus speed up the breaking itself?
In the future, we can consider an algorithm that will divide tasks between the computational performance of computers implemented in a botnet, for example.

As an example of our Brute Force attack, I used some code, freely distributed from the Internet, which I edited.
The following code might look like this:


BruteForce.h

  

#include <vector> #include <time.h> #include <string>
namespace Diall_bruteforce { class CrackMe { private: MD5 md5; ::std::string cracked; ::std::vector Characters; int I,K,N;
private: void CharInit(void) { for(char charset_='a'; charset_<= 'z'; charset_++) { this->Characters.push_back(charset_); } }
public: CrackMe(void) { this->cracked = ""; this->CharInit(); }
public: void CrackIt(::std::string password, char* thread, int j_,int n_) { ::std::cout << ::std::endl << "PASSWORD TO CRACK: "
<< password <<" " << thread << ::std::endl;
this->I = 1;
while(true) { this->I++; this->N = 1;
for(int j=j_;j<this->I;j++) { this>->N*=n_; }
for(int j = j_;j<this->N;j++) { this->K = 1;
for(int k=0;k<this->I;k++) { this->cracked += this->Characters[j/this->K%n_]; this->K *= n_; }
if(password.compare(md5.digestString(&this->cracked[0u])) == 0) { ::std::cout << ::std::endl << " Cracked password : " << this->cracked << " from "<< thread << " Finished Time " << thread <<" : " << clock() / (double) CLOCKS_PER_SEC<<::std::endl<<::std::endl;
return; } } } } }; }





Individual "partial" operations are performed by selecting input values: j_ a n_ method CrackMe.

When creating an instance, we are initializing the data store, in our case Characters type vector, in which we save the set checked during the cracking, in this case the set of characters "a" -> "z".
Size is 26, when running one thread then 26.

Entering values in cracking corresponds to the following distribution:

   Thread A 0-26   -> čas: 13.711

   Thread A 0-12   -> čas: 0.733
   Thread B 13-26


   Thread A 0-9     -> čas: 0.309
   Thread B 10-19
   Thread C 20- 26


   Thread A 0-6    -> čas: 0.079
   Thread B 7-15
   Thread C 16-22
   Thread D 23-26


   Thread A 0-4   -> čas: 0.027
   Thread B 5-11
   Thread C 12-16
   Thread D 17-22
   Thread E 23-26



   Thread A 0-2   -> čas: 1.592
   Thread B 3-9
   Thread C 10-14
   Thread D 15-19
   Thread E 20-23
   Thread F 24-26


Time complexity can be represented by a graph:




file main.cpp:

#include <windows.h> 
#include <iostream> 
#include "md5.h"    //https://bobobobo.wordpress.com/2010/10/17/md5-c-implementation/ 
#include "thread.h" //https://www.netbot.sk/en/14-blog-headers/94-thread-h-eb
#include "BruteForce.h" 
using namespace std; void CrackA(void); void CrackB(void); void CrackC(void); void CrackD(void); void CrackE(void); void CrackF(void); void CrackG(void);
#define passwordtocrack "babac"
unsigned int __stdcall _Thread0(void * input) { CrackA();
return 0; }
unsigned int __stdcall _Thread1(void * input) { CrackB();
return 0; }
unsigned int __stdcall _Thread2(void * input) { CrackC();
return 0; }
unsigned int __stdcall _Thread3(void * input) { CrackD();
return 0;
}
unsigned int __stdcall _Thread4(void * input) { CrackE();
return 0; }
unsigned int __stdcall _Thread5(void * input) { CrackF();
return 0; }
unsigned int __stdcall _Thread6(void * input) { CrackG();
return 0; }

int _cdecl main (void) { ::std::cout << endl;
::Threading::ThreadID thread0 = 0; ::Threading::ThreadID thread1 = 1; ::Threading::ThreadID thread2 = 2; ::Threading::ThreadID thread3 = 3; ::Threading::ThreadID thread4 = 4; ::Threading::ThreadID thread5 = 5; ::Threading::ThreadID thread6 = 6; ::Threading::ThreadHandle tHandle0 = ::Threading::MultyThreads->ThreadStart(_Thread0, NULL,
&thread0); ::Threading::ThreadHandle tHandle1 = ::Threading::MultyThreads->ThreadStart(_Thread1,
NULL,
&thread1); ::Threading::ThreadHandle tHandle2 = ::Threading::MultyThreads->ThreadStart(_Thread2,
NULL,
&thread2); ::Threading::ThreadHandle tHandle3 = ::Threading::MultyThreads->ThreadStart(_Thread3,
NULL,
&thread3); ::Threading::ThreadHandle tHandle4 = ::Threading::MultyThreads->ThreadStart(_Thread4,
NULL,
&thread4); ::Threading::ThreadHandle tHandle5 = ::Threading::MultyThreads->ThreadStart(_Thread5,
NULL,
&thread5); ::Threading::ThreadHandle tHandle6 = ::Threading::MultyThreads->ThreadStart(_Thread6,
NULL,
&thread6); ::Threading::MultyThreads->WaitingForThread(tHandle0); ::Threading::MultyThreads->WaitingForThread(tHandle1); ::Threading::MultyThreads->WaitingForThread(tHandle2); ::Threading::MultyThreads->WaitingForThread(tHandle3); ::Threading::MultyThreads->WaitingForThread(tHandle4); ::Threading::MultyThreads->WaitingForThread(tHandle5); ::Threading::MultyThreads->WaitingForThread(tHandle6); ::Threading::MultyThreads->CloseThread(tHandle0); ::Threading::MultyThreads->CloseThread(tHandle1); ::Threading::MultyThreads->CloseThread(tHandle2); ::Threading::MultyThreads->CloseThread(tHandle3); ::Threading::MultyThreads->CloseThread(tHandle4); ::Threading::MultyThreads->CloseThread(tHandle5); ::Threading::MultyThreads->CloseThread(tHandle6);
return 0; }
void CrackA(void) { MD5 md5 ;
string pass = md5.digestString( passwordtocrack );
Diall_bruteforce::CrackMe * crackme = new Diall_bruteforce::CrackMe(); crackme->CrackIt(pass, "Thread A", 0, 2); }
void CrackB(void) { MD5 md5 ;
string pass = md5.digestString( passwordtocrack );
Diall_bruteforce::CrackMe * crackme = new Diall_bruteforce::CrackMe(); crackme->CrackIt(pass, "Thread B", 3, 6); }
void CrackC(void) { MD5 md5 ;
string pass = md5.digestString( passwordtocrack );
Diall_bruteforce::CrackMe * crackme = new Diall_bruteforce::CrackMe(); crackme->CrackIt(pass, "Thread C", 7, 12); }
void CrackD(void) { MD5 md5 ;
string pass = md5.digestString( passwordtocrack );
Diall_bruteforce::CrackMe * crackme = new Diall_bruteforce::CrackMe(); crackme->CrackIt(pass, "Thread D",13, 16); }
void CrackE(void) { MD5 md5 ;
string pass = md5.digestString( passwordtocrack );
Diall_bruteforce::CrackMe * crackme= new Diall_bruteforce::CrackMe(); crackme->CrackIt(pass, "Thread E",17, 21); }
void CrackF(void) { MD5 md5 ;
string pass = md5.digestString( passwordtocrack );
Diall_bruteforce::CrackMe * crackme = new Diall_bruteforce::CrackMe(); crackme->CrackIt(pass, "Thread F",22, 23); }
void CrackG(void) { MD5 md5 ;
string pass = md5.digestString( passwordtocrack );
Diall_bruteforce::CrackMe * crackme1 = new Diall_bruteforce::CrackMe(); crackme1->CrackIt(pass, "Thread G",24, 26); }