Cenzic 232 Patent
Paid Advertising
sla.ckers.org is
ha.ckers sla.cking
Sla.ckers.org
Script obfuscation, filter evasion, IDS/IPS/WAF bypassing... this is where it should live. Because this topic is too big to live anywhere else. Phj33r! 
Go to Topic: PreviousNext
Go to: Forum ListMessage ListNew TopicSearchLog In
Decoding the great js wall
Posted by: Gareth Heyes
Date: February 09, 2010 10:31AM

So at some point I'm going to do a little project to decode the obfuscation stuff we've been playing with. I experimented with this in the past by inspecting variables:-

http://www.businessinfo.co.uk/labs/jstimeshift/jstimeshift.html

But...

We don't have any variables now :) So I guess I could write a char by char parser to do it but I was wondering about other ways. One possible way would be to inspect the toString and rewrite [] checks any other ideas?

------------------------------------------------------------------------------------------------------------
"People who say it cannot be done should not interrupt those who are doing it.";
labs : [www.businessinfo.co.uk]
blog : [www.thespanner.co.uk]
Hackvertor : [hackvertor.co.uk]

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: SW
Date: February 09, 2010 03:03PM

These huge strings are built from a few predictable static limited number of elements, so it should be relatively easy to reverse them, no? The hard part is just matching the scope right.

All we have at the start are a couple ways to make each of these: numbers, true, false, NaN, undefined, Infinity.

You just must decide how far to reduce it, because they are highly nested.

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: Gareth Heyes
Date: February 09, 2010 03:13PM

Well no they're not static they can be generated in many different ways:-

+[++[[]][+[]]+[[][+[]]+[]][+[]][+[++[[]][+[]]]+ ++[[]][+[]]+ ++[[]][+[]]]+[++[[]][+[]]]+[++[[]][+[]]]+[++[[]][+[]]]+[++[[]][+[]]]]

I'd have to match the whole of the block to convert it to Infinity, the decoder would also have to know js syntax in order to do it. The problem is there are too many ways to generate these strings and when you combine it with other js syntax it could be very difficult to match

------------------------------------------------------------------------------------------------------------
"People who say it cannot be done should not interrupt those who are doing it.";
labs : [www.businessinfo.co.uk]
blog : [www.thespanner.co.uk]
Hackvertor : [hackvertor.co.uk]

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: SW
Date: February 09, 2010 03:31PM

I am personally more interested in encoding right now: no alnum, no variables.

I think we should determine the shortest path to every letter, then it would be quite feasible to automatically convert an arbitrary command into an unreadable mess. :)
a: "false"[1]
b: (1+{})[3] 
c: "function filter() { [native code] }"[3]
d: "undefined"[2]
e: "undefined"[3]
f: "false"[0]
g: (''.constructor+1)[14]
h: window.atob("aN")[0]
i: undefined[5]
j: (1+{})[4]
k: 
l: "false"[2]
m: (1..constructor+1)[11] 
n: "undefined"[1]
o: (1+{})[2] 
p: (/./.constructor+1)[14]
q: 
r: "true"[1]
s: "false"[3]
t: "true"[0]
u: "true"[1]
v: "0function filter() { [native code] }"[30]
w: ((1,[].sort)()+'')[13]
x: (controllers.__proto__+1)[1] //woohoo!
y: (1/0+'')[7]
z: navigator.appCodeName[2] //Mozilla only

A: ([].constructor+1)[9] //or (Audio+'')[8] :)
B: ((![]).constructor+1)[9]
C: ((1,[].sort)()['crypto']+1)[8]
D: ((1,[].sort)()['document']+1)[12]
E: (1..constructor.__proto__+1)[9] //only on Chrome
F: (1..constructor.constructor+1)[9] 
G: (navigator.geolocation+1)[8]
H: ((1,[].sort)()['document']+1)[8]
I: (1/0+'')[0]
J: 
K: 
L: ((1,[].sort)()['document']+1)[11]
M: ((1,[].sort)()['document']+1)[10]
N: NaN[0]
O: (''+{})[8]
P: ((1,[].sort)()['toolbar']+1)[11]
Q: 
R: (/./.constructor+1)[9] 
S: (''.constructor+1)[9]
T: ((1,[].sort)()['document']+1)[9]
U: ((1,[].sort)()['controllers']+1)[9]
V: 
W: ((1,[].sort)()+1)[8]
X: ((1,[].sort)()['controllers']+1)[8]
Y: 
Z:

I will work on some longer ones later and update it. I suspect for the majority of the other letters it will be fastest to use atob, unless there's some other function I didn't think of.

Allowing an arbitrary number variables would make it very interesting to determine the optimal assignments. I think you'd have to parse the whole result determining the # of uses and length of each "string", and assign the highest ones the variables. Interestingly javascript doesn't care about scope, which makes it a lot easier.



Edited 15 time(s). Last edit at 02/09/2010 05:03PM by .mario.

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: Anonymous User
Date: February 09, 2010 03:40PM

@SW okay if us mods add some of the missing letters to your post?

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: SW
Date: February 09, 2010 03:42PM

