View  Edit  Attributes  History  Attach  Print  Search

JavaScriptObfuscator

Background

Thanks to Google, JavaScript becomes a hot technology again. Mr. Jesse James Garrett coined the technique utilizing JavaScript and XMLHTTPRequest as AJAX. Whatever it is called, I believed that it is the most natural way for both web application developer and web users if the web application have to be an RIA (Rich Internet Application). However, there is an important issue to deal with before it can grow. All JavaScript are basically plain text. What problem?

I believe that the adoption of AJAX will grow only if there are enough number of components avaiable in the market. However, if you can't protect the code, are you willing to spend the time to develop the components? So, the answer is obfuscating the source code.

As I searched on the web, only a few obfuscators are available. All of them are useless for component developer. Imagine that you have written a JavaScript component, say TreeListView (google it if you don't know). You would like to share the scripts but you don't want others to see how it works (avoid other parties from stealing it and selling it). You tried the obfuscator to scramble the code. Then, you found that the names of classes, public variables and the public functions are renamed. Would you pay that obfuscator? Would you release the component you've written without any protection (substitude "you" to "a company")?

To encourage everyone using JavaScript, I decided to write this obfuscator by observing how I wrote the code and then release it to the public.

Email me about your thought.

Description

The obfuscation rules are:

  1. This JavaScript obfuscator removes all comments.
  2. In case there is a closure that does not end with a semi-colon, ";", a line break will be inserted when "}" is encountered.
  3. Redundant whitespace characters (tab, space, new line) will be removed.
  4. Variable names and function names are replaced only if they are not the member of the class.
    1. this.x, document.write() will not be replaced.
    2. Generally, the name after a dot, ".", will not be replaced.
  5. Variable names and function names will not be replaced if the token
    1. is a member of a class as mentioned at #4
    2. starts with a capital letter (assuming they are classes)
    3. is in the exception list. The exception list can be specified in a file delimiting the tokens with whitespace characters (tab, space), dot ("."), comma (","), double-quote ("""), and single-quote ("'")
  6. If specified, tokens in string literals will be encoded into \uXXXX or \XXX format
  7. If a line is end with a JavaScript delimiter or a double-slash comment, it will merged with the next line to a single line
  8. It does not process regular expression literals

Implications from the obfuscation rules:

  1. Using with should be avoided
  2. If using member of the window object, it is better to explicitly write window.something (e.g. window.setInterval...)
  3. All classes should be started with a capital letter
  4. Using a semi-colon to seperate a statement is encouraged because
     var a = "abc"
     var b = a
     var c = b // foo
     var d = c
    
    will be encoded to
     var a = "abc"var b = a
     var c = bvar d = c
    
    (see rule #7)
  5. The size of the obfuscated script will be smaller if the characters in string literals are not encoded into \uXXXX or \XXX format
  6. "asod asdi".replace(/as/gi, "cool")
    becomes
    "asod asdi".replace(/ab/bb,"cool")
    Use "asod asdi".replace(new RegExp("as", "gi")) instead

The output will be printed to STDOUT if the destination directory is not specified. Also, a mapping of old_variable=>new_variable will be printed to STDERR.

[ Download Source ][ Download JAR ][ License ]

Win32 executable is also available here [ Download ].

However, due to the restriction of the server (it's free anyway), I have to split it into pieces. Please simply download the pieces and run the batch file (generated by JR File Split). It will reconstruct the Win32 executable]]

(thanks to tElock 0.98, it compressed the 8.53MB executable into a 2.43MB one.).

Requirement

  • Java SDK 1.4 for compilation
  • Java JRE 1.4 for JAR file execution
  • MS Windows 98/2000/XP for Win32 executable

Build

javac JSO.java

Usage

  • Compiled from source
    • java JSO <list of javascript file> [options]
  • Using the JAR file
    • java -jar jso.jar ...
  • Using the Win32 executable
    • jso ...

where the options are:

  • e=<exception list file>
    • filename of the excption list.
    • exception tokens are delimited by tab, space, dot, comma, single quote and double quote
  • d=<destination directory>
    • the output directory
    • print to the STDOUT if not specified
  • o=<obfuscation parameters of string literals>
    • If it is specified, the characters in string literals will be encoded in either \uXXXX (hexidemcial) or \XXX (octal) format.
    • The parameters are a 2 or 3 floating point values delimited by commas. e.g. 0.5,0.3 or 0.5,0.3,0.9
    • The values are
      • probability to encode a token in a string literal
      • probability to encode a character in a candidate string
      • probability to encode a character into \uXXXX format
    • The last parameter is set to 0.5 if not specified.
  • p=<prefix for private members>
    • "private" prefix to ensure that functions/variables preceeded by the prefix are obfuscated even when preceded by "this."

Examples

Obfuscate all scripts in the current directory and output to ./out directory

java JSO *.js d=out

Pipe the STDOUT output to x.o.js

java JSO x.js > x.o.js

Obfuscate class member preceded by "_" or "__" (e.g. this._foo )

java JSO x.js p=_,__

Merge a.js and b.js and pipe the merged output to script.js. Tokens in exception list, noReplace.txt will not be replaced.

java JSO a.js b.js e=noReplace.txt > script.js

Obfuscate the 100% of token in string literals, 68% of the characters will be encoded. 50% of the character will be encoded as \uXXXX format (default)

java JSO x.js o=1,0.68

Comparison

JSO in Action

To Do

  • It would be good if you could put a link to http://www.shaneng.net/ if you use this obfuscator to encode the JavaScript. Thanks!