Usually, obfuscators are used to protect Java programs. Obfuscators allow you to rename classes, methods, variables, change the control flow (bypass code). These functions are able to do all obfuscators including free and paid.
The goal of obfuscating bytecode is to build such a set of JVM commands from which the decompiler would not be able to build the correct source code in the Java language.
Confrontation obfuscators and decompilers continues constantly.
')
For example, in the framework of the
Soot research project, the
JBCO obfuscator and the
DAVA decompiler are being developed at the same time, whose developers are competing with each other.
Why should intruders and bona fide developers need to decompile Java programs?
- Reverse engineering proprietary API
- Modifying bytecode to disable various licensing mechanisms
- Accessing sensitive information
The classic obfuscator deals relatively well with protection against the second type of attack. From reverse engineering, it helps weakly, because Java programs use a Java API that is publicly available and obfuscator cannot change it. There is one exception, but this is not even an obfuscator, but a full-fledged virtual machine with a native Java API implementation -
Excelsior JET .
It’s not a secret to anyone that at present there is a “boom” of Trojans who, using vulnerabilities in the JVM, penetrate the user's computer to carry out their malicious actions, most of all in relation to programs that work with financial and other valuable information.
Modern means of protecting Java code should rather not protect it from decompiling, but organize a sandbox inside a Java sandbox :)
We encountered these problems when developing a licensing system for Java / Java FX applications -
C3 . And so was born
Stringer .
Now back to reality. Most of the logic that developers of commercial Java applications would like to protect (including various applications for Android) is tied to strings ... Oh, those java.lang.String's.
For example. We have a graphical client that receives data in a certain format from an Internet resource, parsit and displays it to the user. It’s enough for an attacker to gain access to a Java class constant pool and it’s easy to make a clone program.
Usually, developers use their string encryption functions to protect against these attacks or use obfuscators with support for these functions.
Stringer is perfectly able to perform this task:
- Encryption is implemented on the basis of the AES algorithm with dynamic encryption keys for each protected Java package.
- The logic of the decryption functions is dynamically embedded in the already existing class files:
Fragment of the decompiled class file before embedding the protection:
public class App { public static void main(String args[]) { System.out.println("Hello World!"); } }
Fragment of the decompiled class file after embedding protection:
public class App { public static void main(String args[]) { System.out.println(main("\u916E\u2E67\uCB8D\u16B9\u479D\u7669\u3F20\uD7DC\u75C5\u30F1\uEC7E\uA26B\uEEB0\u2F0E\u4828\u19C6")); } .... }
- Protecting the context of calling the decryption functions
Plus the possibility of organizing a sandbox mentioned above: protection against the use of reflection, protection of private fields of classes and methods, protection of final fields of classes against modification.
We believe that almost every developer needs encryption of strings, and for companies that want to protect users of their products from information theft, Stringer allows you to organize a secure environment within a Java application, but this topic deserves a separate post ...
We are currently developing a Stringer for Android applications.
Stay tuned :)
PS
By the way, our CrackMe so no one hacked.
In addition to Habr users, Javalobby users took a very active part. In total, there were about a thousand downloads, and only one of the participants reached the stage of interaction with the licensing server.