- Protecting the Ideas Behind Your Code
- Obfuscation As a Protection of Intellectual Property
- Transformations Performed by Obfuscators
- Knowing the Best Obfuscators
- Potential Problems and Common Solutions
- Using Zelix KlassMaster to Obfuscate a Chat Application
- Cracking Obfuscated Code
- Quick Quiz
- In Brief
Cracking Obfuscated Code
Now that we have spent so much time talking about how to protect intellectual property through obfuscation, a few words are due on the strength of the protection. Does a good obfuscator make it hard to hack an application? Absolutely. Does it guarantee that the application will not be hacked? Not at all!
Unless flow control obfuscation is used, reading and working with the obfuscated code is not that difficult. The key point is finding a good starting point for decompiling. Chapter 2, "Decompiling Classes," presented several techniques for reverse engineering of applications, but obfuscation can defeat many of them. For example, the most effective way of locating a starting point is text searching through the class files. With string encoding, the search will yield no results because the strings are not stored as plain text. Package names and class names can no longer be used to learn about the application structure and to select a good starting point. It is still technically possible to decompile the application entry point and work your way through the control flow for a decent-size application, but it is not feasible.
For flow-obfuscated code, the most sensible method of learning the application implementation is using a good old debugger. Most IDEs come with debugging capabilities, but our case will require a heavyweight debugger capable of working without the source code. To find a good starting point for decompiling, the application needs to be run in debug mode. Java has a standard API for debuggers called Debugger API (duh!) that is capable of local as well as remote debugging. Remote debugging enables the debugger to attach itself to an application running in debug mode and is a preferred way of cracking the application. Good debuggers display in-depth information about running threads, call stacks for each thread, loaded classes, and objects in memory. They enable you to set a breakpoint and trace the method executions. A key for working with obfuscated applications is to use the regular interface (UI or programming API) to navigate to a feature of interest and then to rely on the debugger to learn about the class or classes that implement the feature. After the classes are identified, they can be decompiled and studied as described in Chapter 2. Working with debuggers is covered in detail in Chapter 9, "Cracking Code with Unorthodox Debuggers."