Gareth Heyes Wrote:
-------------------------------------------------------
> Well no they're not static they can be generated
> in many different ways:-
>
> +[++[[]][+[]]+[[][+[]]+[]][+[]][+[++[[]][+[]]]+
> ++[[]][+[]]+
> ++[[]][+[]]]+[++[[]][+[]]]+[++[[]][+[]]]+[++[[]][+
> []]]+[++[[]][+[]]]]

What is happening with these strings is you are adding extra digits in braces until it overflows the Number() and is set as Infinity. There are a few ways to generate each, but I think they can be enumerated.

To start with [+[]] = [0], [++[+[]][0]]=[++[[]][0]]=[++[0][0]]=1

I must go now, but I think it can be done.

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: SW
Date: February 09, 2010 03:43PM

.mario Wrote:
-------------------------------------------------------
> @SW okay if us mods add some of the missing
> letters to your post?

Of course. :)

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: Gareth Heyes
Date: February 09, 2010 03:49PM

@SW

Well yeah anything can be done if you try hard enough :)
I was just looking for shortcuts, IMO prototyping toString and valueOf before the obfuscated code is run

------------------------------------------------------------------------------------------------------------
"People who say it cannot be done should not interrupt those who are doing it.";
labs : [www.businessinfo.co.uk]
blog : [www.thespanner.co.uk]
Hackvertor : [hackvertor.co.uk]

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: SW
Date: February 09, 2010 04:37PM

@mario
I see you used more chars thee, I guess that is fine after all.

@Gareth
I don't know much about this, but I see your point.

It seems to me if you just eval every [...] and (...) recursively from the inside out, you will deobfuscate the whole thing... the only decision is where to stop. Is that what you were thinking?

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: Anonymous User
Date: February 09, 2010 04:47PM

@SW I only used chars constructible by no-alnum sources. Or chars using chars coming from properties being accessed by using no-alnum sources lol

qkJQKVXYZ are tough though... atob would just be too easy ;)

[edit]
You guys are aware that we are more or less accidentally constructing the ultimate JS Sandbox buster? Without excessive use of delete code executing w/o variables and alphanumeric characters is almost impossible to tame :P
[/edit]



Edited 3 time(s). Last edit at 02/09/2010 04:58PM by .mario.

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: Anonymous User
Date: February 09, 2010 05:15PM

And just for completeness sake:
[_=([]=[].sort)()]==[_=_.atob((_.controllers+[])[+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(_+[])[(+!![])+[]+(+!![]+!![]+!![])])],_
:)



Edited 4 time(s). Last edit at 02/09/2010 05:44PM by .mario.

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: SW
Date: February 09, 2010 05:47PM

Shorter:
alert(([],[].sort)()['atob']("undefined"[0]+18)[1])

I was aware of using window.document...., but I think atob is probably shorter in the end, depending how you get all the letters and which charset you use.

Originally I was thinking of only using []+!(), but I guess there's no practical reason for not using the others. :)

Other characters...

<> ="/
All returned by "f".big()

:: window.Date()[21]


This is very interesting stuff. It still won't let you get inside script tags unfortunately, and only works on FF. :(



Edited 1 time(s). Last edit at 02/09/2010 05:49PM by SW.

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: Anonymous User
Date: February 09, 2010 05:51PM

@SW Nice!!!

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: Anonymous User
Date: February 09, 2010 05:56PM

But still too long haha

alert((0,[].sort)().atob([0]+18)[1])

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: SW
Date: February 09, 2010 06:02PM

Ahhh yes! Hah.

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: Anonymous User
Date: February 09, 2010 06:10PM

And even three bytes less:

alert((0,[].sort)().atob(118)[1])

Welcome to the club of mad JavaScript scientists, SW ;)



Edited 1 time(s). Last edit at 02/09/2010 06:28PM by .mario.

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: thornmaker
Date: February 09, 2010 07:20PM

@all - which set of letters are we allowing? Is / valid? or are we just using +[]? and what about ! and/or = ? This is why I stopped updating my other cheat sheet. Also, we should put this in it's own thread...

@Gareth sorry for the thread jack :) I don't see why a recursive parser wouldn't be able to interpret these... but it sounds like an awful thing to code up correctly.

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: SW
Date: February 09, 2010 07:33PM

Yes I think we need to decide on charsets. Perhaps the best way is to make separate lists depending on which chars are used.

And yea we could split into a new thread too, since I guess it's not directly related.

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: __matt
Date: February 09, 2010 07:42PM

I know its longer but for missing chars why not:


((' '['constructor'])['fromCharCode'])(97)

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: SW
Date: February 09, 2010 09:15PM

I made a new thread, maybe you can copy some of yours over there mario and delete the spam from this thread. :D

Also eventually at least we should list the hard code for them all, so we can really see what is longer or shorter....

@__matt ... for example it takes like 3800 characters to access fromCharCode() with []()+! and atob is probably always better unless you manage to use fromCharCode(.....) to convert your entire string.

Options: ReplyQuote
Re: Decoding the great js wall
Posted by: Gareth Heyes
Date: February 10, 2010 02:41AM

@mario

I think JSReg will/is be safe :D

------------------------------------------------------------------------------------------------------------
"People who say it cannot be done should not interrupt those who are doing it.";
labs : [www.businessinfo.co.uk]
blog : [www.thespanner.co.uk]
Hackvertor : [hackvertor.co.uk]

Options: ReplyQuote


Sorry, only registered users may post in this forum.