/*
* character-set based brute-forcing algorithm
* (c) 2004 by mimayin@aciiid.ath.cx
* Also posted on http://www.darkc0de.com/c0de/c/crunch.txt
* Not my code; if you are the author and want it removed, please contact me.
* to compile, g++ crunch.cpp -o crunch
*
* usage: ./crunch <from-len> <to-len> [charset] [-t [FIXED]@@@@] [-s startblock]
*
* e.g:
*
* ./crunch 3 7 abcdef
*
* ./crunch 1 5 1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM > alphaNumMixedCase_5.dic
*
* Plaintext (uncompressed) output exceeds 34Gb in 3 hrs on a P4 3.2, 4Gb RAM
* ./crunch 1 4 \`\~\!\@\#\$\%\^\&\*\(\)\_\+\-\=\[\]\{\}\;\'\:\"\,\.\/\<\>\?1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM > all_4.dic
*
*
* This example will compute all passwords between 3 and 7 chars
* using 'abcdef' as the character set and dump it to stdout.
*
* Options:
*
* -t [FIXED]@@@@ : allows you to specify a pattern, eg: @@god@@@@
* where the only the @'s will change
*
* -s : allows you to specify the starting string, eg: 03god22fs
*
*
* This code can be easily adapted for use in brute-force attacks
* against network services or cryptography.
*
* Compiles on: linux, ms visual c++, freebsd
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
char def_charset[] = "abcdefghijklmnopqrstuvwxyz";
unsigned int inc[128];
int finished(char *block, char *charset, char *templ)
{
unsigned int i;
if(templ[0]==0)
{
for(i=0;i<strlen(block);i++)
if(inc[i] < strlen(charset)-1) return FALSE;
}
else
{
for(i=0;i<strlen(block);i++)
if(templ[i]=='@' && (inc[i] < strlen(charset)-1)) return FALSE;
}
return TRUE;
}
void increment(char *block, int len, char *charset, char *templ)
{
int i;
for(i=strlen(block)-1;i>-1;i--)
{
if(templ[0]==0 || templ[i]=='@')
{
if(inc[i] < strlen(charset)-1)
{
inc[i]++;
block[i] = charset[inc[i]];
i=-1;
}
else
{
block[i] = charset[0];
inc[i] = 0;
}
}
else
{
}
}
}
void chunk(int start, int end, char *charset, char *templ, char *startblock)
{
int i,j,k,t;
char block[128];
if(end-start <0) return;
if(templ[0]==0) t=0;
else t=1;
for(i=start;i<=end;i++)
{
memset(block,0,sizeof(block));
for(j=0;j<i;j++)
{
if(startblock[0]==0)
{
if(t==0)
{
block[j] = charset[0];
inc[j] = 0;
}
else
{
if(templ[j]=='@')
{
block[j] = charset[0];
inc[j] = 0;
}
else block[j] = templ[j];
}
}
else
{
block[j] = startblock[j];
for(k=0;k<strlen(charset);k++)
if(block[j]==charset[k]) inc[j] = k;
}
}
printf("%s\n",block);
while(!finished(block,charset,templ))
{
increment(block,i,charset,templ);
printf("%s\n",block);
}
}
}
int main(int argc, char *argv[])
{
int i,j,flag,min,max;
char charset[256];
char templ[256];
char startblock[256];
if(argc<3)
{
printf("usage: %s <from-len> <to-len> [charset] [-t [FIXED]@@@@] [-s startblock]\n",argv[0]);
return 0;
}
memset(charset,0,sizeof(charset));
memset(templ,0,sizeof(templ));
memset(startblock,0,sizeof(startblock));
/* remove duplicate characters from charset */
if(argc>3)
{
for(i=0;i<strlen(argv[3]);i++)
{
flag = 0;
for(j=0;j<strlen(charset);j++)
if(argv[3][i] == charset[j]) flag = 1;
if(flag==0) strncat(charset,&argv[3][i],1);
}
}
else strncpy(charset,def_charset,strlen(def_charset));
min = atoi(argv[1]);
max = atoi(argv[2]);
for(i=1;i<argc-1;i++)
{
if(strncmp(argv[i],"-t",2)==0)
{
strncpy(templ,argv[i+1],strlen(argv[i+1]));
}
if(strncmp(argv[i],"-s",2)==0)
{
if(strlen(argv[i+1]) >min)
{
printf("Warning: starting length increased to %d.\n",strlen(argv[i+1]));
min = strlen(argv[i+1]);
}
if(strlen(argv[i+1]) <min)
{
printf("Warning: minimum length decreased to %d.\n",strlen(argv[i+1]));
min = strlen(argv[i+1]);
}
strncpy(startblock,argv[i+1],strlen(argv[i+1]));
}
}
chunk(min,max,charset,templ,startblock);
return 0;
}