Sunday, May 14, 2006

Javascript "Encryption"

Last night a friend pointed me at a forum where someone was 'daring' people to 'crack his encryption'. I absolutely love these challenges and always give them a try. In this case, the challenge wasn't so much 'cracking encryption' as making sense of some semi obfuscated javascript code. I've decided to explain some of the techniques I use to do this, incase anyone ever finds a good use for them :P

Alright, so the code is long and mungy, so rather than pasting it here I'll explain some of it and paste the main function so I can walk you through it.

First, two arrays are declared. A standard array called asciiasc and an associative array called asciichr. These are used to create an alphabet table in the following way:

asciichr["A"] = 65; asciichr["B"] = 66; asciichr["C"] = 67; asciichr["D"] = 68; ...
asciival[65] = "A"; asciival[66] = "B"; asciival[67] = "C"; asciival[68] = "D"; ...

each of these array contains 255 values.

Following this is a javascript function, I've added indentations for readability:

function synvb(text) {
var allchr, myfinal = "";
var textasc, allasc = 0;
var passasc = 137;
var i, j = 0;
var rep2 = "";
rep2 = /\\r/g;
text = text.replace(rep2,"\r");
rep2 = /\\n/g; text = text.replace(rep2,"\n");
for (i = 0; i < text.length; i++) {
textasc = asciichr[text.charAt(i)];
allasc = textasc - passasc;
if (allasc < 1) {
j = allasc + 255;
allchr = asciiasc[j];
} else {
allchr = asciiasc[allasc];
}
if (!allchr) {
allchr = " ";
}
myfinal = myfinal + allchr;
}
return myfinal;
}

First some variables are declared. The two replace()'s are done to unescape carriage retures (\r) and newlines (\n). Following this we are passed into a for loop.

for (i = 0; i < text.length; i++) {

A for loops peramaters can often contain enough information to allow us to make a preliminary hypothisis of what happens within the loop construction. In this case, the loops condition is based on the length of the string 'text' which is the paramater passed to this function. Having seen the webpage I know that text contains an 'encrypted' string. Knowing this, we can hypothesize that this loop will iterate over every character, and is therefor likely the 'decryption' routine.

textasc = asciichr[text.charAt(i)];
allasc = textasc - passasc;

In the first iteration of the loop we get the value for the 1st ascii character in 'text', and subract from that value 137. Ah, so this is a basic shift cipher! The conditional statements following this are used to 'wrap' the shift to accomodate for values of allasc less than 0. Finally we take our values and concatonate them in 'myfinal'.

Now that we know that this cipher shifts the alphabet by -137 it would be trivial to code a decryption function. Rather than doing this, however, we'll use the code already at our disposal. We can add a line here:

myfinal = myfinal + allchr;
> document.write(myfinal);

However, in the instance of the code I was looking at, this will not work. After running through it, nothing was displayed. But why? What kind of data could be passed to document.write and not be displayed in the content of the document? It must be code! maybe the value is something like: <!-- this is the decrypted text \-->. This would not be displayed. So how can we have it displayed? The <textarea> tag is a perfect perfect for this problem. Anything following this tag is considered data (not code) and placed inside a textarea box. So, the first time through our loop we want to document.write('<textarea>').

function synvb(text) {
var allchr, myfinal = "";
var textasc, allasc = 0;
var passasc = 137;
var i, j = 0;
var rep2 = "";
rep2 = /\\r/g;
text = text.replace(rep2,"\r");
rep2 = /\\n/g; text = text.replace(rep2,"\n");
for (i = 0; i < text.length; i++) {
textasc = asciichr[text.charAt(i)];
allasc = textasc - passasc;
if (allasc < 1) {
j = allasc + 255;
allchr = asciiasc[j];
} else {
allchr = asciiasc[allasc];
}
if (!allchr) {
allchr = " ";
}
--> if(!myfinal){document.write('<textarea>')}
myfinal = myfinal + allchr;
}
return myfinal;
}



Hope you like the technique :).

No comments: