Tuesday, January 24, 2012

WAR file obfuscation using ProGuard

Yes, people can read your Java class files using simple decompilers like DJ Java Decompiler. That's great but sometimes undesirable. What if you want to protect those files so other (bad) people can't see your source code as you do? What you want to do is you might want to protect your WAR file using obfuscation techniques and it can be tricky sometimes. Why? Well, multiple reasons. Before you begin, keep in mind the following :

Be careful when you obfuscate classes. One of the obfuscation techniques is the process of changing class and method names, so you might want to take special care not to change something you might regret. For instance, public methods like getters and setters mustn't be changed, or otherwise you will loose some functionality or your JSP or JSF code might fail. For instance, JSP code looks for get* or set* methods when you use JSTL (JSP Standard Template Library) and if you obfuscate that code without filtering those methods, your JSP pages will fail since the method names will turn from getUsername() to a() for instance.

Be careful when you work with annotations. Often obfuscation tools will skip Java annotations. This is usually fine, but it can break the code sometimes. For instance, if you use JPA and @NamedQuery annotation, and you obfuscate class members, you will have to update those annotations manually since they still reference old (unobfuscated) names. I'm not sure if there's a tool which can do this automatically. Similar thing with EJB notations like @PostConstruct and @PreDestruct. Again, you don't wnat to obfuscate these methods, otherwise EJB container will faiil to call them properly. not sure if there's a workaround for this.

Do not obfuscate dependent libraries. Most of the time you don't want to obfuscate dependent libraries, since they themselves may have dependencies.

Update your XML files if you have them. Since obfuscation process change names of packages and classes, XML files can still reference the old names in old packages. Some obfuscation tools can update this automatically, but if you're not sure how to set this, update those files manually. For instance, you may have web.xml file which references some servlets in their packages. you will need to update this names to reflect obfuscated names, or otherwise servlets won't be accessible.

Finally, be careful when you generate WAR file. WAR file has the same structure as ZIP file, meaning you can simply change the extension into ZIP and use your favorite tool to unzip it. But, if you later want to regenerate that WAR file, do not use tools like WinZIP or WinRAR! These tools will not work proerply here, so what you need to do is you need to use jar tool from the command prompt. Simply cd into the working folder (folder with WAR structure) and type :

jar cvf ../WebService.war *

This command will generate WebService.war in the parent folder, using all available content in the current folder.

In this post we will use ProGuard which can be downloaded from http://proguard.sourceforge.net/. Beside other functionalities, ProGuard is a free Java class file obfuscator. It works like some sort of pipeline and it can  do other handy things for you like shrink, optimize, preverify and other but we won't tackle this right now. We are only going to use the obfuscation stage. There are other more robust and professional obfuscators over there, so if you need a professional grade obfuscation you might want to consider Zelix KlassMaster.

Download the latest version and cd into the extracted folder. Cd again into the lib subfolder and type :
java -jar proguardgui.jar

This will bring up ProGuard GUI, which is really easy to set up. This thingy is just a simple GUI wrapper
around command line tool called proguard. It's features can be set by typing them manually in command prompt, or instead you can use config files. Here is the step by step guide how to set up you obfuscation project :

Step 1 : Click on Input/Output tab on the left and choose your input folder, output folder and dependent libraries like this :


Remember, you have to set all dependencies otherwise errors will occur. For instance, if you use Oracle's library Jersey, make sure you add all Jersey jars.

Step 2 : Click on Shrinking tab and unckech shrink checkbox at the top.
Step 3 : Move to obfuscation part and use these settings :


Take special care at the bottom where you need to specify additional class names and/or members to keep from obfuscation. If something goes wrong with your WAR, you probably haven't set this rules to exclude some stuff. For instance, if you want to exclude start and stop methods from your enterprise java bean, which are annotated using @PostConstruct and @PreDestruct annotations, create a new rule like this :


Add additional rules for other classes in your project. You might want to skip obfuscating some class members since they are being used from annotations.

Ste 4 : Uncheck optimization checkbox and move to Information tab.
Step 5 : Use the following settings :


Step 6 : Move to Process tab. Here, you have an options to save all the settings into *.pro file, which I suggest you do. Then click Process button. If you forgot to specify some dependencies, you will get some errors. You need to go back and add missing libraries. If you don't know what jar file contains some problematic class, you can always use jarvana at http://www.jarvana.com/jarvana/.

That's it! Now, regenerate your WAR file from the output folder, deploy it on GlassFish for instance and test it. 

4 comments:

  1. It is good tutorial on war file obfuscation. But I feel some aspects are missing.
    class files of original war file gets deleted on obfuscation with proguard and solution is to make .jar file of these .class files. But I couldn't figure out how to acheive it using Ant Task ? Your answer is awaited.

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. is there a place in this application where we can add obfuscation rules

    ReplyDelete