Java Code Obfuscation
Download
Report
Transcript Java Code Obfuscation
Java Code Obfuscation
Neerja Bhatnagar
Reverse Engineering
Figuring out source code corresponding to a
given byte code
Source code intellectual property, needs
protection
Money, intelligence, hard work, time put to
work to develop code
Problem of Reverse Engineering
Java code especially prone to reverse engineering,
because
Java byte code well documented and well
structured (freely available in JVM specs)
Most of the information contained in source
code also present in byte code.
Software engineers have little control over
distribution of Java applications and their source
code because most Java applications
distributed over the Internet (easy downloads)
Code Obfuscation
Technique to discourage and deter reverse
engineering
Scrambles byte code to make it unintelligible,
difficult to understand
Alters structure and appearance of code
Attempts to make in uneconomical for an
attacker to reverse engineer code
Does not affect function of original program
Does not alter source code, alters byte code
Code Obfuscation Techniques
Low-Level
Layout Obfuscations
Control Obfuscations
Data Obfuscations
High-Level or Design Obfuscations
Class Coalescing Obfuscation
Class Splitting Obfuscation
Type Hiding
Design Obfuscations
Low-level obfuscation techniques not
sufficient because they do not hide
design information
Design information can facilitate an
attacker from gaining general
understanding of code and what it does
Design obfuscations aim at hiding
valuable high-level design information
Class Coalescing Obfuscation
Combines two or more classes into a single
class
If the classes to be coalesced
have attributes with same name, these
are renamed to distinguish among them
have non-constructor methods with same
signature, except for one non-constructor
methods, all others are renamed and
altered
Class Coalescing Obfuscation Example
public class Animal {
String name; int age;
public class A {
String name;
String model;
int age;
int age2;
public Animal() {
name = “Goofy”; age = 1;
}
public int calcAge() {
return 2004 – 1985;
}
public Animal() {
name = “Goofy”; age = 1;
}
public void comments() {
System.out.println(“Fluffy”);
}
public Car() {
name = “VW”; age = 2;
}
}
public int calcAge() {
return 2004 – 1985;
}
public class Car {
String model; int age;
public int calcAge(int make)
return 2004 – make;
}
public Car() {
name = “VW”; age = 2;
}
public int calcAge(int make)
return 2004 – make;
}
}
public void comments() {
System.out.println(“Fluffy”);
}
{
public void comments() {
System.out.println(“Smooth”);
}
{
public void commentsFromCar() {
System.out.println(“Smooth”);
}
}
Class Coalescing Obfuscation Shortcomings
Becomes very complicated when classes extend
other classes or implement interfaces because
superclasses and interfaces need to be
coalesced too
variable names and method signatures
cannot be altered in any way
Cannot be performed when classes extend classes
from Java standard library
Java standard library classes need to be
coalesced too
Makes code non-portable
Classes with native methods cannot be coalesced
because analyzing native code very difficult
Class Splitting Obfuscation
Splits a class into multiple classes
Several ways to split a class
Valid split function preserves dependencies
among class’s methods and fields
Valid split functions include
Split class A into classes A1 and A2, where A2
extends A1
Split methods defined in class A between
classes A1 and A2
Class Splitting Obfuscation Example
public class Animal
String name;
int age;
public class Dog
String name;
int age;
String sound;
{
{
public Dog() {
name = “Bruno”;
age = 5;
sound = “woof”;
}
public Animal() {
name = “Bruno”;
age = 5;
}
public void sleep() {
System.out.println(“zzz…zzz”);
}
}
public void bark() {
System.out.println(“Woof! Woof!”);
}
public void sleep() {
System.out.println(“zzz…zzz”);
}
public class Doggie extends Animal {
String sound;
public Doggie() {
super();
sound = “woof”;
}
}
public void bark() {
System.out.println(“Woof! Woof!”);
}
}
Class Splitting Obfuscation Shortcomings
Splitting a class very difficult unless initial
design faulty
May have reverse effect
Splitting a class may improve overall
code design, and get rid of spaghetti
code!
Might actually help the attacker, rather
than deter him
Type Hiding
Uses the concept of Java interface
Transforms a concrete class into
several interfaces
Each interface contains a random
subset of the concrete class’s methods
and fields
Obscures by declaring a concrete class
that implements those interfaces
Type Hiding Example
interface LivingCreature
public void bark();
}
public class Dog
String name;
int age;
String sound;
{
{
public Dog() {
name = “Bruno”;
age = 5;
sound = “woof”;
}
public void bark() {
System.out.println(“Woof! Woof!”);
}
interface Animal {
public void sleep();
}
public class Doggie
String name;
int age;
String sound;
public void sleep() {
System.out.println(“zzz…zzz”);
}
{
public Dog() {
name = “Bruno”;
age = 5;
sound = “woof”;
}
}
public void bark() {
System.out.println(“Woof! Woof!”);
}
public void sleep() {
System.out.println(“zzz…zzz”);
}
}
Type Hiding Shortcomings
Type hiding done the way described in
previous slide especially vulnerable to
reverse engineering
More effective when combined with
low-level obfuscation techniques
Can be made stronger when randomly
selected classes go through type
hiding, instead of all classes
Obfuscation Products
RetroGuard by Retrologic Systems
Klassmaster by Zelix
JObfuscator by Duckware
Semantic Designs
Conclusion
None of the obfuscation techniques sufficient by
themselves
A combination of these techniques might provide
strong resistance to reverse engineering
Some claim code obfuscation slows down an
application
Impact on performance depends on a particular
technique
Impact usually minimal or none at all
Decision to obfuscate or not is a trade-off between
protecting code or taking a slight performance hit