Inaccurate Design

Half-LM patch for rtgen-mt

Sunday, 19 February 2012

Over at foofus.net you can find a patch for adding support for HalfLM Challenge rainbow table generation to rtgen, a popular rainbow table generation tool. The only problem with this tool is that it’s single-threaded!

Below is the same patch, adapted into a nice diff to support the excellent rtgen-mt tool, which as the name suggests, is the multi-threaded version of rtgen.

You can also download the patch directly


diff -rupN rtgen-mt-orig//HashAlgorithm.cpp rtgen-mt//HashAlgorithm.cpp
--- rtgen-mt-orig//HashAlgorithm.cpp    2008-07-21 09:23:54.000000000 +1000
+++ rtgen-mt//HashAlgorithm.cpp 2012-02-19 11:43:34.731040616 +1100
@@ -91,3 +91,101 @@ void HashRIPEMD160(unsigned char* pPlain
 {
    RIPEMD160(pPlain, nPlainLen, pHash);
 }
+
+
+//*********************************************************************************
+// Code for LM Challenge/Response Authentication Hashing
+// http://www.securityfocus.com/archive/1/375137/30/0/threaded
+// Modified: JoMo-Kun 
+//*********************************************************************************
+void HashNetLM(unsigned char* pPlain, int nPlainLen, unsigned char* pHash)
+{
+  int i;
+  for (i = nPlainLen; i < 14; i++)
+    pPlain[i] = 0;
+
+  static unsigned char magic[] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
+  //static unsigned char chllng[8] = {0}; // the fixed challenge of smbrelay
+  static unsigned char chllng[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; // Cain & Abel fixed challenge
+  des_key_schedule ks;
+  unsigned char lm[21];
+
+  setup_des_key(pPlain, ks);
+  des_ecb_encrypt((des_cblock*)magic, (des_cblock*)lm, ks, DES_ENCRYPT);
+  setup_des_key(&pPlain[7], ks);
+  des_ecb_encrypt((des_cblock*)magic, (des_cblock*)&lm[8], ks, DES_ENCRYPT);
+  setup_des_key(lm, ks);
+  des_ecb_encrypt((des_cblock*)chllng, (des_cblock*)pHash, ks, DES_ENCRYPT);
+  setup_des_key(&lm[7], ks);
+  des_ecb_encrypt((des_cblock*)chllng, (des_cblock*)&pHash[8], ks, DES_ENCRYPT);
+  if (nPlainLen < 8)
+  {
+    pHash[16] = 0x57; pHash[17] = 0xe9; pHash[18] = 0xa1; pHash[19] = 0xb7;
+    pHash[20] = 0x95; pHash[21] = 0x40; pHash[22] = 0xc3; pHash[23] = 0x74;
+  }
+  else
+  {
+    lm[16] = lm[17] = lm[18] = lm[19] = lm[20] = 0;
+    setup_des_key(&lm[14], ks);
+    des_ecb_encrypt((des_cblock*)chllng, (des_cblock*)&pHash[16], ks, DES_ENCRYPT);
+  }
+}
+
+//*********************************************************************************
+// Code for LM Challenge/Response Authentication Hashing
+// Generate 1/3 of the LM response. This should help to significantly reduce
+// the potential keyspace of the first half of the LM password.
+// Based on oxid.it Forum Post
+// Modified: JoMo-Kun 
+//*********************************************************************************
+void HashHalfNetLM(unsigned char* pPlain, int nPlainLen, unsigned char* pHash)
+{
+  int i;
+  for (i = nPlainLen; i < 14; i++)
+    pPlain[i] = 0;
+
+  static unsigned char magic[] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
+  static unsigned char chllng[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; // Cain & Abel fixed challenge
+  des_key_schedule ks;
+  unsigned char lm[8];
+
+  // generate LM hash (first half)
+  setup_des_key(pPlain, ks);
+  des_ecb_encrypt((des_cblock*)magic, (des_cblock*)lm, ks, DES_ENCRYPT);
+
+  // generate LM response (first third)
+  setup_des_key(lm, ks);
+  des_ecb_encrypt((des_cblock*)chllng, (des_cblock*)pHash, ks, DES_ENCRYPT);
+}
+
+//*********************************************************************************
+// Code for NTLMv1 Challenge/Response Authentication Hashing
+// http://www.securityfocus.com/archive/1/375137/30/0/threaded
+// Modified: JoMo-Kun 
+//*********************************************************************************
+void HashNetNTLM(unsigned char* pPlain, int nPlainLen, unsigned char* pHash)
+{
+  unsigned char UnicodePlain[MAX_PLAIN_LEN];
+  int len = (nPlainLen < 127) ? nPlainLen : 127;
+  int i;
+  for (i = 0; i < len; i++)
+  {
+    UnicodePlain[i * 2] = pPlain[i];
+    UnicodePlain[i * 2 + 1] = 0x00;
+  }
+
+  //static unsigned char chllng[8] = {0}; // the fixed challenge of SMBRelay
+  static unsigned char chllng[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; // Cain & Abel fixed challenge
+  des_key_schedule ks;
+  unsigned char lm[21];
+
+  MD4(UnicodePlain, len * 2, lm);
+  lm[16] = lm[17] = lm[18] = lm[19] = lm[20] = 0;
+  setup_des_key(lm, ks);
+  des_ecb_encrypt((des_cblock*)chllng, (des_cblock*)pHash, ks, DES_ENCRYPT);
+  setup_des_key(&lm[7], ks);
+  des_ecb_encrypt((des_cblock*)chllng, (des_cblock*)&pHash[8], ks, DES_ENCRYPT);
+  setup_des_key(&lm[14], ks);
+  des_ecb_encrypt((des_cblock*)chllng, (des_cblock*)&pHash[16], ks, DES_ENCRYPT);
+}
+
diff -rupN rtgen-mt-orig//HashAlgorithm.h rtgen-mt//HashAlgorithm.h
--- rtgen-mt-orig//HashAlgorithm.h  2008-07-21 09:24:01.000000000 +1000
+++ rtgen-mt//HashAlgorithm.h   2012-02-19 11:42:11.660569429 +1100
@@ -18,4 +18,13 @@ void HashMD5(unsigned char* pPlain, int
 void HashSHA1(unsigned char* pPlain, int nPlainLen, unsigned char* pHash);
 void HashRIPEMD160(unsigned char* pPlain, int nPlainLen, unsigned char* pHash);
 
+//****************************************************************************
+// LM/NTLMv1 Challenge/Response Authentication Hashing
+// Modified: JoMo-Kun 
+//****************************************************************************
+void HashNetLM(unsigned char* pPlain, int nPlainLen, unsigned char* pHash);
+void HashHalfNetLM(unsigned char* pPlain, int nPlainLen, unsigned char* pHash);
+void HashNetNTLM(unsigned char* pPlain, int nPlainLen, unsigned char* pHash);
+
+
 #endif
diff -rupN rtgen-mt-orig//HashRoutine.cpp rtgen-mt//HashRoutine.cpp
--- rtgen-mt-orig//HashRoutine.cpp  2008-07-21 09:24:08.000000000 +1000
+++ rtgen-mt//HashRoutine.cpp   2012-02-19 11:42:34.371634056 +1100
@@ -25,6 +25,10 @@ CHashRoutine::CHashRoutine()
    AddHashRoutine("md5",  HashMD5,  16);
    AddHashRoutine("sha1", HashSHA1, 20);
    AddHashRoutine("ripemd160", HashRIPEMD160, 20);
+   AddHashRoutine("netlm", HashNetLM, 24);
+   AddHashRoutine("halflmchall", HashHalfNetLM, 8);
+   AddHashRoutine("nethalflm", HashHalfNetLM, 8);
+   AddHashRoutine("netntlm", HashNetNTLM, 24);
 }
 
 CHashRoutine::~CHashRoutine()