|
Impossible is not french
Applying a scoring method to guess the key
|
 Javascript
|
16 june 99
| by
Laurent
|
|
 |
Courtesy of Fravia's page of
reverse engineering
|
|
fra_00xx 990616 Laurent 1100 NA PC
|
Amazing work by Laurent, a Javascript Lizard that has turned into a javascript wizard :-)
Read, meditate, think. Humans can reach the stars, and reverse javascript. Enjoy!
| |
|
There is a crack, a crack in everything
That's how the light gets in
| |
Rating
|
( )Beginner ( )Intermediate ( )Advanced ( )Expert
| |
Impossible is not french
Applying a scoring method to guess the key
Written by
Laurent
In this essay I'll try to explain how I did to guess a working key for the
impossible entrance. Note that I said a working key, not the correct one. This is
because, even if that key works fine, it leads to a 404 page. So maybe it's not
the correct one.
Although I really think it's the correct one :)
A C compiler
im_poss1.htm
Your_target's_history (if any)
First of all, i have to admit that at first sight I really thought it was
really an impossible entrance.
It's only when I saw a post of sNw and DonQuijote saying that they were
working hard on it that I thought "Well, Impossible is not french, so why
not try it too".
The reason why I thought it was impossible is that from the cipher text you
have, you can obtain *whatever* plaintext you want. Of course, the key may be
quite long, but every plaintext is possible. Here is an example : Use the
following key and you'll get a nice plain text :
--->x i8#:mje^FV5 b-CgX@S.e7Sdxix<---
Of course this lead to very long and weird key, but there was no 'obvious'
way to guess key lenght or meaning, so i thought that it would be impossible to
guess the correct one.
So, when I read sNw and DonQuijote talking about trying to search for a key which could
give meaningfull words like 'location', 'window', 'navigate' and so on,
I wrote a little program which allowed me to extract a key given a know
plaintext and a cipher.
I run this program so it would give me every key for plaintext word to find
at every possible place in the cipher.
As you see it's quite easy but unfortunately it doesn't helped at all.
Actually, I wasn't expecting much result from this approach cause it would not
have been an impossible entrance at all. Imagine that the word 'location' would
have been in the plain text, that would have give us 8 letters of the key
at once ...Too easy.
Before going anyfurther I'd like to say that I did not tried the word 'navigate'
cause I think it's not working with Netscape products, so it would have
restricted access to micro$oft users only, what would have been a real shame :)
Anyway, I then wondered how they could have hidden those 'necessary' words ?
Was there any other way they could take you to another page without using
something like 'location' ?
Then I thought that maybe 'location' was actually made up of a concatenation of little string like :
"loc"+"ati"+"on" .... But then how could they pass that to eval ?
eval would only return the concatenated string, but not executing it....
Then it poped in my mind ... Of course .. they use another eval in their cypher.
it's something like eval(fin) ... where fin is a string = "'eval('+'loc'+'ation'+'='+xxx.htm'+')'". So the first eval
(the cyphered one) will return a full string which will be processed by the second eval(fin).
That sound quite smart :)
So I run my program to extract keys for 'eval'. I used a max key length of 12 (thanks DonQuijote:).
Well, as eval is not very long (4 char) I got lot of meaningless garbage :(
But I was quite sure I was on the good way .... Unfortunately,I had to browse
through 1071 (119*9) possible 'plaintext' to find the good one :(
Well, I sit down once again and thought that the good plain text should be
full of character like ",+,lo,loc,at,io,ht, ml and so on ...
So I modified my program to 'score' each plaintext depending on the number of
occurence of those character or mini-strings.
Bingo .... I got a plaintext with a score of 11 for a key length of 4 and 6
and a score of 8 for a key length of 12 :)
MoreOver the 12 char length key looks something like : _____rCrA___ ...
Upper and lower case toggling, CrA like 'Crack' :)
Here is the plain text I obtained and below is the original cipher text followed
by the key I applied :
;< / eval '+"o "ti" + " +'ef "'nE AcK. 'ml' < );
6gy.=gvlq:z91=uowwYsM+w86gyrQnzpPfI!7jFrBpWAy'H86jTJAlzly I!8lMNCoywG=H7~myrBpyF5aH~dSWYWSF2rkG!#HCoBnPDw@I~#fBtCkwep'E86g
_____rCrA________rCrA________rCrA________rCrA________rCrA________rCrA________rCrA________rCrA________rCrA________rCrA_____
I replaced the 'carriage return' character with the 'less than' (<) to improve readability.
Note that I wrote my program so that the _ char is used as 'unknow' key char.
So it does not decipher for this character.
We are on the good way ... We have 'o' and 'ti' from 'location 'ef'from maybe
'href' and 'ml' from 'html'.
Now it's quite easy. Just try to guess some cipher-plain text pair and fill
the gaps in the key.
I used the following :
1. the cipher 'f' should give a plain 'c' (after '+"o).
;< /* eval '+"oc "ti"< + ". +'ef' "'nE" AcK.h 'ml'+ < );<
_____rCrAc_______rCrAc_______rCrAc_______rCrAc_______rCrAc_______rCrAc_______rCrAc_______rCrAc_______rCrAc_______rCrAc___
2. the cipher 'B' should give a plain '+' (before "ti").
0;< /* eval l'+"oc +"ti"< ' + ". "+'ef' +"'nE" rAcK.h +'ml'+ "< );<
____ErCrAc______ErCrAc______ErCrAc______ErCrAc______ErCrAc______ErCrAc______ErCrAc______ErCrAc______ErCrAc______ErCrAc___
3. the cipher 'I' should give a 'a' or a '"' (after l'+"oc). It gives either H or K ... K is great ... it gives CrAcK
Well, you guess now how it work, so i won't bother typing all that.
Finally you get the right key ... %nEvErCrAcK%
Well, here below you'll find the program i used .. I tried to comment it as
much as possible, but I'm quite lazy for that, sorry :(
#include <math.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
//this is the original ciphertext
char* b="6gy.=gvlq:z91=uowwYsM+w86gyrQnzpPfI!7jFrBpWAy'H86jTJAlzly "+
"I!8lMNCoywG=H7~myrBpyF5aH~dSWYWSF2rkG!#HCoBnPDw@I~#fBtCkwep'E86g";
//this is the original 'alphabet
char* a="@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234"+
"56789~!#$%^&*():;/.\t\r -'+\"=";
//this function return the indexOf the char 'c' in the 'alphabet'
int cton(char c)
{
int i;
for (i=0; i<strlen(a); i++) {if (a[i] == c) return i;}
printf("error\n");
return 0;
}
//This function simply decipher the OrigString with the 'key' .
//The result is returned in OrigString
void decode(char* OrigString, char* key)
{
int i;
int pos = 0;
char first, second;
for (i=0;i < strlen(OrigString);i++)
{
first = OrigString[i];
seconfiltered= key[pos];
if (seconfiltered== '_') OrigString[i] = ' ';
else OrigString[i]=a[(cton(first)-cton(second)+strlen(a))%strlen(a)];
pos = (pos+1)%strlen(key);
}
}
//This function return a valid key from a pair of cipher and plaintext.
//both cipher and plain text must have the same length
void getkey(char* cipher, char* plain, char* key)
{
int i;
for (i=0; i<trlen(cipher); i++)
{key[i] = a[(cton(cipher[i])-cton(plain[i])+strlen(a))%strlen(a)];}
key[i] = 0;
}
//This function was added when I wanted to 'score' each obtained plaintext.
//It return the number of time the plaintext 'st' contain the string in the tips array.
int check(char* st)
{
int i,j;
int score = 0;
char* tips[11] = {"rep","lac","re","loc","ati","ht","lo","ca","oc","\"","+",};
for (i=0; i<strlen(st); i++)
{
for (j=0; j<1; j++)
{
if (strncmp(&st[i],tips[j], strlen(tips[j])) == 0) score++;
}
}
return score;
}
void main(void)
{
char temp[128];
char key[128];
char tempkey[128];
int i;
//This is the plain text we want to obtain
char* plaintofind = "eval";
FILE *outkey,*outplain,*outfull;
// outkey will contain the key,
// outplain the plain text
// and full both the keys and the plain text
outkey = fopen("key.txt", "wt");
outplain = fopen("plain.txt", "wt");
outfull = fopen("full.txt", "wt");
/* // This was added when I already found the start of the key.
//It allow me to get a key char from a cipher and a plain char
// getkey("~~","''",key);
// printf("***%s***\n",key);
//And then to get the result of the new key.
strcpy(temp, b);
decode(temp, "____ErCrAc__");
printf("%s\n%s\n",temp,b);
fprintf(outfull,"%s\n%s\n",temp,b);
*/
//Here start the original program...
// It loops from the first to the last char or the cipher
for (i=0; i<strlen(b); i++)
{
//Get a cipher of the same length of the plaintext and starting at the position i.
strncpy(temp, &b[i], strlen(plaintofind));
temp[strlen(plaintofind)] = 0;
//Check if we didn't reach out of the cipher
if (strlen(temp) == strlen(plaintofind))
{
getkey(temp, plaintofind, key); //Get a valid key
printf("%s : \n",key);
fprintf(outkey, "%s : \n", key);
fprintf(outfull, "%s : \n", key); //print it to files
int keylen;
//Then decipher the while cipher with that key padded to differents lengths
for (keylen=strlen(plaintofind); keylen< 13; keylen++)
{
while (strlen(key)<keylen) strcat(key, "_"); //pad with _
strcpy(tempkey, key);
strcat(tempkey, key);
strcat(tempkey, key);
//realign the key so that it start well
strcpy(temp, &tempkey[keylen-(i%keylen)]);
temp[keylen]=0;
strcpy(tempkey, temp); //tempkey will be applied to the whole cipher
printf("len : %d, %s : \n", keylen, tempkey);
fprintf(outkey,"len : %d, %s : \n", keylen, tempkey);
fprintf(outfull,"len : %d, %s : \n", keylen, tempkey);
strcpy(temp, b);
decode(temp, tempkey); //decipher
//This was added for the scoring : write score
printf("%02d ", check(temp));
fprintf(outplain,"%02d ", check(temp));
fprintf(outfull,"%02d ", check(temp));
printf("%s\n", temp); //write the plaintext we obtained
fprintf(outplain,"%s\n", temp);
fprintf(outfull,"%s\n", temp);
}
fprintf(outfull, "---\n"); //end mark
}
}
fclose(outkey);
fclose(outplain);
fclose(outfull);
int ch = getch();
}
To conclude, once you got the trick they used it's not so impossible finally :)
Just a last thing ... I'm not french ... Just french speaking !
I wont even bother explaining you
that you should BUY this target program if you intend to use it for a
longer period than the allowed one. Should you want to STEAL this
software instead, you don't need to crack its protection scheme at all:
you'll find it on most Warez sites, complete and already regged,
farewell, don't come back.
You are deep inside fravia's page of reverse engineering,
choose your way out:
homepage
links
search engines
+ORC
students' essays
academy database
tools
cocktails
bots wars
anonimity academy
antismut CGI-scripts
counter measures
mail_fravia+
Is reverse engineering legal?