int ktup_comparison_hasch ( char *i_seq1, char *i_seq2, const int ktup) { /*Ktup comparison adapted from Rob Edgar, NAR, vol32, No1, 381, 2004*/ /*1: hasch sequence 1 2: Count the number of seq2 ktup found in seq1 */ char c; int key; static HaschT*H1; static char *pseq; Hasch_entry *e; char *s; int l, ls; int p, a, max_dist=-1; double score=0; if (!strm (i_seq1, pseq)) { if (H1) { hdestroy (H1, declare_ktup_hasch_data, free_ktup_hasch_data); string2key (NULL, NULL); } H1=hasch_sequence ( i_seq1, ktup); vfree (pseq);pseq=(char*)vcalloc ( strlen (i_seq1)+1, sizeof (char)); sprintf ( pseq, "%s", i_seq1); } ls=l=strlen (i_seq2); s=i_seq2; p=0; while (ls>ktup) { c=s[ktup];s[ktup]='\0'; key=string2key (s, NULL); e=hsearch (H1,key,FIND, declare_ktup_hasch_data, free_ktup_hasch_data); if ( e==NULL); else if ( max_dist==-1)score++; else { for ( a=1; a<=(e->data)->list[1]; a++) if (FABS((p-(e->data)->list[a]))<=max_dist) {score++; break;} } s[ktup]=c;s++;p++;ls--; } score/=(l-ktup); score=(log(0.1+score)-log(0.1))/(log(1.1)-log(0.1)); if ( score>100) score=100; return (int)(score*100); }
HaschT* hasch_sequence ( char *seq1, int ktup) { char c; int key, offset=0, ls; HaschT *H; Hasch_entry *e; H=hcreate ( strlen (seq1), declare_ktup_hasch_data, free_ktup_hasch_data); ls=strlen (seq1); while (ls>=(ktup)) { c=seq1[ktup];seq1[ktup]='\0'; key=string2key (seq1, NULL); e=hsearch (H,key,FIND, declare_ktup_hasch_data, free_ktup_hasch_data); if (e==NULL) { e=hsearch (H,key,ADD,declare_ktup_hasch_data,free_ktup_hasch_data); (e->data)->list[++(e->data)->list[1]+1]=offset; } else { if ((e->data)->list[0]==((e->data)->list[1]+2)){(e->data)->list[0]+=10;(e->data)->list=(int*)vrealloc ((e->data)->list,(e->data)->list[0]*sizeof (int));} (e->data)->list[++(e->data)->list[1]+1]=offset; } seq1[ktup]=c;seq1++;ls--; offset++; } return H; }
int string2key (char *s, Char_node *n) { static Char_node *root; if ( !root)root=declare_char_node (DECLARE); if ( n==NULL && s==NULL) { declare_char_node (FREE_STACK); } else if (n==NULL) { return string2key(s, root); } else if ( s[0]=='\0') { return n->key; } else { return string2key(s+1, (n->c[(int)s[0]])?(n->c[(int)s[0]]):(n->c[(int)s[0]]=declare_char_node (DECLARE))); } return 0; }
int krb_verify_kdcrep(KRB_CONTEXT* krb_ctx, KrbKDCREP* kdc_rep, int msgtype) { ENCKDCREPPart* reppart; KrbENCKey* key; rdpBlob* decmsg; uint8 tag; tag = 0; key = NULL; /* Verify everything */ if((kdc_rep->pvno != KRB_VERSION) || (kdc_rep->type != msgtype) || strcasecmp(kdc_rep->cname, krb_ctx->cname) || strcasecmp(kdc_rep->realm, krb_ctx->realm)) { krb_ctx->state = KRB_PACKET_ERROR; return -1; } /* decrypt enc-part */ decmsg = xnew(rdpBlob); if(krb_ctx->askey->enctype != kdc_rep->enc_part.enctype && msgtype == KRB_TAG_ASREP) { freerdp_blob_free(&(krb_ctx->askey->skey)); xfree(krb_ctx->askey); krb_ctx->askey = string2key(&(krb_ctx->passwd), kdc_rep->enc_part.enctype); } krb_ctx->askey->enctype = kdc_rep->enc_part.enctype; decmsg = crypto_kdcmsg_decrypt(&(kdc_rep->enc_part.encblob), krb_ctx->askey, 8); //RFC4757 section 3 for msgtype (T=8) if(msgtype == KRB_TAG_ASREP) { key = krb_ctx->askey; tag = 25; } else if (msgtype == KRB_TAG_TGSREP) { key = krb_ctx->tgskey; tag = 26; } /* KDC-REP-PART decode */ if(decmsg == NULL || ((reppart = krb_decode_enc_reppart(decmsg, tag)) == NULL)) { krb_ctx->state = KRB_PACKET_ERROR; return -1; } freerdp_blob_free(decmsg); xfree(decmsg); /* Verify KDC-REP-PART */ if(reppart->nonce != krb_ctx->nonce || strcasecmp(reppart->realm, krb_ctx->realm) || strcasecmp(reppart->sname, krb_ctx->sname)) { krb_free_reppart(reppart); xfree(reppart); krb_ctx->state = KRB_PACKET_ERROR; return -1; } /* save stuff */ krb_ctx->clockskew = reppart->authtime - krb_ctx->ctime; //Used to synchronize clocks krb_save_ticket(krb_ctx, kdc_rep); freerdp_blob_copy(&(key->skey), &(reppart->key.skey)); key->enctype = reppart->key.enctype; krb_free_reppart(reppart); xfree(reppart); return 0; }
void krb_asreq_send(KRB_CONTEXT* krb_ctx, uint8 errcode) { KrbASREQ* krb_asreq; PAData** pa_data; KrbENCData enc_data; KrbENCKey* enckey; STREAM* s; STREAM* paenc; rdpBlob msg; rdpBlob* encmsg; uint32 curlen, totlen, pai; uint8 *bm; bm = NULL; totlen = pai = 0; krb_asreq = krb_asreq_new(krb_ctx, errcode); pa_data = krb_asreq->padata; enckey = NULL; s = stream_new(2048); paenc = stream_new(100); //Begin write asn1 data reversely into stream stream_seek(s, 1024); stream_seek(paenc, 99); /* KDC-REQ-BODY (TAG 4) */ totlen += krb_encode_req_body(s, &(krb_asreq->req_body), krb_asreq->type); totlen += krb_encode_contextual_tag(s, 4, totlen); /* padata = PA-ENC-TIMESTAMP */ if(errcode != 0) { freerdp_blob_alloc(&msg, 21); memcpy(msg.data, "\x30\x13\xa0\x11\x18\x0f", 6); // PA-ENC-TS-ENC without optional pausec memcpy(((uint8*) msg.data) + 6, krb_asreq->req_body.from, 15); enckey = string2key(&(krb_ctx->passwd), krb_ctx->enctype); encmsg = crypto_kdcmsg_encrypt(&msg, enckey, 1); //RFC4757 section 3 for msgtype (T=1) enc_data.enctype = enckey->enctype; enc_data.kvno = -1; enc_data.encblob.data = encmsg->data; enc_data.encblob.length = encmsg->length; curlen = krb_encode_encrypted_data(paenc, &enc_data); freerdp_blob_free(&msg); msg.data = paenc->p; msg.length = curlen; /* padata = PA-ENC-TIMESTAMP */ (*(pa_data + pai))->type = 2; (*(pa_data + pai))->value = msg; pai++; freerdp_blob_free(encmsg); xfree(encmsg); } freerdp_blob_alloc(&msg, 7); memcpy(msg.data, "\x30\x05\xa0\03\x01\x01", 6); // asn1 data *((uint8*)msg.data + 6) = krb_asreq->pa_pac_request; /* padata = PA-PAC-REQUEST */ (*(pa_data + pai))->type = 128; (*(pa_data + pai))->value = msg; *(pa_data + ++pai) = NULL; /* padata (TAG 3) */ curlen = krb_encode_padata(s, pa_data); totlen += curlen + krb_encode_contextual_tag(s, 3, curlen); /* MSGTYPE = AS-REQ (TAG 2) */ totlen += krb_encode_uint8(s, 2, krb_asreq->type); /* KERBEROS PROTOCOL VERSION NO (TAG 1)*/ totlen += krb_encode_uint8(s, 1, krb_asreq->pvno); totlen += krb_encode_sequence_tag(s, totlen); totlen += krb_encode_application_tag(s, krb_asreq->type, totlen); totlen += krb_encode_recordmark(s, totlen); /* READY SEND */ krb_tcp_send(krb_ctx, s->p, totlen); /* save stuff */ krb_ctx->askey = enckey; krb_ctx->nonce = krb_asreq->req_body.nonce; xfree(krb_ctx->sname); krb_ctx->sname = xstrdup(krb_asreq->req_body.sname); krb_ctx->ctime = get_local_time(krb_asreq->req_body.from); krb_ctx->state = KRB_ASREQ_OK; /* clean up */ freerdp_blob_free(&msg); stream_free(s); stream_free(paenc); krb_free_asreq(krb_asreq); xfree(krb_asreq); }
int main(int argc, char *argv[]) { files_t *files = NULL; // scan int outdirlen = 0, curr_file = 0, input_total_files = 0; u8 filedir[PATHSZ + 1] = "", outdir[PATHSZ + 1] = "", *p = NULL; u32 bufflen, filelen; int i, forceenc = 0, encver = 1; u8 *filebuff, *buff, *in_file, *out_file; setbuf(stdout, NULL); setbuf(stderr, NULL); fputs("\n" "Race WTCC files encrypter/decrypter " VER "\n" "by Luigi Auriemma\n" "e-mail: [email protected]\n" "web: aluigi.org\n" "\n", stdout); #ifdef WIN32 // scan + gui mywnd = GetForegroundWindow(); if(GetWindowLong(mywnd, GWL_WNDPROC)) { for(i = 1; i < argc; i++) { if(((argv[i][0] != '-') && (argv[i][0] != '/')) || (strlen(argv[i]) != 2)) { break; } } i = 2 - (argc - i); if(i > 0) { fprintf(stderr, "- GUI mode activated, remember that the tool works also from command-line\n" " where are available various other options and the encryption mode\n" "\n"); buff = calloc(argc + i + 1, sizeof(char *)); if(!buff) STD_ERR; memcpy(buff, argv, sizeof(char *) * argc); argv = (void *)buff; argc -= (2 - i); if(i >= 2) argv[argc + 0] = get_file("select the input file to decrypt, type \"\" for the whole folder and subfolders", 1); if(i >= 1) argv[argc + 1] = get_file("select the output file or folder (type \"\") where decrypting the files", 1); // multi is not used, needed for "" argc += 2; } } #endif if(argc < 3) { printf("\n" "Usage: %s [options] <input_file/folder> <output_file/folder>\n" "\n" "Options:\n" "-o overwrite output file if already exists without prompting\n" "-v VER specify the file version for encryption, default %u\n" "-e d/e this option is here only for compatibility reasons, it allows you\n" " to force decryption 'd' or encryption 'e'\n" "-k GAME select the specific key for the specific GAME which uses a non\n" " default key, the following is the list of games (example -k volvo):\n" " raceroom\n" " volvo\n" "-F W filter the input files using the W wildcard, example -F \"*.gmt\"\n" "-V debug\n" "\n" "The encryption or decryption function is automatically chosen by the tool\n" "after having checked if the file is encrypted or not, use -e to override it.\n" "Note that -k volvo worked also with some old versions of RaceRoom.\n" "For the JCA files of RaceRoom use QuickBMS and the relative script:\n" " http://quickbms.aluigi.org\n" "\n", argv[0], encver); std_err(""); } argc -= 2; for(i = 1; i < argc; i++) { if(((argv[i][0] != '-') && (argv[i][0] != '/')) || (strlen(argv[i]) != 2)) { printf("\nError: recheck your options (%s is not valid)\n", argv[i]); std_err(""); } switch(argv[i][1]) { case 'o': overwrite = 1; break; case 'v': encver = atoi(argv[++i]); break; case 'e': forceenc = tolower(argv[++i][0]); break; case 'k': customkey = argv[++i]; break; case 'F': filter_in_files = argv[++i]; break; case 'V': debug = 1; break; default: { printf("\nError: wrong command-line argument (%s)\n\n", argv[i]); std_err(""); break; } } } if(customkey) { if(!stricmp(customkey, "volvo")) { customkey = (u8 *)volvo_key; customkeylen = sizeof(volvo_key); } else if(!stricmp(customkey, "roomrace") || !stricmp(customkey, "raceroom")) { customkey = (u8 *)raceroom_key; customkeylen = sizeof(raceroom_key); } else { printf("- unknown game specified with the -k option, I will consider it a hex key\n"); customkey = strdup(customkey); // not needed but good customkeylen = string2key(customkey); } } in_file = argv[argc]; out_file = argv[argc + 1]; // scan #ifdef WIN32 if(GetWindowLong(mywnd, GWL_WNDPROC) && fin[strlen(fin) + 1]) { // check if there are files after the folder i = snprintf(filedir, PATHSZ, "%s%c", fin, PATHSLASH); if((i < 0) || (i >= PATHSZ)) std_err(""); for(p = fin;;) { p += strlen(p) + 1; if(!*p) break; mystrcpy(filedir + i, p, PATHSZ - i); add_files(filedir, 0, NULL); } } else #endif if(check_is_dir(fin)) { printf("- start the scanning of the input folder: %s\n", fin); //strcpy(filedir, "."); // if you enable it you must add " + 2" to each add_files mystrcpy(filedir, fin, PATHSZ); recursive_dir(filedir, PATHSZ); } if(filedir[0]) { files = add_files(NULL, 0, &input_total_files); curr_file = 0; if(input_total_files <= 0) { printf("\nError: the input folder is empty\n"); myexit(-2); } } if(check_is_dir(fout)) { outdirlen = snprintf(outdir, PATHSZ, "%s%c", fout, PATHSLASH); if((outdirlen < 0) || (outdirlen >= PATHSZ)) std_err(""); fout = outdir; } int finlen = strlen(fin); redo_scan: if(files) { fin = files[curr_file].name; curr_file++; fprintf(stderr, "\n"); } if(outdirlen) { if(files) { for(p = fin + finlen; *p; p++) { if((*p != '\\') && (*p != '/')) break; } } else { p = strrchr(fin, '\\'); if(!p) p = strrchr(fin, '/'); if(p) { p++; } else { p = fin; } } mystrcpy(outdir + outdirlen, p, PATHSZ - outdirlen); } redo: filebuff = fd_read(in_file, &filelen); if((memcmp(filebuff, "\x0f\xb1\xff\xff", 4) && memcmp(filebuff, "\x1f\x8b\x08", 3) && (forceenc != 'd')) || (forceenc == 'e')) { printf("- perform encryption:\n"); buff = wtcc_encrypt(filebuff, filelen, &bufflen, encver); } else { printf("- perform decryption:\n"); buff = wtcc_decrypt(filebuff, filelen, &bufflen); } if(!buff && auto_try) { auto_try++; // 1 switch(auto_try) { case 2: customkey = (u8 *)raceroom_key; customkeylen = sizeof(raceroom_key); break; case 3: customkey = (u8 *)volvo_key; customkeylen = sizeof(volvo_key); break; default: auto_try = 0; break; } free(filebuff); printf("\n"); if(auto_try) goto redo; } fd_write(out_file, buff, bufflen); printf("- %u bytes written\n", bufflen); if(files && (curr_file < input_total_files)) { // scan if(!((buff >= filebuff) && (buff <= (filebuff + 16)))) free(buff); free(filebuff); goto redo_scan; } fprintf(stderr, "- done\n"); std_err(""); // scan return(0); }