I have combined this with a more cache friendly searchtable, the result is here:
Code: Select all
Edited - see below for newer version of code
Have fun.
Code: Select all
Edited - see below for newer version of code
Code: Select all
buffer[len]=0x80;
buffer[62]=(len*8)>>8;
buffer[63]=(len*8)&0xff;
this fast implementation has the limitation of hash upto 55 characters.gorim wrote: But supposedly people are seeing no problems with fastSHA1 as a result. Can anyone explain why this was added to the recent code ?
Code: Select all
Edited - see below for newer version of code
Code: Select all
/*
SHA1 dictionary attack program v5.4 (c) 2005 adresd
based on original by djhuevo
Hash searchtable and other mods by adresd
Endian independant now, with sanity checks verified on both settings
No License, public domain, do as you want, no warranties
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <malloc.h>
#include <stdlib.h>
// Comment this out for BIG endian machines
#define LITTLE_ENDIANESS
// This enables using both routines, if not enabled it will use the opted one as default
#define USEBOTHSHA1ROUTINES
// These are the sanity checks at startup
#define NEW_SHA1_CHECK
#define OLD_SHA1_CHECK
// This overrides all others, and forces using the reference implementation ALWAYS
//#define FORCE_USE_SLOW
// This forces skipping over words with an existing result file
//#define SKIP_EXISTING
#ifdef FORCE_USE_SLOW
#undef NEW_SHA1_CHECK
#endif
typedef char s8;
typedef short s16;
typedef int s32;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
//
// This is the original REFERENCE SHA-1 Algorithm
//
typedef struct {
unsigned long state[5];
unsigned long count[2];
unsigned char buffer[64];
} SHA1_CTX;
void SHA1Transform(unsigned long state[5], unsigned char buffer[64]);
void SHA1Init(SHA1_CTX* context);
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#ifdef LITTLE_ENDIANESS
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */
__inline__ void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
{
unsigned long a, b, c, d, e;
typedef union {
unsigned char c[64];
unsigned long l[16];
} CHAR64LONG16;
CHAR64LONG16* block;
#ifdef SHA1HANDSOFF
static unsigned char workspace[64];
block = (CHAR64LONG16*)workspace;
memcpy(block, buffer, 64);
#else
block = (CHAR64LONG16*)buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
}
/* SHA1Init - Initialize new context */
__inline__ void SHA1Init(SHA1_CTX* context)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. */
__inline__ void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len)
{
unsigned int i, j;
j = (context->count[0] >> 3) & 63;
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
context->count[1] += (len >> 29);
if ((j + len) > 63) {
memcpy(&context->buffer[j], data, (i = 64-j));
SHA1Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64) {
SHA1Transform(context->state, &data[i]);
}
j = 0;
}
else i = 0;
memcpy(&context->buffer[j], &data[i], len - i);
}
/* Add padding and return the message digest. */
__inline__ void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
{
unsigned long i, j;
unsigned char finalcount[8];
for (i = 0; i < 8; i++) {
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
SHA1Update(context, (unsigned char *)"\200", 1);
while ((context->count[0] & 504) != 448) {
SHA1Update(context, (unsigned char *)"\0", 1);
}
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++) {
digest[i] = (unsigned char)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
/* Wipe variables */
i = j = 0;
memset(context->buffer, 0, 64);
memset(context->state, 0, 20);
memset(context->count, 0, 8);
memset(&finalcount, 0, 8);
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
SHA1Transform(context->state, context->buffer);
#endif
}
__inline__ unsigned int hashSHA1(char *buffer, SHA1_CTX *context, int size)
{
unsigned char digest[20];
SHA1Init(context);
SHA1Update(context, buffer, size);
SHA1Final(digest, context);
#ifdef LITTLE_ENDIANESS
return *((unsigned int *)digest);
#else
{ // Swap the bytes around
unsigned int temp = *((unsigned int *)digest);
return ( ((temp&0xff000000)>>24) | ((temp&0x00ff0000)>>8) | ((temp&0x0000ff00)<<8) | ((temp&0x000000ff)<<24) );
}
#endif
}
SHA1_CTX context;
//
// This is the OPTIMISED SHA-1 Algorithm
//
/*
SHA-1 based on Steve Reid SHA1 code <[email protected]>
*/
#define o_rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#ifdef LITTLE_ENDIANESS
#define o_blk0(i) (block[i] = (o_rol(block[i],24)&0xFF00FF00) \
|(o_rol(block[i],8)&0x00FF00FF))
#else
#define o_blk0(i) block[i]
#endif
#define o_blk(i) (block[i&15] = o_rol(block[(i+13)&15]^block[(i+8)&15] \
^block[(i+2)&15]^block[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define o_R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+o_blk0(i)+0x5A827999+o_rol(v,5);w=o_rol(w,30);
#define o_R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+o_blk(i)+0x5A827999+o_rol(v,5);w=o_rol(w,30);
#define o_R2(v,w,x,y,z,i) z+=(w^x^y)+o_blk(i)+0x6ED9EBA1+o_rol(v,5);w=o_rol(w,30);
#define o_R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+o_blk(i)+0x8F1BBCDC+o_rol(v,5);w=o_rol(w,30);
#define o_R4(v,w,x,y,z,i) z+=(w^x^y)+o_blk(i)+0xCA62C1D6+o_rol(v,5);w=rol(w,30);
u32 fastSHA1(unsigned char *buffer,int len) {
u8 buf[64];
s32 i;
u32 a, b, c, d, e;
u32 *block;
int len2;
len2 = len;
if (len2 > 63) len2 = 63;
memcpy(buf, buffer, len2);
block=(u32 *)buf;
for(i=len2; i<=63; i++) {
buf[i]=0x00;
}
buf[len2]=0x80;
buf[62]=(len2*8)>>8;
buf[63]=(len2*8)&0xff;
a = 0x67452301;
b = 0xEFCDAB89;
c = 0x98BADCFE;
d = 0x10325476;
e = 0xC3D2E1F0;
/* 4 rounds of 20 operations each. Loop unrolled. */
o_R0(a,b,c,d,e, 0); o_R0(e,a,b,c,d, 1); o_R0(d,e,a,b,c, 2); o_R0(c,d,e,a,b, 3);
o_R0(b,c,d,e,a, 4); o_R0(a,b,c,d,e, 5); o_R0(e,a,b,c,d, 6); o_R0(d,e,a,b,c, 7);
o_R0(c,d,e,a,b, 8); o_R0(b,c,d,e,a, 9); o_R0(a,b,c,d,e,10); o_R0(e,a,b,c,d,11);
o_R0(d,e,a,b,c,12); o_R0(c,d,e,a,b,13); o_R0(b,c,d,e,a,14); o_R0(a,b,c,d,e,15);
o_R1(e,a,b,c,d,16); o_R1(d,e,a,b,c,17); o_R1(c,d,e,a,b,18); o_R1(b,c,d,e,a,19);
o_R2(a,b,c,d,e,20); o_R2(e,a,b,c,d,21); o_R2(d,e,a,b,c,22); o_R2(c,d,e,a,b,23);
o_R2(b,c,d,e,a,24); o_R2(a,b,c,d,e,25); o_R2(e,a,b,c,d,26); o_R2(d,e,a,b,c,27);
o_R2(c,d,e,a,b,28); o_R2(b,c,d,e,a,29); o_R2(a,b,c,d,e,30); o_R2(e,a,b,c,d,31);
o_R2(d,e,a,b,c,32); o_R2(c,d,e,a,b,33); o_R2(b,c,d,e,a,34); o_R2(a,b,c,d,e,35);
o_R2(e,a,b,c,d,36); o_R2(d,e,a,b,c,37); o_R2(c,d,e,a,b,38); o_R2(b,c,d,e,a,39);
o_R3(a,b,c,d,e,40); o_R3(e,a,b,c,d,41); o_R3(d,e,a,b,c,42); o_R3(c,d,e,a,b,43);
o_R3(b,c,d,e,a,44); o_R3(a,b,c,d,e,45); o_R3(e,a,b,c,d,46); o_R3(d,e,a,b,c,47);
o_R3(c,d,e,a,b,48); o_R3(b,c,d,e,a,49); o_R3(a,b,c,d,e,50); o_R3(e,a,b,c,d,51);
o_R3(d,e,a,b,c,52); o_R3(c,d,e,a,b,53); o_R3(b,c,d,e,a,54); o_R3(a,b,c,d,e,55);
o_R3(e,a,b,c,d,56); o_R3(d,e,a,b,c,57); o_R3(c,d,e,a,b,58); o_R3(b,c,d,e,a,59);
o_R4(a,b,c,d,e,60); o_R4(e,a,b,c,d,61); o_R4(d,e,a,b,c,62); o_R4(c,d,e,a,b,63);
o_R4(b,c,d,e,a,64); o_R4(a,b,c,d,e,65); o_R4(e,a,b,c,d,66); o_R4(d,e,a,b,c,67);
o_R4(c,d,e,a,b,68); o_R4(b,c,d,e,a,69); o_R4(a,b,c,d,e,70); o_R4(e,a,b,c,d,71);
o_R4(d,e,a,b,c,72); o_R4(c,d,e,a,b,73); o_R4(b,c,d,e,a,74); o_R4(a,b,c,d,e,75);
o_R4(e,a,b,c,d,76); o_R4(d,e,a,b,c,77); o_R4(c,d,e,a,b,78); o_R4(b,c,d,e,a,79);
a+=0x67452301;
// Swap the bytes around
return (a>>24)|((a>>8)&0xff00)|((a<<8)&0xff0000)|((a<<24));
}
typedef struct {
char **dict;
char *dict_member_length;
int dict_count;
} dictionary_struct;
dictionary_struct dicfirstword,dicmain;
unsigned int *hash;
int hash_count;
int load_hash_list(char *filename)
{
int i;
unsigned int t;
FILE *fp;
printf("Reading hash file '%s'\n", filename);
if ((fp = fopen(filename, "rt")) == NULL)
return -1;
hash_count = 0;
while (fscanf(fp, "0x%x\n", &t) == 1)
hash_count++;
printf("hash_count = %d\n", hash_count);
fseek(fp, 0, SEEK_SET);
hash = malloc(hash_count * sizeof(unsigned int));
i = 0;
while (fscanf(fp, "0x%x\n", &hash[i++]) == 1);
fclose(fp);
return 0;
}
int load_dictionary(dictionary_struct *dic,char *filename)
{
int i;
char buffer[0x200];
FILE *fp;
printf("Reading dictionary file '%s'\n", filename);
if ((fp = fopen(filename, "rt")) == NULL)
return -1;
dic->dict_count = 0;
while (fscanf(fp, "%s\n", buffer) != EOF)
dic->dict_count++;
printf("dict_count = %d\n", dic->dict_count);
fseek(fp, 0, SEEK_SET);
dic->dict = (char **) malloc(dic->dict_count * sizeof(char *));
dic->dict_member_length = malloc(dic->dict_count);
i = 0;
while (fscanf(fp, "%s\n", buffer) == 1) {
if ((buffer[0] == '-') || (buffer[0] == '/')) { // This handles comments in the dic file
} else { // Not a comment, so do duplicate check
int count;
int found = 0;
for (count = 0; count < (i - 1); count++)
if (strcmp(buffer, dic->dict[count]) == 0)
found = 1;
if (found == 0) { // If not already in dictionary, then add
dic->dict_member_length[i] = strlen(buffer);
dic->dict[i] = malloc(dic->dict_member_length[i] + 1);
strcpy(dic->dict[i], buffer);
i++;
}
}
}
dic->dict_count = i;
fclose(fp);
return 0;
}
FILE *fout;
// Hash seems to be where the program spends most of its time, so we need to speedup the
// search somehow - 32 bit value, 4 bytes
// what we do, is pre-sort the hashlist, so they are in order AABBCCDD
// Then index each byte into the list, hence cutting down the search space considerably
#define VER2_SIZE 256
// midsearch should hopefully fit in cache, so will help quite a lot with rejection testing.
int midsearch[VER2_SIZE*VER2_SIZE];
// bigsearch is really a cop out, will not fit in cache, but still quicker than checking many elements.
int bigsearch[VER2_SIZE*VER2_SIZE*VER2_SIZE];
void fillsearchtable()
{
unsigned int searchval;
int hashpos,hashpos2,hashpos3;
int count,count2,count3;
int found = 1;
// Firstly Sort the hashlist, order AABBCCDD
printf("Sorting Hashlist\n");
while (found == 1) {
found = 0;
for (count=0;count<(hash_count-1);count++) {
if (hash[count] > hash[count+1]) { // swap entries if wrong way around
unsigned int temp = hash[count+1];
hash[count+1] = hash[count];
hash[count] = temp;
found = 1;
}
}
}
// Really lazy slow clear array, but who cares only done once
printf("Clearing Search Tree\n");
for (count=0;count<(VER2_SIZE*VER2_SIZE);count++)
midsearch[count] = -1;
for (count=0;count<(VER2_SIZE*VER2_SIZE*VER2_SIZE);count++)
bigsearch[count] = -1;
// Now build the toplevel (first) byte
printf("Building Search Tree\n");
for (count=0;count<256;count++) { // Find the first firstbyte in the hashlist that matches this value
hashpos = 0;
searchval = (count<<24);
while ((hash[hashpos++]&0xff000000) < searchval);
hashpos--;
if ((hash[hashpos]&0xff000000) == searchval) { // Now Search for a twobyte combo
for (count2=0;count2<256;count2++) { // Find the first secondbyte in the hashlist from this pos
hashpos2 = hashpos;
searchval = (count<<24) | (count2<<16);
while ((hash[hashpos2++]&0xffff0000) < searchval);
hashpos2--;
if ((hash[hashpos2]&0xffff0000) == searchval) { // Add this entry
midsearch[(count<<8)+count2] = hashpos2;
// Now Search for a threebyte combo
for (count3=0;count3<256;count3++) { // Find the first thirdbyte in the hashlist from this pos
hashpos3 = hashpos2;
searchval = (count<<24) | (count2<<16) | (count3<<8);
while ((hash[hashpos3++]&0xffffff00) < searchval);
hashpos3--;
if ((hash[hashpos3]&0xffffff00) == searchval)
{ // Add this entry
bigsearch[(count<<16)+(count2<<8)+count3] = hashpos2;
} } } } } } }
int findhash(char *buffer, int size)
{
unsigned int hashvalue;
int pos;
#ifdef FORCE_USE_SLOW
hashvalue = hashSHA1(buffer,&context, size);
#else
#ifdef USEBOTHSHA1ROUTINES
if (size < 55) // If small string, use the optimised version
hashvalue = fastSHA1(buffer, size);
else // else use the standard reference implementation
hashvalue = hashSHA1(buffer,&context, size);
#else
hashvalue = fastSHA1(buffer, size);
#endif
#endif
// get twobyte position
pos = midsearch[(hashvalue &0xffff0000)>>16];
if (pos != -1) { // Get threebyte position
pos = bigsearch[(hashvalue &0xffffff00)>>8];
if (pos != -1) { // Found a position, so search from here
int h;
for(h=pos; h<hash_count; h++) {
if (hashvalue >= hash[h])
if(hashvalue == hash[h]) { // If equal, found
printf("0x%08x %s\n",hashvalue,buffer);
fprintf(fout,"<FUNC><NID>0x%08x</NID><NAME>%s</NAME></FUNC>\n",hashvalue,buffer);
return 1;
}
else // If not, reject as above
return 0;
} } }
return 0;
}
int sanity_SHA1(char *teststring, unsigned int testhash)
{
// As a first task, perform a sanity check, verify SHA1 routines
unsigned int hashvalue1;
unsigned int hashvalue2;
unsigned int size;
int failed = 0;
size= strlen(teststring);
printf("Running SHA1 Check : '%s'(%d) ",teststring,size);
#ifdef OLD_SHA1_CHECK
// Check reference version
hashvalue2 = hashSHA1(teststring,&context, size);
if (hashvalue2 != testhash) {
printf("\nReference Version Failed Sanity Check (0x%08X)\n",hashvalue2);
failed = 1;
}
#endif
#ifdef NEW_SHA1_CHECK
// Check optimized version
hashvalue1 = fastSHA1(teststring, size);
if (hashvalue1 != testhash) {
printf("\nOptimised Version Failed Sanity Check (0x%08X)\n",hashvalue1);
failed = 1;
}
#endif
#ifdef NEW_SHA1_CHECK
#ifdef OLD_SHA1_CHECK
// Both Together, so check against each other
if (hashvalue1 != hashvalue2) {
printf("\nSHA1 return values differ (0x%08X),(0x%08X)\n",hashvalue1,hashvalue2);
failed = 1;
}
#endif
#endif
if (failed == 0)
printf("- Sanity Check Passed\n");
else
printf("- Sanity Check Failed, should be 0x%08X\n",testhash);
return failed;
}
int main(int argc, char **argv)
{
int i;
int x, y, z, zz;
int firstword;
char buffer[0x200];
time_t start, end;
time_t start2, end2;
char xmlfilename[200];
char *ptr, *ptr0, *ptr1, *ptr2, *ptr3;
char *prefix = "";
int prefixlen = 0;
printf("SHA1 hash dictionary attack v5.4 by adresd\n");
printf("based on the original by djhuevo\n\n");
if (argc == 2) {
unsigned int hash;
unsigned char *ptr = argv[1];
int length = strlen(ptr);
#ifdef FORCE_USE_SLOW
hash = hashSHA1(ptr,&context, length);
#else
#ifdef USEBOTHSHA1ROUTINES
if (length > 55)
hash = hashSHA1(ptr,&context, length);
else
hash = fastSHA1(ptr, length);
#else
hash = fastSHA1(ptr, length);
#endif
#endif
printf("Input string '%s' - hash 0x%08X\n",ptr,hash);
return(0);
}
{ // Perform the sanity checks
int failed = 0; // All test hashes under 55 chars so can check both old and new vers of SHA1 algo
failed += sanity_SHA1("MyTestString",0x0CC01ABB);
failed += sanity_SHA1("abc",0x363E99A9);
failed += sanity_SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopn",0x2d96FE59);
failed += sanity_SHA1("This!is+another_test*string$zebra@~}{@!!£'$^&*()[]{}=",0x4916E3FD);
if (failed > 0)
{
printf("\n\nFAILED SANITY CHECK!!!\n\n");
exit(1);
}
printf("\n");
}
if (argc < 3) {
printf("usage:\n\t%s <hash_list> <dictionaryfirst> <dictionarymain> [prefix]\n", argv[0]);
return 1;
}
if (load_hash_list(argv[1]) < 0) {
fprintf(stderr, "can't open the hash file %s\n", argv[1]);
return 2;
}
if (load_dictionary(&dicfirstword,argv[2]) < 0) {
fprintf(stderr, "can't open the first word dictionary file %s\n", argv[2]);
return 3;
}
if (load_dictionary(&dicmain,argv[3]) < 0) {
fprintf(stderr, "can't open the main dictionary file %s\n", argv[3]);
return 3;
}
if (argc > 4) {
prefix = argv[4];
strcpy(buffer, prefix);
prefixlen = strlen(prefix);
}
if (hash_count < 1 || dicmain.dict_count < 1 || dicfirstword.dict_count < 1) {
fprintf(stderr, "error on input data.\n");
fprintf(stderr, "hash_count = %d, dict_count = %d, dict_count = %d\n", hash_count, dicmain.dict_count,dicfirstword.dict_count);
return 4;
}
#ifdef FORCE_USE_SLOW
printf("Forcing using REFERENCE SHA1 algo\n");
#endif
printf("\nprefix : '%s'\n", prefix != "" ? prefix : "<None>");
printf("hash count : %d\n", hash_count);
printf("dictionary words (firstword) : %d\n", dicfirstword.dict_count);
printf("dictionary words (main) : %d\n\n", dicmain.dict_count);
fillsearchtable();
firstword = 0;
{ // Check for resuming a run
FILE *fpt;
if ((fpt = fopen("nidstatus.tmp", "rt")) != NULL) {
char bufferstr[200];
fscanf(fpt,"%s",bufferstr);
fclose(fpt);
// Now find the string in dic
for (x = 0; x < dicfirstword.dict_count; x++) {
if (strcmp(dicfirstword.dict[x],bufferstr) == 0)
firstword = x + 1; // Match, so select next word
}
if (firstword == 0) { // means we had a status file, but the word doesnt match
printf("\nResume file contains invalid word, please remove\n");
exit(1);
}
if (firstword != 0)
printf("\nResuming from : %s\n",dicfirstword.dict[firstword]);
} }
printf("\nsearching...\n\n");
fflush(stdout);
time(&start);
ptr = buffer + prefixlen;
// First Word
for (x = firstword; x < dicfirstword.dict_count; x++) {
time(&start2);
ptr0 = ptr;
for (i = 0; i < dicfirstword.dict_member_length[x]; i++) {
*(ptr0++) = dicfirstword.dict[x][i];
}
*(ptr0) = 0;
printf("// processing word: %s\n", buffer);
sprintf(xmlfilename,"results_%s.xml",buffer);
#ifdef SKIP_EXISTING
// Open results file for this word, see if it already exists
if ((fout = fopen(xmlfilename,"rt")) > 0) { // Output file exists
printf("Skipping Word : %s - Output Exists\n",buffer);
fclose(fout);
}
else
#endif
{ // Open the results file, ready for writing
printf("// opening results file : %s\n",xmlfilename);
if ((fout = fopen(xmlfilename, "wt")) <= 0) {
printf("Failed to open output file\n");
exit(1);
}
fprintf(fout,"<NIDFUNCLIST>\n");
fflush(stdout);
// Second word
for (y = 0; y < dicmain.dict_count; y++) {
ptr1 = ptr0;
for (i = 0; i < dicmain.dict_member_length[y]; i++) {
*(ptr1++) = dicmain.dict[y][i];
}
*(ptr1) = 0;
//printf("// processing word: %s\n",buffer);
// Only do next loop if first and second dont match
if (strcmp(dicmain.dict[x], dicmain.dict[y]) != 0) {
// Third Word
for (z = 0; z < dicmain.dict_count; z++) {
ptr2 = ptr1;
for (i = 0; i < dicmain.dict_member_length[z]; i++) {
*(ptr2++) = dicmain.dict[z][i];
}
// Only do next loop if second and third dont match
if (strcmp(dicmain.dict[y], dicmain.dict[z]) != 0) {
// Fourth Word
for (zz = 0; zz < dicmain.dict_count; zz++) {
ptr3 = ptr2;
for (i = 0; i < dicmain.dict_member_length[zz]; i++) {
*(ptr3++) = dicmain.dict[zz][i];
}
#if 0
// Only do next loop if third and fourth dont match
if (strcmp(dicmain.dict[z], dicmain.dict[zz]) != 0) {
// Fifth Word
for (z2 = 0; z2 < dicmain.dict_count; z2++) {
ptr4 = ptr3;
for (i = 0; i < dicmain.dict_member_length[z2]; i++) {
*(ptr4++) = dicmain.dict[z2][i];
}
*(ptr4) = 0x00;
findhash(buffer, ptr4 - buffer);
}
}
#endif
*(ptr3) = 0x00;
findhash(buffer, ptr3 - buffer);
}
}
*(ptr2) = 0x00;
findhash(buffer, ptr2 - buffer);
}
}
*(ptr1) = 0x00;
findhash(buffer, ptr1 - buffer);
}
*(ptr0) = 0x00;
findhash(buffer, ptr0 - buffer);
// Print out end time for word
time(&end2);
printf("\n\ntime : %f minutes.\n", difftime(end2, start2)/60);
// Close results file
fprintf(fout,"</NIDFUNCLIST>\n");
fflush(fout);
fclose(fout);
}
{ // Write out toplevel word, for resuming a run from last first word
FILE *fpt;
if ((fpt = fopen("nidstatus.tmp", "wt")) != NULL) {
fprintf(fpt,"%s",buffer+prefixlen);
fclose(fpt);
}
}
}
time(&end);
printf("\n\nhash count : %d\n", hash_count);
printf("dictionary words (firstword) : %d\n", dicfirstword.dict_count);
printf("dictionary words (main) : %d\n", dicmain.dict_count);
printf("\n\ntime : %f seconds.\n\n", difftime(end, start));
return 0;
}
i also have a sha12psp attack program and it does work correctly if built with vc6 debug, vc6 release, vc7 debug, vc71 debug, vc8 debug.loser wrote:yeh i noticed that in 'release config' in msvc++ it didnt work correctly, but in 'debug config' it did. after adding the memsets to buffer and buffer2 at the top it seemed to work. that was more of a quick fix tho; this part you point out is prolly what really needs fixing