Java Obfuscator
Obfuscation is the process of making something unclear or difficult to interpret. Obfuscators are being used in programming to protect the source code from hackers. In this article, we will learn about code obfuscation, how obfuscators work, obfuscation tools, and their applications. We'll also learn how to obfuscate a Java application.
Obfuscation of Code
In the subject of computer science, the word "obfuscation" is frequently used. In a programming context, obfuscation is to make the code ambiguous by making some changes to the executable code, but the code still functions as intended. Obfuscating the code has the goal of rendering it useless to hackers.
The output of the application or program is unaffected by the obfuscation process, although it may change the method instructions or metadata. Obfuscating code is mainly used to make reverse engineering challenging. Code obfuscators are the tools that we employed in this approach.
Code Obfuscator
With enough time and effort, practically every programming code can be reverse-engineered. Many de-compilers are publicly accessible for various platforms, including Java, Android, .NET, iOS, etc. They may be used to quickly and easily extract the source code from an executable or library. As a result, hackers may readily comprehend the code.
We utilize a code obfuscator to fix the issues mentioned above. These are the resources that safeguard code against hackers without modifying its operation.
Operation of Obfuscator
Obfuscation is used in various ways to provide multilayer protection against reverse engineering. These methods include the following:
- Rename Obfuscation
- String Encryption
- Control Flow Obfuscation
- Instruction Pattern Transformation
- Dummy Code Insertion
- Unused Code and Meta Data Removal
- Binary Linking/Merging
- Opaque Predicate Insertion
- Anti-Tamper
- Anti-Debug
Rename Obfuscation
Numerous obfuscators employ this fundamental technique. The names of the variables and methods are modified. It is more difficult to understand code when variables and methods have different names. Notably, it has no impact on how the code runs. Renaming can use alphabetic, numeric, illegible, unprintable characters, etc.
String Encryption
Even after renaming obfuscation is used, all strings in code can still be read plainly. Messages that are visible to the user, such as error messages, are frequently included in strings. It conceals the string in the executable and, if necessary, restores the original string.
Control Flow Obfuscation
It generates iterative constructs and conditional branching. It produces legitimate executable logic, yet when decompiled, have non-deterministic semantic outcomes. It makes code challenging so that hackers can't easily understand it. Be aware that the technique may cause a method's runtime performance to reduce.
Instruction Pattern Transformation
The instructions produced by the compiler are changed into others using this method. These are often legal machine language commands that cannot be translated into high-level languages.
Dummy Code Insertion
The dummy code is inserted into the executable, but the application's logic is unaffected. The decompiles become broken. The addition makes reverse-engineered code analysis more challenging than dimming code.
Unused Code and Meta Data Removal
Applications can be made smaller and have less information available to attackers by removing debug information, unnecessary metadata, and utilized code. It improves the application's performance.
Binary Linking/Merging
It creates one or more output binaries from several input executables or libraries. It reduces the size of applications, especially when combined with pruning and renaming. As a result, it limits the information hackers can access.
Opaque Predicate Insertion
The conditional branches are included, which always evaluate predetermined outcomes. These are the outcomes that static analysis cannot be used to predict or ascertain. It offers code that might be flawed but never runs. The sole intent is to baffle hackers attempting to decipher the source code.
Anti-Tamper
An obfuscator can confine application self-assurance within the code to ensure that the program hasn't been altered. If an alteration is detected, it can be closed down to the extent that it is still valid, cause erratic crashes (to hide the causes of the crashes), or perform some other particular task.
Anti-Debug
An obfuscator can add a layer of application self-security by injecting code that can detect whether our production program is running in a debugger. If a debugger is used, it can destroy sensitive.
Why do we need to utilize an obfuscator?
Java de-compilers make it simple to reverse-engineer applications written in Java. Java de-compilers show the source code, so we employ obfuscators to protect it. The obfuscator allows us to shield our source code from hackers. The best way to secure the source code is with this method. There are different obfuscators for various platforms. There are numerous free Java obfuscator utilities available.
Java Obfuscate Tools
- ProGuard Java Optimizer
- DashO Android and Java Obfuscator
- KlassMaster Heavy Duty Protection
- Javaguard
The ProGuard Java Optimizer
It is an open-source obfuscator, optimizer, shrinker, and pre-verifier for Java class files (Bytecode).
DashO Android and Java Obfuscator
This active protection utility obfuscates Java and Katlin applications to provide security.
KlassMaster Heavy Duty Protection
This safeguards the bytecode as well. The tool's advantage is that it can obfuscate and minimize code and string constants. Another benefit of the tool is the ability to translate the stack trace back into readable form after saving the obfuscation log.
Javaguard
This essential bytecode obfuscator utility lacks much documentation.
Java Obfuscation Example 1
Original code snippet
class X{
static
int n(int a, char b){
return 1 ;
}
}
class Y extends X{
boolean n(int c, char d){
return false ;
}
}
Obfuscated code snippet
class X{
static
int n(int a, char b){
return 1 ;
}
}
class Y extends X{
boolean n(int c, char d){
return false ;
}
}
De-obfuscated code snippet
class class_0_pub{
class_0_pub(){}
static
int method_ret_int(int i, char c){
return 1 ;
}
}
class class_1_pub extends class_0_pub{
boolean
method_1_ret_boolean(int i, char c){
return false ;
}
class_1_pub(){}
}
Obfuscated Symbol Cross Reference
X -> class_0_pub
n -> method_ret_int
a -> i
b -> c
Y -> class_1_pub
boolean n -> boolean method_1_ret_boolean
Java Obfuscation Example 2
Obfuscated code snippet
import javax.swing.JOptionPane;
public class Program1
{
public static void main(String args[]) {
String first, second;
double choice;
double radius,width,area,length;
String value = " "; //initialize the string
value = JOptionPane.showInputDialog("Please chose one of the options:"+"\n"+"a)Enter 1 to calculate the area of the Circle"+"\n"+"b)Enter 2 to calculate the area of the Triangle"+"\n"+"c)Enter 3 to calculate the area of the Square"+"\n"+"d)Enter 4 to calculate the area of the Rectangle"+"\n"+"e)Enter 5 to calculate the area of the Cube"+"\n"+"f)Enter 6 to exit the program");
choice = Double.parseDouble(value);
while (choice != 6) {
//if(choice!=1||choice!=2||choice!=3||choice!=4||choice!=5)
// JOptionPane.showMessageDialog(null,"Wrong option entered", " error",
// JOptionPane.ERROR_MESSAGE);
if (choice == 1) { //calculate the area of circle
first = JOptionPane.showInputDialog("Enter the value of radius");
radius = Double.parseDouble(first);
area = Math.PI*radius*radius;
//print out the result
JOptionPane.showMessageDialog(null,"The area of the Circle: "+area,"result",JOptionPane.INFORMATION_MESSAGE);
} else
if (choice == 2) { //calculate the area of triangle
first = JOptionPane.showInputDialog("Enter the value of length");
second = JOptionPane.showInputDialog("Enter the value of width");
length = Double.parseDouble(first);
width = Double.parseDouble(second);
area = (width*length)/2;
JOptionPane.showMessageDialog(null,"The area of triangle: "+area,"result",JOptionPane.INFORMATION_MESSAGE);
} else
if (choice == 3) { //calculate the area of square
first = JOptionPane.showInputDialog("Enter the value of length");
length = Double.parseDouble(first); //change string into integer
area = length*length;
JOptionPane.showMessageDialog(null,"The area of the square: "+area," result",JOptionPane.INFORMATION_MESSAGE);
} else
if (choice == 4) { //calculate the area of rectangle
first = JOptionPane.showInputDialog("Enter the value of length");
second = JOptionPane.showInputDialog("Enter the value of width");
length = Double.parseDouble(first);
width = Double.parseDouble(second);
area = width*length;
JOptionPane.showMessageDialog(null,"The area of the rectangle: "+area,"result",JOptionPane.INFORMATION_MESSAGE);
} else
if (choice == 5) { //calculate the area of cube
first = JOptionPane.showInputDialog("Enter the value of length");
length = Double.parseDouble(first);
area = 6*length;
JOptionPane.showMessageDialog(null,"The area of the cube: "+area,"result",JOptionPane.INFORMATION_MESSAGE);
}
value = JOptionPane.showInputDialog("Please chose one of the options:"+"\n"+"a)Enter 1 to calculate the area of the Circle"+"\n"+"b)Enter 2 to calculate the area of the Triangle"+"\n"+"c)Enter 3 to calculate the area of the Square"+"\n"+"d)Enter 4 to calculate the area of the Rectangle"+"\n"+"e)Enter 5 to calculate the area of the Cube"+"\n"+"f)Enter 6 to exit the program");
choice = Double.parseDouble(value);
} //end of while loop
System.out.println("Program terminated\n");
System.exit(0);
} //end of main
}
De-obfuscated code snippet
import javax.swing.JOptionPane;
public class Program1
{
public static void main(String l1[]) {
String l10,O11;
double l100;
double O101,l110,l111,O1000;
String l1001 = " ";
l1001 = JOptionPane.showInputDialog("P\154\145\141se c\150o\163e\040\157ne of the \157\160\164i\157ns:" + "\012" + "\141\051\105\156t\145r\0401\040\164o\040\143alc\165late \164\150e\040\141r\145a\040of \164\150e\040C\151\162c\154e" + "\012" + "b\051Enter 2 t\157\040c\141lc\165l\141\164e the \141\162\145a\040o\146 t\150e\040Tr\151\141n\147\154e" + "\012" + "c\051Enter 3\040t\157 \143a\154\143ulate the ar\145\141 \157\146\040th\145 \123quar\145" + "\012" + "\144)\105\156\164\145r\0404\040t\157\040\143\141\154c\165\154a\164e\040t\150e\040ar\145a\040o\146 \164h\145 R\145c\164a\156g\154e" + "\012" + "\145)\105\156\164\145r\0405\040t\157\040\143\141\154c\165\154a\164\145\040\164h\145 \141\162ea\040o\146\040t\150e\040Cub\145" + "\012" + "\146)\105\156\164e\162 \066 \164o \145xit the p\162\157gr\141m");
l100 = Double.parseDouble(l1001);
while (l100 != 6) {
if (l100 == 1) {
l10 = JOptionPane.showInputDialog("\105n\164\145\162\040t\150e\040v\141\154\165\145\040o\146\040r\141\144iu\163");
O101 = Double.parseDouble(l10);
l111 = Math.PI * O101 * O101;
JOptionPane.showMessageDialog(null, "\124\150\145\040\141r\145a\040of\040\164\150e Ci\162\143l\145\072\040\040 \040" + l111, "result", JOptionPane.INFORMATION_MESSAGE);
} else
if (l100 == 2) {
l10 = JOptionPane.showInputDialog("Ent\145r\040\164\150e\040v\141l\165e \157\146\040\154en\147ht");
O11 = JOptionPane.showInputDialog("\105\156\164\145\162 \164h\145 value of\040width");
O1000 = Double.parseDouble(l10);
l110 = Double.parseDouble(O11);
l111 = (l110 * O1000) / 2;
JOptionPane.showMessageDialog(null, "T\150e area \157f\040t\162i\141\156g\154e: " + l111, "re\163ult", JOptionPane.INFORMATION_MESSAGE);
} else
if (l100 == 3) {
l10 = JOptionPane.showInputDialog("\105\156\164\145\162 \164h\145 value\040of lengt\150");
O1000 = Double.parseDouble(l10);
l111 = O1000 * O1000;
JOptionPane.showMessageDialog(null, "\124he area \157f \164h\145 \163\161uare: " + l111, " re\163ul\164", JOptionPane.INFORMATION_MESSAGE);
} else
if (l100 == 4) {
l10 = JOptionPane.showInputDialog("\105\156\164er t\150e\040v\141lu\145\040\157f len\147\164h");
O11 = JOptionPane.showInputDialog("E\156\164er the\040v\141l\165e \157\146 width");
O1000 = Double.parseDouble(l10);
l110 = Double.parseDouble(O11);
l111 = l110 * O1000;
JOptionPane.showMessageDialog(null, "T\150e are\141\040o\146 \164h\145 rectangle: " + l111, "\162\145\163\165\154t", JOptionPane.INFORMATION_MESSAGE);
} else
if (l100 == 5) {
l10 = JOptionPane.showInputDialog("E\156ter t\150\145\040v\141l\165\145\040of lengt\150");
O1000 = Double.parseDouble(l10);
l111 = 6 * O1000;
JOptionPane.showMessageDialog(null, "T\150e area \157f\040t\150e\040\143\165\142e: " + l111, "r\145sult", JOptionPane.INFORMATION_MESSAGE);
}
l1001 = JOptionPane.showInputDialog("P\154ease\040\143h\157s\145 \157ne of the options\072" + "\012" + "\141)\105\156\164e\162 \061 \164o c\141\154culat\145\040th\145 \141r\145a \157f\040th\145 \103i\162cl\145" + "\012" + "\142\051\105\156\164e\162 \062 to \143\141lculat\145\040th\145 \141re\141 \157f\040\164h\145 \124r\151an\147le" + "\012" + "c\051\105\156ter 3\040t\157 \143alc\165\154ate th\145\040ar\145a\040of\040t\150\145 \123q\165a\162e" + "\012" + "\144)Ente\162\0404\040t\157 \143alc\165\154ate th\145\040a\162\145\141\040o\146 \164\150e\040R\145c\164a\156g\154e" + "\012" + "\145)Ent\145\162 \065 \164o\040\143\141\154\143ula\164\145 \164\150\145\040a\162ea\040o\146 \164h\145 C\165b\145" + "\012" + "\146)\105\156\164e\162 \066 \164o \145\170it t\150e\040\160r\157\147r\141m");
l100 = Double.parseDouble(l1001);
}
System.out.println("\120r\157\147\162a\155 \164e\162mi\156a\164ed\012");
System.exit(0);
}
}
Obfuscated Symbol Cross Reference
Double -> Double
INFORMATION_MESSAGE -> INFORMATION_MESSAGEs
JOptionPane -> JOptionPane
Math -> Math
PI -> PI
Program1 -> Program1
String -> String
System -> System
area -> l111
args -> l1
choice -> l100
exit -> exit
first -> l10
javax -> javax
length -> O1000
out -> out
parseDouble -> parseDouble
println -> println
radius -> O101
second -> O11
showInputDialog -> showInputDialog
showMessageDialog -> showMessageDialog
swing -> swing
value -> l1001
width -> l110