Tuesday, October 24, 2006

Defeating Dean Edwards' Javascript Packer

Today a friend passed me some obfuscated javascript and asked if I would help him decode it. I had a quick look at it and saw the following code fragment:

eval(function(p,a,c,k,e,d){ ...

This made me smile. p,a,c,k,e,d... Cute. After a little research, I found this to be a signature function of Dean Edwards javascript packer. I found 2 very quick ways to deobfuscate code packed with this packer, and I have decided to share them with you. By presenting this my intention is NOT to insult Dean's work in any way, when it comes to javascript, and a few other topics, Dean is lightyears ahead of me. I present this to provide the community with a few methodologies they might use to approach these scenarios in the future, should it be necessary.

Here's a link to the packer:

http://dean.edwards.name/packer/

The first method does not attack the obfuscation technique, but a feature of the packer interface. Built RIGHT IN to the interface is a decode button. This has been designed to only allow decoding of your own code. If you look at the interface, you can't paste into the top textarea (because of the readonly attribute) and the decode button is disabled until you've actually packed something. This design is inherently flawed as it depends on the browser.

I wrote a bookmarklet called reEnable that will remove the readonly attribute from textfields and the disabled attribute from other html elements.

reEnable: Bookmark this :)

Using reEnable you can paste obfuscated code into the interface and decode it with a click.

The second method attacks a weakness in the obfuscation technique itself. Here is some code

unpacked:



document.write('Hello World!');



and packed:



eval(function(p,a,c,k,e,d){e=function(c){
return c};if(!''.replace(/^/,String)){while
(c--){d[c]=k[c]||c}k=[(function(e){return
d[e]})];e=(function(){return'\\w+'});c=1}
;while(c--){if(k[c]){p=p.replace(new
RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return
p}('3.0(\'1 2!\');',4,4,'write|Hello|World
|document'.split('|'),0,{}))



(I had to force multiple lines to avoid it breaking my layout lol)

it looks like a lot of randomness, but the weakness is pretty easy to spot if you know what you're looking for.

Notice near the bottom all the code is there, just rearanged with the syntax punctuation removed? if you look even closer the syntax punctuation is there as well, only seperate from the strings. If we looked at this long enough, we might be able to write a utility to unpack it... but there's an even easier way. Notice how everything is wrapped in an eval()? well, we don't want the code to be evaluated, we want to SEE it... If you replace the opening eval( with document.write( ... all the code is dumped to the screen. If some of it is being interpereted as html rather than being displayed consider forcing your document.write to write between <textarea></textarea> tags.

<3

8 comments:

kangax said...

Nice one, Ryan

I recently packed one of my scripts and forgot to make a copy of original...

This came in handy

Anonymous said...

Enjoy. Thank youu bro

MHavoc said...

Great post and insight!

Aaron Dwyer said...

I didn't realise javascript could be used in a bookmarklet like this. Well done. Aaron

Anonymous said...

lol
Thanks, man!

bacho said...

Old but yet still works!

Unknown said...

Pretty though isn't it?

eval(function(p,a,c,k,e,d)

;)

Anonymous said...

Fantastic, thanks for this post.