Didier Stevens

Tuesday 19 December 2006

Teaching a SpiderMonkey a new trick

Filed under: Reverse Engineering — Didier Stevens @ 9:28

Have you read NJ Verenini post on Websense’s Blog were he explains how to use SpiderMonkey to deobfuscate Javascript? As SpiderMonkey has no document object, Verenini shows a way to define your own document object to support document.write().

I’ve adapted the SpiderMonkey source code to include the document object. Not that my method is better than Verenini’s, I just wanted to play with SpiderMonkey.
An upcoming “Virus Lab” post will explain how I use this adapted SpiderMonkey, but for now I want to explain how I proceeded to modify SpiderMonkey.

If you’re not familiar with the SpiderMonkey source-code (like me), were do you start? I want to implement a document object with a write method. Is there something similar in JavsScript? Take a look at the Math object.

js
js>Math
[object Math]

The Math object has several methods, like sin:
js> Math.sin(3.1415926/2)
0.9999999999999997

document does not exist:
js> document
2: ReferenceError: document is not defined

The trick is to add a document object that has the same behaviour as the Math object (i.e. same members), and if this works, we adapt the document object by removing all Math members and adding a write method.

Greping for Math in the source code reveals that the object is defined in jsmath.c and jsmath.h. This is good, the Math object is defined in it’s own source files. So we will make our own source files for document based on Math: copy jsmath.[ch] to jsdocument.[ch]. Then edit jsdocument.[ch] and replace Math with document (there are some execeptions, like math.h).

Then we add jsdocument.[ch] to the makefile.
Greping for jsmath.h reveals that it’s included in jsapi.c. A quick search for
Math in jsapi.c reveals this code:
js_InitMathClass(cx, obj) &&
{js_InitMathClass, ATOM_OFFSET(Math)},

We add our own code:

js_InitDocumentClass(cx, obj) &&
{js_InitDocumentClass, ATOM_OFFSET(Document)},

Now when we build, we’ll get an error because we use a Document ATOM that we didn’t define. A bit of searching in the source code shows that atoms are defined in jsatom.[ch]. We search for Math and add extra code for Document.
And now the build succeeds!

js
js> document
[object document]
js> document.sin(3.1415926/2)
0.9999999999999997

Now we have to remove all members and add our own write method, but this is for another post, where I’ll publish my modified spidermonkey (it’s GPLed).

Reversing with the commented source code is not so difficult as reversing binaries, especially the patching process. If you want to add a new feature, look for an existing similar feature and do an “intelligent” copy-paste of the source code.

Once upon a time, long ago, I read the Dragon Book, and this also explains how I was able to quickly understand how to modify SpiderMonkey.

2 Comments »

  1. [...] Filed under: Reverse Engineering, Malware — Didier Stevens @ 8:13 My first SpiderMonkey trick is more than 6 months old, and I still haven’t released the source code. Let’s do it now, but [...]

    Pingback by A Second SpiderMonkey Trick « Didier Stevens — Tuesday 7 August 2007 @ 8:13

  2. [...] the ones interested here is the method where you need to recompile spidermonkey and [...]

    Pingback by JavaScript deobfuscation a little start « DiabloHorn — Saturday 6 December 2008 @ 1:59


RSS feed for comments on this post. TrackBack URI

Leave a Reply (comments are moderated)

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Rubric Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 234 other followers

%d bloggers like this: