Courtesy of Fravia's page of reverse engineering
Well, some simple steps for newbyes, a nice C++ probe (which deserves your attention) and some Zen considerations... nice reading, isn't it?
"?vemuffrer" sounds to me like an old piece of sliced bread long forgotten in some drawer "You should'nt eat that vemuffrer thing, Gretchen!"... I wonder how comes it got such an high ponderation :-)

Back to Advanced javascript

Tom to Fravia+: 26 March 1998

```

How dummy I was! That's it! Listen to me fellow newbies

(Yes, I haven't got much experience in cracking)! Zen,

Zen, and much more Zen! In this case, semantics is the

key. Don't act like me, hoping that the solution will

come to you after just "some" Zen, you need a lot more

to get it :-) Perhaps, later will it come quicker

(that's called "experience" ;-).

Let's study the "Easy entrance to the advanced

JavaScript page" step by step:

Step 1: Turn off JavaScript in your browser, grab the

JavaScript code and modify it to dump the values of

f[].

Step 2: Determine the possible password lengths: with

the biggest value of f[] we obtain 7 characters (the

result is still less than the final code), and with the

smallest value of f[] we obtain 13 characters. The

length of the significant part of the password is in

range [8;13].

Since the final code can only be divided by 9 in the

[8;13] range, the password length is 10 (including the

first character ignored by the check routine).

Note also that the first two characters can be

switched.

Step 3: Some brute forcing with a short proggy (se the

other essays) shows quickly that there are too many

possibilities to try them all. What we need here is

lots of Zen.

Step 4: Switch off your computer and eat your windoze CD

(Yes, it helps :o), and... Zen!

Step 5: Given that the password is the name of the html

page, we can hopefully get rid of uppercase letters,

coz their use on a web server often leads to a "Object

not found" message in your browser (depending from the

"comprehension" between your browser and the host

operating system). Anyway we must reduce the number of

possibilities, so go on and calculate how many there are

now:

The short proggy tells us: 5767 (without the first

random character :-). Still too huge!

Step 6: It's the end of the brute force method. If we

can't find another way to reduce the number of

possibilities, we're stuck here. If Fravia+ said that we

can break it, it must be something "easy". After a

little exam we can see that the last letters must be in

{h, i, r, w}: the filename doesn't end with a digit...

Did he dare to put a(some) digit(s) right in the middle

of a filename? Could it be something like "java2advan"?

May be. We can't discard numbers for now. If the

filename isn't somehow meaningful, trying the hard

entrance would be quite the same (just have a look at

it ;o). Once more: Zen!

Step 7: Semantics. The targeted page is about java, so

it's name contains certainly "ja" or "jav" or "java".

After having filtered all passwords containing any of

these subsets (don't forget to consider the first

character in your pattern matching!), it gives 112

remaining possibilities And that's only for the

significant part. There is a total of 62 x 112 = 6944

possible passwords... Perhaps a subset of "Fravia"? It

will certainly lead to the same conclusion: still too

much possibilities. Anyway, the password could be

"bozo2trash". Bad weather! Never mind, let's try the

"good english" filtering.

The program makes some statistics about all "good

english" letter triplets found in each password

computed. Each good triplet found increases the current

score by one. If the final score is (or will be ;-)

less than the minimal score passed on the command line,

the password is rejected. In our case, consider that

the max possible score is 7 (9 minus 2) and that a

single disturbing character (like a digit) in the

middle of the password will reduce the score to 4. When

I experimented, the good password popped up with a

minimal score of 5 (calculation time is about 7 seconds

on a P233):

5 ?varnrdich (Deutsch ?)

...

5 ?vemuikich

...

5 ?vnlawkich

5 ?v9nabouch

5 ?9vnabouch

5 ?8veiswuch

5 ?vadusna6r

...

5 ?varhovidr

...

6 ?vdcurther

5 ?dvcurther

advcurther (may be...)

5 ?vafurther

avafurther (this one ?)

...

5 ?avfurther

...

favfurther (or this one ?)

...

javfurther (oh !)

lavfurther

navfurther (??)

...

5 ?verilvher (Deutsch ?)

...

5 ?nvinwdjer (some other Nordic language ?)

...

7 ?vemuffrer Hi-score ! But... what does it mean ???

...

5 ?evmuffrer

...

5 ?kvaullrer

5 ?v4osiorer

5 ?4vosiorer

6 ?ulwaporer (junk, junk, and more junk)

...

6 ?vbdurtrer

5 ?bvdurtrer

obvdurtrer

5 ?kfxtutrer

...

5 ?fkxtutrer

* 24 passwords with a min score equal to 5

Note that I wrote before a little word parser that

stored in a file all letter triplets found in some

english texts (downloaded from a "Project Guttenberg"

like site). The generated file is redirected to the

password cracker's stdin (I obtained a dictionary

containing about 3700 triplets).

Here's the C++ (C should work too, needs __int64

support) source code of my password cracker. Don't

blame me for the poor comments nor for the junky style:

I hadn't much time to write this proggy and you are

all reverse engineers, aren't you ? ;-)

```
#include <stdio.h> #include <stdlib.h> #include <string.h> #define BOZO_MAX_CHARS 9 const char base[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', // 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', // 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; const long f[] = { 23, 535, 1047, 1559, 2071, 2583, 3095, 3607, 4119, 4631, // 12, 21, 26, 38, 53, 72, 101, 139, 294, 375, 584, 841, 1164, // 1678, 2425, 4989, 6478, 10076, 14494, 21785, 30621, 69677, 87452, 139356, 201113, 278810, 80, 83, 93, 99, 113, 131, 159, 194, 346, 416, 619, 861, 1165, 1649, 2256, 4766, 6077, 9554, 13713, 20576, 28894, 65661, 82386, 131248, 164801, 262524 }; int* triplets; __int64 nTarget = 25834242042i64; __int64 nSols = 0; const int nKeys = sizeof(f)/sizeof(long); const int nTriplets = 26*26*26; char buf[BOZO_MAX_CHARS + 2]; char tbuf[BOZO_MAX_CHARS + 2]; int nMinScore = 0; int hurts(char* s) { // wait for a three letter string if( (s[0] >= '0' && s[0] <= '9') || (s[1] >= '0' && s[1] <= '9') || (s[2] >= '0' && s[2] <= '9') ) return 0; return triplets[((((s[0] - 'a') * 26) + s[1] - 'a') * 26) + s[2] - 'a']; } // the recursive one, the leasy way void test(__int64 code, int n, int score) { int i; if( n == 0 ) { if( code == "0.class" tppabs="http://Fravia.org/0.class" && score >= nMinScore ) { int j; buf[0] = '?'; printf("%d %s\n", score, buf); for(j = 0; j < 26; j++) { if( tbuf[1] >= 'a' && tbuf[1] <= 'z' && tbuf[2] >= 'a' && tbuf[2] <= 'z' && triplets[(((j * 26) + tbuf[1] - 'a') * 26) + tbuf[2] - 'a'] == 1 ) { buf[0] = j + 'a'; printf(" %s\n", buf); } } nSols++; } else if( code == "0.class" tppabs="http://Fravia.org/0.class" ) fprintf(stderr, "%s\r", buf); // progress indicator return; } // time killer 1000% if( n + score < nMinScore ) return; if( (code % n) == 0 ) { code /= n; for(i = 0; i < nKeys; i++) { buf[n] = base[i]; tbuf[n] = (buf[n] >= 'A' && buf[n] <= 'Z') ? buf[n] + 32 : buf[n]; test(code-f[i], n-1, score + ((n < 8)?hurts(&tbuf[n]):0)); } } return; } // the heart of the crack, for each good triplet we store a 1 in // the triplets array at position [26*26*(char 1) + 26*(char 2) + (char 3)] // I used the same technique to generate the input file void getTriplets() { int c, i = 0, idx = 0; while( (c = getchar()) != EOF ) { // skip white spaces if( c == '\n' || c == '\r' || c == ' ' || c == '\t' ) continue; // there are only a-z chars in the generated file if( c < 'a' || c > 'z' ) break; idx *= 26; idx += c - 'a'; if( ++i == 3 ) { triplets[idx] = 1; idx = i = 0; } } } // type <wordfile> | passit <min score> int main(int argc, char** argv) { __int64 code = 0; if( argc > 1 ) nMinScore = atoi(argv[1]); if( nMinScore < 0 ) nMinScore = 0; tbuf[0] = buf[0] = '?'; tbuf[BOZO_MAX_CHARS+1] = buf[BOZO_MAX_CHARS+1] = '\0'; triplets = new int[nTriplets]; // C users: use malloc() instead memset(triplets, 0, nTriplets * sizeof(int)); getTriplets(); test(nTarget, BOZO_MAX_CHARS, 0); fprintf(stderr, "* %I64d passwords with a min score equal to %d\n", nSols, nMinScore); delete [] triplets; // C users: use free() instead return 0; }
```

That's all folks !```
(c) 1998 Tom All rights reversed

You are deep inside Fravia's page of reverse engineering, choose your way out:

Back to Advanced Javascript

homepage links anonymity +ORC students' essays academy database
tools cocktails javascripts wars antismut CGI-scripts search_forms mail_Fravia
Is reverse engineering legal?