Overview
If we are developing java application whose byte code is publicly distributed over internet, there is always possibility to reverse engineer the class files using various decompilation tools.
To make reverse engineering much difficult, Java obfuscators can be used.
Java obfuscators will ensure to replace the identifiers to names which are unclear and also make the flow very difficult to understand after decompilation.
There are multiple free and commercial Java obfuscators whose list can be found here.
The current post deals with obfuscation process using Proguard.
Pre-requisites
Sample source file
The below is sample java source files (NoObsfuscation.java and ObfuscationImpl.jav) which will be explained in current post, other sample files can be found here.
public class NoObsfuscation { public static void main(String[] args) { ObfuscationInterface obfuscationInterface = new ObfuscationImpl(); obfuscationInterface.printInput("obfuscation interface instance"); obfuscationInterface.printDefaultMthd(); ObfuscationImpl obfuscationImpl = new ObfuscationImpl(); obfuscationImpl.genericAbstractMethod(); obfuscationImpl.genericImpl(); } }
public class ObfuscationImpl extends AbstractObfuscation implements ObfuscationInterface { public void printInput(String input) { System.out.println("printInput implementation:--->"+this.hashCode()); } @Override public void genericAbstractMethod() { System.out.println("genericAbstractMethod:-->"+this.hashCode()); }
Obfuscation Steps with Proguard
- 1. Create Proguard Conf flile
- 2. Execute Proguard
- 3. Decompiled sources
- 4. Proguard Map file
The proguard conf file provides configuaruon details to be considered while obfuscation. The below mentioned are few config details and complete list can be found here.
# The input jar which need to be obfuscated. -injars core-java.jar # The obfuscated jar. -outjars core_java_obfuscated.jar # The java source library jar which is the run time jar for code execution. -libraryjars "C:/Program Files/Java/jdk1.8.0_25/jre/lib/rt.jar" # Proguard provides map file which provides mapping between original java source identifiers and obsfuscted names for trouble shooting and debugging purpose. -printmapping proguard.map # Proguard removes the unused and unreferenced sources to reduce the size of obfusctaed file. dontshrink options instructs proguard to retain all the files without removing them. -dontshrink # This file is not obfuscated and considered as root of the current references -keep public class com.siva.mythoughts.obfustcation.NoObsfuscation { *; } # This ensures all the files with below mentioned package are not obfusctaed and remain in tact -keep class com.siva.mythoughts.executorservice.* { *; }
The proguard can be executed via command line Or it can also be executed during build process using Maven.
The successful execution of proguard results in out jar as well as map file
Execute via Command line C:\obfuscation\proguard5.2.1\proguard5.2.1\bin>proguard.bat @../examples/myconfig.pro
<profiles> <profile> <id>obfuscatedemo</id> <build> <plugins> <plugin> <groupId>com.github.wvengen</groupId> <artifactId>proguard-maven-plugin</artifactId> <version>2.0.11</version> <executions> <execution> <phase>package</phase> <goals><goal>proguard</goal></goals> </execution> </executions> <configuration> <outjar>core_java_obfuscated.jar</outjar> <options> <option>-dontshrink</option> <option>-dontwarn</option> <option>-keep public class com.siva.mythoughts.obfustcation.NoObsfuscation { *; }</option> <option>-keep class com.siva.mythoughts.executorservice.* { *; }</option> </options> </configuration> </plugin> </plugins> </build> </profile> </profiles>
Find below the comparison between decompiled sources after and before obfuscation.
import java.io.PrintStream; // Referenced classes of package com.siva.mythoughts.obfustcation: // b, c public class NoObsfuscation { public NoObsfuscation() { } public static void main(String args[]) { (args = new b()).c(); args.a_(); args = args = new b(); System.out.println((new StringBuilder("genericAbstractMethod:-->")).append(args.hashCode()).toString()); System.out.println("Generic Abstract Implementation"); } }
package com.siva.mythoughts.obfustcation; // Referenced classes of package com.siva.mythoughts.obfustcation: // ObfuscationImpl, ObfuscationInterface public class NoObsfuscation { public NoObsfuscation() { } public static void main(String args[]) { ObfuscationInterface obfuscationInterface = new ObfuscationImpl(); obfuscationInterface.printInput("obfuscation interface instance"); obfuscationInterface.printDefaultMthd(); ObfuscationImpl obfuscationImpl = new ObfuscationImpl(); obfuscationImpl.genericAbstractMethod(); obfuscationImpl.genericImpl(); } }
The below is the proguard map file which can be used for debugging and troubleshooting purpose.
com.siva.mythoughts.obfustcation.AbstractObfuscation -> com.siva.mythoughts.obfustcation.a: void <init>() -> <init> void genericImpl() -> a void genericAbstractMethod() -> b com.siva.mythoughts.obfustcation.NoObsfuscation -> com.siva.mythoughts.obfustcation.NoObsfuscation: void <init>() -> <init> void main(java.lang.String[]) -> main com.siva.mythoughts.obfustcation.ObfuscationImpl -> com.siva.mythoughts.obfustcation.b: void <init>() -> <init> void printInput$552c4e01() -> c void genericAbstractMethod() -> b com.siva.mythoughts.obfustcation.ObfuscationInterface -> com.siva.mythoughts.obfustcation.c: void printInput$552c4e01() -> c void printDefaultMthd() -> a_
Limitations of Obfusction
- Obfuscation process doesnt change the name of java API classes, they are still visible in decompiled obfuscated code
- Dynamic generated classes obfuscation may create instability in the program execution
- Obfuscation of life cycle call back methods may create instability during call backs
- Serialized classes are not obfuscated
- Further enhanced releases of the software should ensure to maintain compatibility with previous released obfuscated code
- Some of the obfuscators may change the code work flow which may prevent jvm optimizations
- Some anit virus softwares may alert obfuscated code as malicious