#include #include #include #include static unsigned int CSStab0[11]={5,0,1,2,3,4,0,1,2,3,4}; static unsigned char CSStab1[256]= { 0x33,0x73,0x3b,0x26,0x63,0x23,0x6b,0x76,0x3e,0x7e,0x36,0x2b,0x6e,0x2e,0x66,0x7b, 0xd3,0x93,0xdb,0x06,0x43,0x03,0x4b,0x96,0xde,0x9e,0xd6,0x0b,0x4e,0x0e,0x46,0x9b, 0x57,0x17,0x5f,0x82,0xc7,0x87,0xcf,0x12,0x5a,0x1a,0x52,0x8f,0xca,0x8a,0xc2,0x1f, 0xd9,0x99,0xd1,0x00,0x49,0x09,0x41,0x90,0xd8,0x98,0xd0,0x01,0x48,0x08,0x40,0x91, 0x3d,0x7d,0x35,0x24,0x6d,0x2d,0x65,0x74,0x3c,0x7c,0x34,0x25,0x6c,0x2c,0x64,0x75, 0xdd,0x9d,0xd5,0x04,0x4d,0x0d,0x45,0x94,0xdc,0x9c,0xd4,0x05,0x4c,0x0c,0x44,0x95, 0x59,0x19,0x51,0x80,0xc9,0x89,0xc1,0x10,0x58,0x18,0x50,0x81,0xc8,0x88,0xc0,0x11, 0xd7,0x97,0xdf,0x02,0x47,0x07,0x4f,0x92,0xda,0x9a,0xd2,0x0f,0x4a,0x0a,0x42,0x9f, 0x53,0x13,0x5b,0x86,0xc3,0x83,0xcb,0x16,0x5e,0x1e,0x56,0x8b,0xce,0x8e,0xc6,0x1b, 0xb3,0xf3,0xbb,0xa6,0xe3,0xa3,0xeb,0xf6,0xbe,0xfe,0xb6,0xab,0xee,0xae,0xe6,0xfb, 0x37,0x77,0x3f,0x22,0x67,0x27,0x6f,0x72,0x3a,0x7a,0x32,0x2f,0x6a,0x2a,0x62,0x7f, 0xb9,0xf9,0xb1,0xa0,0xe9,0xa9,0xe1,0xf0,0xb8,0xf8,0xb0,0xa1,0xe8,0xa8,0xe0,0xf1, 0x5d,0x1d,0x55,0x84,0xcd,0x8d,0xc5,0x14,0x5c,0x1c,0x54,0x85,0xcc,0x8c,0xc4,0x15, 0xbd,0xfd,0xb5,0xa4,0xed,0xad,0xe5,0xf4,0xbc,0xfc,0xb4,0xa5,0xec,0xac,0xe4,0xf5, 0x39,0x79,0x31,0x20,0x69,0x29,0x61,0x70,0x38,0x78,0x30,0x21,0x68,0x28,0x60,0x71, 0xb7,0xf7,0xbf,0xa2,0xe7,0xa7,0xef,0xf2,0xba,0xfa,0xb2,0xaf,0xea,0xaa,0xe2,0xff }; static unsigned char CSStab2[256]= { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x09,0x08,0x0b,0x0a,0x0d,0x0c,0x0f,0x0e, 0x12,0x13,0x10,0x11,0x16,0x17,0x14,0x15,0x1b,0x1a,0x19,0x18,0x1f,0x1e,0x1d,0x1c, 0x24,0x25,0x26,0x27,0x20,0x21,0x22,0x23,0x2d,0x2c,0x2f,0x2e,0x29,0x28,0x2b,0x2a, 0x36,0x37,0x34,0x35,0x32,0x33,0x30,0x31,0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38, 0x49,0x48,0x4b,0x4a,0x4d,0x4c,0x4f,0x4e,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, 0x5b,0x5a,0x59,0x58,0x5f,0x5e,0x5d,0x5c,0x52,0x53,0x50,0x51,0x56,0x57,0x54,0x55, 0x6d,0x6c,0x6f,0x6e,0x69,0x68,0x6b,0x6a,0x64,0x65,0x66,0x67,0x60,0x61,0x62,0x63, 0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x76,0x77,0x74,0x75,0x72,0x73,0x70,0x71, 0x92,0x93,0x90,0x91,0x96,0x97,0x94,0x95,0x9b,0x9a,0x99,0x98,0x9f,0x9e,0x9d,0x9c, 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x89,0x88,0x8b,0x8a,0x8d,0x8c,0x8f,0x8e, 0xb6,0xb7,0xb4,0xb5,0xb2,0xb3,0xb0,0xb1,0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8, 0xa4,0xa5,0xa6,0xa7,0xa0,0xa1,0xa2,0xa3,0xad,0xac,0xaf,0xae,0xa9,0xa8,0xab,0xaa, 0xdb,0xda,0xd9,0xd8,0xdf,0xde,0xdd,0xdc,0xd2,0xd3,0xd0,0xd1,0xd6,0xd7,0xd4,0xd5, 0xc9,0xc8,0xcb,0xca,0xcd,0xcc,0xcf,0xce,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf6,0xf7,0xf4,0xf5,0xf2,0xf3,0xf0,0xf1, 0xed,0xec,0xef,0xee,0xe9,0xe8,0xeb,0xea,0xe4,0xe5,0xe6,0xe7,0xe0,0xe1,0xe2,0xe3 }; static unsigned char CSStab3[512]= { 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff, 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff,0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff }; static unsigned char CSStab4[256]= { 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0,0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0, 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8,0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8, 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4,0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4, 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec,0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc, 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2,0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2, 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea,0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa, 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6,0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6, 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee,0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe, 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1,0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1, 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9,0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9, 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5,0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5, 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed,0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd, 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3,0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3, 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb,0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb, 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7,0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7, 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef,0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff }; void CSStitlekey1(unsigned char *key,unsigned char *im) { unsigned int t1,t2,t3,t4,t5,t6; unsigned char k[5]; int i; t1=im[0]|0x100; t2=im[1]; t3=im[2] | (im[3]<<8) | (im[4]<<16); t4=t3&7; t3=t3*2+8-t4; t5=0; for(i=0;i<5;i++) { t4=CSStab2[t2]^CSStab3[t1]; t2=t1>>1; t1=((t1&1)<<8)^t4; t4=CSStab4[t4]; t6=(((((((t3>>3)^t3)>>1)^t3)>>8)^t3)>>5)&0xff; t3=(t3<<8)|t6; t6=CSStab4[t6]; t5+=t6+t4; k[i]=t5&0xff; t5>>=8; } for(i=9;i>=0;i--) key[CSStab0[i+1]]=k[CSStab0[i+1]]^CSStab1[key[CSStab0[i+1]]]^key[CSStab0[i]]; } /******************************************************** * * The CSS Hash reversal * * Devised and written by Frank A. Stevenson * * ( frank@funcom.com ) * Released on a GPL license * ********************************************************/ #define K1TABLEWIDTH 10 /* simple function to convert hex bytes to int */ /* note: will give random results if nonhex digits are input */ static char hexdigits[17] = "0123456789abcdef\0"; static int HexByteToInt( const char *pNumber ) { char ch; int r; ch = tolower( pNumber[0] ); r = 16 * (int)( strchr( hexdigits, ch ) - hexdigits ); ch = tolower( pNumber[1] ); r+= (int)( strchr( hexdigits, ch ) - hexdigits ); return r & 0x0ff; /* invalid input will have produce garbage */ } /* * Simple function to test if a candidate key produces the given hash */ void investigate( unsigned char* hash, unsigned char *k ) { unsigned char im2[6]; unsigned char pkey[6]; memcpy( im2, hash, 5 ); im2[5] = 0; memcpy( pkey, k, 5 ); pkey[5] = 0; CSStitlekey1( im2, pkey ); if( memcmp( im2, pkey, 5 ) == 0 ) { printf( " Possible tmp key %02x %02x %02x %02x %02x\n", k[0], k[1], k[2], k[3], k[4] ); } } /* Main function */ int main( int argc, char* argv[] ) { unsigned char A[5] = { 0,0,0,0,0 }; /* hashed disk key - unput to mangle cipher */ unsigned char B[5] = { 0,0,0,0,0 }; /* Second Stage of mangle cipher */ unsigned char C[5] = { 0,0,0,0,0 }; /* Output Stage of mangle cipher - IntermediateKey */ unsigned char k[5] = { 0,0,0,0,0 }; /* Mangling cipher key - Also output from CSS( C ) */ unsigned char out1[5]; /* five first output bytes of LFSR1 */ unsigned char out2[5]; /* five first output bytes of LFSR2 */ unsigned int lfsr1a; /* upper 9 bits of LFSR1 */ unsigned int lfsr1b; /* lower 8 bits of LFSR1 */ unsigned int tmp, tmp2, tmp3, tmp4,tmp5; int i,j; unsigned int nStepA; /* iterator for LFSR1 start state */ unsigned int nStepB; /* iterator for possible B[0] */ unsigned int nTry; /* iterator for K[1] possibilities */ unsigned int nPossibleK1; /* #of possible K[1] values */ unsigned char* K1table; /* Lookup table for possible K[1] */ unsigned int* BigTable; /* LFSR2 startstate indexed by 1,2,5 output byte */ /* Greeting */ printf( "CSS hash finder - gobbles memory ( 64 MB RAM ) Good luck\n\n" ); /* Check arguments */ if( argc != 6 ) { printf( "Usage: %s xx xx xx xx xx ( Hashed Disk key )\n", argv[0] ); return -1; } /* Convert input arguments to hash */ for( i = 0; i < 5 ; i++ ) { A[ i ] = HexByteToInt( argv[i+1] ); } printf( "Searching for hash: %02x %02x %02x %02x %02x\n", A[0], A[1], A[2], A[3], A[4] ); /* * Prepare tables for hash reversal */ /* initialize lookup tables for k[1] */ printf( "Initializing k[1] lookup table\n"); K1table = malloc( 65536 * K1TABLEWIDTH ); memset( K1table, 0 , 65536 * K1TABLEWIDTH ); if( K1table == NULL ) { printf( "Out of memory error, damn you should see what I will malloc next :-)\n" ); exit( -1 ); } tmp = A[0] ^ CSStab1[ A[1] ]; for( i = 0 ; i < 256 ; i++ ) /* k[1] */ { tmp2 = CSStab1[ tmp ^ i ]; /* CSStab1[ B[1] ]*/ for( j = 0 ; j < 256 ; j++ ) /* B[0] */ { tmp3 = j ^ tmp2 ^ i; /* C[1] */ tmp4 = K1table[ K1TABLEWIDTH * ( 256 * j + tmp3 ) ]; /* count of entries here */ tmp4++; if( tmp4 == K1TABLEWIDTH ) { printf( "Table disaster %d\n", tmp4 ); } if( tmp4 < K1TABLEWIDTH ) K1table[ K1TABLEWIDTH * ( 256 * j + tmp3 ) + tmp4 ] = i; K1table[ K1TABLEWIDTH * ( 256 * j + tmp3 ) ] = tmp4; } } /* Initing our Really big table */ printf( "Initializing and clearing 64MB of RAM\n"); BigTable = malloc( 16777216 * sizeof(int) ); memset( BigTable, 0 , 16777216 * sizeof(int) ); if( K1table == NULL ) { printf( "Out of memory error. As if this wouldn't hurt\n" ); exit( -1 ); } tmp3 = 0; printf( "Calculating big table. Wait, this takes time\n"); printf( "--------------------------------\n" ); for( i = 0 ; i < 16777216 ; i++ ) { if( (i & 0x07ffff) == 0 ) { printf( "#" ); fflush( stdout ); } tmp = (( i + i ) & 0x1fffff0 ) | 0x8 | ( i & 0x7 ); for( j = 0 ; j < 5 ; j++ ) { tmp2=((((((( tmp>>3 )^tmp)>>1)^tmp)>>8)^tmp)>>5)&0xff; tmp =(tmp<<8)|tmp2; out2[j] = CSStab4[ tmp2 ]; } j = ( out2[0] << 16 ) | ( out2[1] << 8 ) | out2[4]; BigTable[j] = i; } printf( "\n" ); /* * We are done initing, now reverse hash */ printf( "Table init completed, now reversing hash\n\n" ); tmp5 = A[0] ^ CSStab1[ A[1] ]; for( nStepA = 0 ; nStepA < 65536 ; nStepA ++ ) { lfsr1a = 0x100 | ( nStepA >> 8 ); lfsr1b = nStepA & 0xff; /* Generate 5 first output bytes from lfsr1 */ for( i = 0 ; i < 5 ; i++ ) { tmp = CSStab2[ lfsr1b ] ^ CSStab3[ lfsr1a ]; lfsr1b = lfsr1a >> 1; lfsr1a = ((lfsr1a&1)<<8) ^ tmp; out1[ i ] = CSStab4[ tmp ]; } /* cumpute and cache some variables */ C[0] = nStepA >> 8; C[1] = nStepA & 0xff; tmp = A[3] ^ CSStab1[ A[4] ]; tmp2 = CSStab1[ A[0] ]; /* Search through all possible B[0] */ for( nStepB = 0 ; nStepB < 256 ; nStepB++ ) { /* reverse parts of the mangling cipher */ B[0] = nStepB; k[0] = CSStab1[ B[0] ] ^ C[0]; B[4] = B[0] ^ k[0] ^ tmp2; k[4] = B[4] ^ tmp; nPossibleK1 = K1table[ K1TABLEWIDTH * (256 * B[0] + C[1]) ]; /* Try out all possible values for k[1] */ for( nTry = 0 ; nTry < nPossibleK1 ; nTry++ ) { k[1] = K1table[ K1TABLEWIDTH * (256 * B[0] + C[1]) + nTry + 1 ]; B[1] = tmp5 ^ k[1]; /* reconstruct output from LFSR2 */ tmp3 = ( 0x100 + k[0] - out1[0] ); out2[0] = tmp3 & 0xff; tmp3 = tmp3 & 0x100 ? 0x100 : 0xff; tmp3 = ( tmp3 + k[1] - out1[1] ); out2[1] = tmp3 & 0xff; tmp3 = ( 0x100 + k[4] - out1[4] ); out2[4] = tmp3 & 0xff; /* Can be 1 off */ /* test first possible out2[4] */ tmp4 = ( out2[0] << 16 ) | ( out2[1] << 8 ) | out2[4]; tmp4 = BigTable[ tmp4 ]; C[2] = tmp4 & 0xff; C[3] = ( tmp4 >> 8 ) & 0xff; C[4] = ( tmp4 >> 16 ) & 0xff; B[3] = CSStab1[ B[4] ] ^ k[4] ^ C[4]; k[3] = A[2] ^ CSStab1[ A[3] ] ^ B[3]; B[2] = CSStab1[ B[3] ] ^ k[3] ^ C[3]; k[2] = A[1] ^ CSStab1[ A[2] ] ^ B[2]; if( ( B[1] ^ CSStab1[ B[2] ] ^ k[ 2 ] ) == C[ 2 ] ) investigate( &A[0] , &C[0] ); /* Test second possible out2[4] */ out2[4] = ( out2[4] + 0xff ) & 0xff; tmp4 = ( out2[0] << 16 ) | ( out2[1] << 8 ) | out2[4]; tmp4 = BigTable[ tmp4 ]; C[2] = tmp4 & 0xff; C[3] = ( tmp4 >> 8 ) & 0xff; C[4] = ( tmp4 >> 16 ) & 0xff; B[3] = CSStab1[ B[4] ] ^ k[4] ^ C[4]; k[3] = A[2] ^ CSStab1[ A[3] ] ^ B[3]; B[2] = CSStab1[ B[3] ] ^ k[3] ^ C[3]; k[2] = A[1] ^ CSStab1[ A[2] ] ^ B[2]; if( ( B[1] ^ CSStab1[ B[2] ] ^ k[ 2 ] ) == C[ 2 ] ) investigate( &A[0] , &C[0] ); } } } free( K1table ); free( BigTable ); return( 0 ); }