#include #include char *dictionary = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; char *extensions[] = {"",".0BJ",".ATT",".BIN",".BUF",".CHR",".CUR",".DAT",".EVT",".FAC",".FWL",".GND",".HED",".ICN",".INT",".M",".MOB",".MON",".NAM",".OBJ",".OUT",".PAL",".PTY",".RAW",".SKY",".SRF",".SWL",".TIL",".TXT",".VGA",".VOC",".WAL",".XEN"}; int extCount = 33; char *buf; unsigned int buflen; unsigned char c1, c2; unsigned long offset; unsigned int length; unsigned char xor=0x35; FILE *fi; unsigned int hashName(char* fname) { unsigned char h0, h1, h2, h3; unsigned int temp; h0 = h1 = 0; while (*fname != 0) { // swap h0 and h1 h2 = h1; h1 = h0; h0 = h2; // rotate left h2 = (((unsigned int)h0 << 1) & 0xff) | (((unsigned int)h1 >> 7) & 0xff); h3 = (((unsigned int)h1 << 1) & 0xff) | (((unsigned int)h0 >> 7) & 0xff); h0 = h2; h1 = h3; // calc toUpper(h1) h2 = (*fname++) & 0x7f; if (h2 >= 0x60) h2 = h2 - 0x20; // add char to h1 temp = ((unsigned int)h0 << 8) | (unsigned int)h1; temp = (temp + h2) & 0xffff; h0 = (temp >> 8) & 0xff; h1 = temp & 0xff; } return (h0 << 8) ^ h1; } int extract(char* name) { int i = 0; unsigned int hash = hashName(name); printf("Hash for '%s' is 0x%04x.\n", name, hash); for (i = 0; i < 8*buflen; i+=8) { if (((buf[i] & 0xff) == (hash & 0xFF)) && ((buf[i+1] & 0xFF) == (hash >> 8))) break; } if (i == 8*buflen) { printf("File not found: '%s'.\n", name); return 0; } i += 2; offset = (unsigned long)buf[i++] & 0xff; offset |= (((unsigned long)buf[i++]) << 8) & 0xff00; offset |= (((unsigned long)buf[i++]) << 16) & 0xff0000; length = (unsigned long)buf[i++] & 0xff; length |= (((unsigned long)buf[i++]) << 8) & 0xff00; printf("Entry #%d, offset=%06x, length=%04x\n", i, offset, length); FILE *fo = fopen(name, "wb"); fseek(fi, offset, SEEK_SET); for (i = 0; i < length; i++) { fputc((fgetc(fi) ^ xor) & 0xff, fo); } fclose(fo); } int extractHash(unsigned int hash) { int i = 0; // printf("Hash for '%s' is 0x%04x.\n", name, hash); for (i = 0; i < 8*buflen; i+=8) { if (((buf[i] & 0xff) == (hash & 0xFF)) && ((buf[i+1] & 0xFF) == (hash >> 8))) break; } if (i == 8*buflen) { printf("Hash not found: '%d'.\n", hash); return 0; } i += 2; offset = (unsigned long)buf[i++] & 0xff; offset |= (((unsigned long)buf[i++]) << 8) & 0xff00; offset |= (((unsigned long)buf[i++]) << 16) & 0xff0000; length = (unsigned long)buf[i++] & 0xff; length |= (((unsigned long)buf[i++]) << 8) & 0xff00; printf("Entry #%d, offset=%06x, length=%04x\n", i, offset, length); FILE *fo = fopen("hashed", "wb"); fseek(fi, offset, SEEK_SET); for (i = 0; i < length; i++) { fputc((fgetc(fi) ^ xor) & 0xff, fo); } fclose(fo); } void decode_buffer(unsigned char *buf, unsigned int l) { unsigned char al, ah=0xAC; int i; for (i = 0; i < l; i++) { al = buf[i]; al = (((int)al << 2) | ((int)al >> 6)) & 0xff; al = (al + ah) & 0xff; buf[i] = al; ah = (ah + 0x67) & 0xff; } } int main(int argc, char *argv[]) { int i; if (argc < 3) { printf("Syntax: %s infile.cc file.ext\n", argv[0]); exit(-1); } if (argc > 3) { char* digit = argv[3]; xor = 0; while (*digit >= '0' && *digit <='9') { xor = (xor * 10) + (*digit - '0'); digit++; } } fi = fopen(argv[1], "rb"); c1 = fgetc(fi); c2 = fgetc(fi); buflen = (unsigned int)c1 | ((unsigned int)c2 << 8); printf("%s contains %d files.\n", argv[1], buflen); buf = (unsigned char *)malloc(8 * buflen); fread(buf, 8, buflen, fi); decode_buffer(buf, 8*buflen); extract(argv[2]); // extractHash(46108); fclose(fi); free(buf); return 0; }