/* Crack zipfile password using two-word combinations */ #include #include unsigned long crc_tbl[256]; #define CRC_POLY 0xedb88320L void init_crc_tbl(void) { int i, j; unsigned long x; for (i = 0; i < 256; i++) { x = i; for (j = 0; j < 8; j++) x = (x & 1) ? ((x>>1) ^ CRC_POLY) : (x>>1); crc_tbl[i] = x; } } /* init_crc_tbl */ void init_keys(unsigned char *pass, int passlen, unsigned long *key0p, unsigned long *key1p, unsigned long *key2p) { int i; unsigned long key0, key1, key2; key0 = 0x12345678L; key1 = 0x23456789L; key2 = 0x34567890L; for (i = 0; i < passlen; i++) { key0 = (key0>>8) ^ crc_tbl[(key0 ^ pass[i]) & 0xff]; key1 = (key1 + (key0 & 0xff)) * 134775813 + 1; key2 = (key2>>8) ^ crc_tbl[(key2 ^ (key1>>24)) & 0xff]; } *key0p = key0; *key1p = key1; *key2p = key2; } /* init_keys */ #define DATA_LEN 15 unsigned char data_bytes[DATA_LEN] = { 0x94, 0xc8, 0x31, 0x2a, 0xe3, 0x49, 0x0b, 0xdb, 0xa8, 0x10, 0xc2, 0x70, 0x9d, 0xfc, 0x10 }; #define PLAIN_START 11 unsigned char plain_bytes[DATA_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0xed, 0x9c, 0x5b }; int try_password(unsigned char *pass, int passlen, unsigned long key0, unsigned long key1, unsigned long key2) { int i, temp; for (i = 0; i < passlen; i++) { key0 = (key0>>8) ^ crc_tbl[(key0 ^ pass[i]) & 0xff]; key1 = (key1 + (key0 & 0xff)) * 134775813 + 1; key2 = (key2>>8) ^ crc_tbl[(key2 ^ (key1>>24)) & 0xff]; } for (i = 0; i < PLAIN_START; i++) { temp = key2 | 3; temp = ((temp * (temp - 1)) >> 8) ^ data_bytes[i]; key0 = key0>>8 ^ crc_tbl[(key0 ^ temp) & 0xff]; key1 = (key1 + (key0 & 0xff)) * 134775813 + 1; key2 = key2>>8 ^ crc_tbl[(key2 ^ key1>>24) & 0xff]; } for (; i < DATA_LEN; i++) { temp = key2 | 3; temp = (((temp * (temp - 1)) >> 8) & 0xff) ^ data_bytes[i]; if (temp != plain_bytes[i]) return 0; key0 = key0>>8 ^ crc_tbl[(key0 ^ temp) & 0xff]; key1 = (key1 + (key0 & 0xff)) * 134775813 + 1; key2 = key2>>8 ^ crc_tbl[(key2 ^ key1>>24) & 0xff]; } return 1; } /* try_password */ #define WORD_LEN 40 #define DICT_FILE "/usr/share/dict/words" int main() { FILE *first, *second; unsigned long key0, key1, key2, count; time_t start, end; int i, len; unsigned char word1[WORD_LEN], word2[WORD_LEN]; init_crc_tbl(); first = fopen(DICT_FILE, "r"); second = fopen(DICT_FILE, "r"); if (first == NULL || second == NULL) { printf("Can't open %s\n", DICT_FILE); return 1; } time(&start); count = 0; while (fgets(word1, WORD_LEN, first)) { len = strlen(word1); if (len > 0 && word1[len-1] == '\n') word1[--len] = '\0'; init_keys(word1, len, &key0, &key1, &key2); if (try_password(word1, 0, key0, key1, key2)) printf("Password: %s\n", word1); for (i = 0; i <= 99; i++) { len = sprintf(word2, "%d", i); if (try_password(word2, len, key0, key1, key2)) printf("Password: %s%s\n", word1, word2); } rewind(second); while (fgets(word2, WORD_LEN, second)) { count++; len = strlen(word2); if (len > 0 && word2[len-1] == '\n') word2[--len] = '\0'; if (try_password(word2, len, key0, key1, key2)) printf("Password: %s%s\n", word1, word2); } } time(&end); printf("Tried %.0f passwords/sec\n", count / difftime(end,start)); return 0; } /* main */