int main(int argc, char* argv[]) { UCHAR seed[256]; UCHAR line[MAX_LINE+1]; UCHAR plain_text[MAX_TEXT+1]; UCHAR cipher_text[MAX_TEXT+1]; UCHAR comment[MAX_LINE+1]; UCHAR xored_text[MAX_TEXT+1]; int i, num; ULONG sweep, done = 0, iter; rc4_key key; FILE *fp; char** args = argv; int acount = argc; double time_taken; USHORT plain_text_len, cipher_text_len, text_len; USHORT cmd_line_project_id, file_check_sum = 0; USHORT completed_check_sum = 0; USHORT comment_len = 0; USHORT segments, start_segment; UCHAR* tag; UCHAR* value; int done_plain_text = 0; int done_cipher_text = 0; #if !defined(_MSDOS) && !defined(__OS2__) struct timeval tv_start,tv_end; #endif double keys_sec, run_time, start_time; int first = 1; #ifdef __OS2__ APIRET rc; #endif big_endian = ((char*)&test_endian)[0]; prog = argv[0]; #ifdef __OS2__ /* set priority class to IDLETIME */ rc = DosSetPriority(PRTYS_PROCESS, PRTYC_IDLETIME, 0, 0); if (rc != 0) { fprintf(stderr, "%s: unable to set priority, rc = %ld\n", prog, rc); exit(1); } #endif /* __OS2__ */ if (argc < 2) { usage(); exit(1); } if (args[1][0]=='-') { switch(args[1][1]) { case 'q': verbose = 0; break; case '\0': /* stdin = '-' */ acount++; args--; /* doesn't count as a flag */ break; default: fprintf(stderr,"invalid flag %s\n",args[1]); usage(); exit(1); } args++; acount--; } if (acount < 5) { usage(); exit(1); } if (!strcmp(args[1],"-")) { fp = stdin; } else { fp = fopen(args[1],"rb"); if (!fp) { fprintf(stderr,"error cannot open config file %s\n",args[1]); exit(2); } } num = sscanf(args[2],"%hx",&cmd_line_project_id); if (num < 1) { fprintf(stderr,"error: project-id should be a hexadecimal number\n\n"); usage(); exit(1); } if (strlen(args[3]) > 4) { fprintf(stderr,"error: start-key should be a 4 digit hexadecimal number\n\n"); usage(); exit(1); } i = byte_pack(seed, (UCHAR*) args[3], 2); if (i != 2) { fprintf(stderr,"error: start-key should be a 4 digit hexadecimal number\n\n"); usage(); exit(1); } seed[2] = seed[3] = seed[4] = 0; start_segment = (USHORT)seed[0]*256 + (USHORT)seed[1]; num = sscanf(args[4],"%hu",&segments); if (num < 1) { fprintf(stderr,"error: segments should be a decimal number\n\n"); usage(); exit(1); } sweep = (ULONG)segments << 8; while (!feof(fp)) { line[0] = '\0'; fgets(line, MAX_LINE, fp); strip_crlf(line); strip_comments(line); file_check_sum = checksum(file_check_sum, line); parse_line(line,&tag,&value); if (!tag || !*tag) { continue; } if (!strcasecmp(tag,"PLAIN-TEXT")) { if (done_plain_text) { fprintf(stderr, "config file error: should only have one PLAIN-TEXT field\n"); exit(2); } if (strlen(value) & 0x1 != 0) { fprintf(stderr, "config file error: PLAIN-TEXT field must be an even number of hex digits\n"); exit(2); } plain_text_len = byte_pack(plain_text, value, MAX_TEXT); if (plain_text_len == 0) { fprintf(stderr, "config file error: PLAIN-TEXT field must be hex digits\n"); exit(2); } done_plain_text = 1; } else if (!strcasecmp(tag,"CIPHER-TEXT")) { if (done_cipher_text) { fprintf(stderr, "config file error: should only have one CIPHER-TEXT field\n"); exit(2); } if (strlen(value) & 0x1 != 0) { fprintf(stderr, "config file error: CIPHER-TEXT field must be an even number of hex digits\n"); exit(2); } cipher_text_len = byte_pack(cipher_text, value, MAX_TEXT); if (cipher_text_len == 0) { fprintf(stderr, "config file error: CIPHER-TEXT field must be hex digits\n"); exit(2); } done_cipher_text = 1; } else if (!strcasecmp(tag,"COMMENT")) { char *rest = strtok(0, "\n"); /* ie to the end of string as there */ if (comment_len != 0) /* won't be a \n due to strip_crlf */ { fprintf(stderr, "config file error: should only have one COMMENT field\n"); exit(2); } strncpy(comment, value, MAX_LINE); if (rest) { comment_len = strlen(comment); strncat(comment," ", MAX_LINE - comment_len); comment_len++; strncat(comment, rest, MAX_LINE - comment_len); comment[MAX_LINE] = '\0'; } comment_len = strlen(comment); } else { fprintf(stderr,"config file error: unknown tag: %s\n",tag); exit(2); } } if (!done_plain_text) { fprintf(stderr,"config file error: no PLAIN-TEXT field\n"); exit(2); } if (!done_cipher_text) { fprintf(stderr,"config file error: no CIPHER-TEXT field\n"); exit(2); } if (plain_text_len != cipher_text_len) { fprintf(stderr,"config file warning: PLAIN-TEXT and CIPHER-TEXT are not the same length\n"); } text_len = plain_text_len < cipher_text_len ? plain_text_len : cipher_text_len; if (cmd_line_project_id != file_check_sum) { fprintf(stderr,"error: you have the wrong config file for project %04x (%04x)\n", cmd_line_project_id, file_check_sum); exit(1); } completed_check_sum = (( (ULONG)file_check_sum + (ULONG)start_segment + (ULONG)segments ) & 0xFFFFL); if (verbose) { fprintf(stderr,"PROJECT-ID\t%04x\n",file_check_sum); if (comment_len) fprintf(stderr,"COMMENT \t%s\n",comment); fprintf(stderr,"START-KEY\t%s\n",print_hex(seed,KEY_SIZE)); fprintf(stderr,"SEGMENTS\t%u (16M keys/segment)\n",segments); fprintf(stderr,"PLAIN-TEXT\t%s\n",print_hex(plain_text,text_len)); fprintf(stderr,"CIPHER-TEXT\t%s\n",print_hex(cipher_text,text_len)); fprintf(stderr,"TEXT-SIZE\t%d\n",text_len); fprintf(stderr,"256k keys per '.' printed, 1 segment per line, a segment = 16M keys\n"); fprintf(stderr,"LINES-TO-DO\t%d\n",segments); } /* pre-compute plain_text XOR cipher_text */ for (i=0; i<text_len; i++) { xored_text[i] = plain_text[i] ^ cipher_text[i]; } for (done=0; done<sweep; done++) { if (verbose) { if (first) { #if defined(_MSDOS) || defined(__OS2__) start_time = (double) clock()/CLOCKS_PER_SEC; #else gettimeofday(&tv_start,0); #endif } } for (iter=0; iter < 65536; iter++) { prepare_key(seed,KEY_SIZE,&key); if (rc4_eq(xored_text, text_len, &key)) { if (verbose) { fprintf(stderr,"\nFOUND-IT\t%s\n", print_hex(seed,KEY_SIZE)); instructions(); } printf("%04x %04x %04x %u %s\n",file_check_sum,completed_check_sum, start_segment,segments,print_hex(seed,KEY_SIZE)); exit(0); } inc_key(seed); } if (verbose) { if (first) { #if defined(_MSDOS) || defined(__OS2__) time_taken = ((double) clock()/CLOCKS_PER_SEC) - start_time; #else gettimeofday(&tv_end,0); time_taken = (double)(tv_end.tv_sec - tv_start.tv_sec); time_taken += ((double)(tv_end.tv_usec - tv_start.tv_usec)/1000000.0); #endif keys_sec = 65536.0 / time_taken; fprintf(stderr,"KEYS-PER-SEC\t%0.1lf keys/sec\n",keys_sec); fprintf(stderr,"EXPECTED-RUNNING-TIME\t"); run_time = sweep * time_taken; if (run_time < 60) { fprintf(stderr,"%0.1lf secs\n",run_time); } else if (run_time < 3600) { fprintf(stderr,"%0.1lf mins\n",run_time / 60); } else { fprintf(stderr,"%0.1lf hours\n",run_time / 3600); if (run_time > 180000) { fprintf(stderr,"in days: %0.1lf days\n",run_time / 86400); } } first = 0; } if ((done & 255L) == 0) { if (done > 0) fprintf(stderr,"]\n"); fprintf(stderr,"%sxxxxxx:[",print_hex(seed,2)); } if ((done & 3L) == 0) { fputc('.',stderr); } #ifdef __OS2__ fflush(stderr); /* needed to prevent buffering of stderr */ #endif } } if (verbose) { fprintf(stderr,"]\n"); instructions(); } printf("%04x %04x %04x %u no\n",file_check_sum,completed_check_sum, start_segment,segments); return 0; }
inline std::size_t operator () (T& result) { return byte_pack(result); }