Application Obfuscation

What is Application Obfuscation?[1]

Application Obfuscation refers to a set of technologies used to protect an application and its embedded intellectual property (IP) from application-level intrusions, reverse engineering, and hacking attempts. Application obfuscation tools protect the application code as the increasing use of intermediate language representations (such as Java and .NET) enables hackers to easily reverse-engineer IP embedded in the software.

Obfuscation Techniques[2]

Obfuscation involves several different methods. Often, multiple techniques are used to create a layered effect. Programs written in software languages that are compiled, such as C# and Java, are easier to obfuscate. This is because they create intermediate-level instructions that are generally easier to read. In contrast, C++ is more difficult to obfuscate, because it compiles machine code, which is more difficult for people to work with. Some common obfuscation techniques include the following:

  • Renaming. The obfuscator alters the methods and names of variables. The new names may include unprintable or invisible characters.
  • Packing. This compresses the entire program to make the code unreadable.
  • Control flow. The decompiled code is made to look like spaghetti logic, which is unstructured and hard-to-maintain code where the line of thought is obscured. The results from this code are not clear, and it's hard to tell what the point of the code is by looking at it.
  • Instruction pattern transformation. This approach takes common instructions created by the compiler and swaps them for more complex, less common instructions that effectively do the same thing.
  • Dummy code insertion. Dummy code can be added to a program to make it harder to read and reverse engineer, but it does not affect the program's logic or outcome.
  • Metadata or unused code removal. Unused code and metadata give the reader extra information about the program, much like annotations on a Word document, that can help them read and debug it. Removing metadata and unused code leaves the reader with less information about the program and its code.
  • Opaque predicate insertion. A predicate in code is a logical expression that is either true or false. Opaque predicates are conditional branches -- or if-then statements -- where the results cannot easily be determined with statistical analysis. Inserting an opaque predicate introduces unnecessary code that is never executed but is puzzling to the reader trying to understand the decompiled output.
  • Anti-debug. Legitimate software engineers and hackers use debug tools to examine code line by line. With these tools, software engineers can spot problems with the code, and hackers can use them to reverse engineer the code. IT security pros can use anti-debug tools to identify when a hacker is running a debug program as part of an attack. Hackers can run anti-debug tools to identify when a debug tool is being used to identify the changes they are making to the code.
  • Anti-tamper. These tools detect code that has been tampered with, and if it has been modified, it stops the program.
  • String encryption. This method uses encryption to hide the strings in the executable and only restores the values when they are needed to run the program. This makes it difficult to go through a program and search for particular strings.
  • Code transposition. This is the reordering of routines and branches in the code without having a visible effect on its behavior.

Should I Obfuscate and Secure my Application?[3]

If you are releasing valuable software (especially Java, Android, .NET, and iOS) anywhere outside your immediate control and you are not distributing the source code, obfuscation should probably be part of your application development process. Obfuscation makes it much more difficult for attackers to review the code and analyze the application. It also may make it hard for hackers to debug and tamper with your application. The end goal is to make it difficult to extract or discover useful information, such as trade secrets (IP), credentials, or security vulnerabilities from an application. It should also make it more difficult to modify application logic or repackage an application with malicious code.

Where Obfuscation Matters[4]

Obfuscation matters in the sensitive part of the code where important information is being processed. A binary block that is responsible for processing sensitive data should be the part where obfuscation and other security features need to be implemented, to fully protect the sensitive data and all the processes around it. Even in this case, security through obscurity (obfuscation) plays only a small role in the safekeeping of the information. This may raise the question from the perspective of an attacker if they only see a particular part of the code obfuscated – Wouldn’t they put all their energy and focus into understanding and de-obfuscating that part of the code? The answer is yes they will. And that is why it is important to implement much more in terms of security (refer to the section below for more information) to achieve a level that will keep an attacker busy for a long-time in the hope that they would eventually give up.

Disadvantages of Obfuscation[5]

While obfuscation can make reading, writing, and reverse-engineering a program difficult and time-consuming, it will not necessarily make it impossible.

  • It adds time and complexity to the build process for the developers.
  • It can make debugging issues after the software has been obfuscated extremely difficult.
  • Once code becomes abandonware and is no longer maintained, hobbyists may want to maintain the program, add mods, or understand it better. *Obfuscation makes it hard for end users to do useful things with the code.
  • Certain kinds of obfuscation (i.e. code that isn't just a local binary and downloads mini binaries from a web server as needed) can degrade performance and/or require Internet.

Tools for Obfuscation[6]

There are a number of tools in the market but here we take a look at the most commonly-known tools:

  • PreEmptive DashO: It scores well on platform versatility and comes with quite a lot of useful features like renaming, string encryption, tamper detection, debug detection, watermarking, and control flow. It provides complete technical support irrespective of the customer category and has a great UI. Its built-in rules help configure the settings swiftly. It supports many types of Jaya and Kotlin applications.
  • GuardSquare’s ProGuard: Proguard has certain limited capabilities when compared to DexGuard since it is its lite version. Configuration, on the positive side, is easier and it also comes with some preinstalled configurations. Though the developer support is decent, additional controls might be required to move to DexGuard. It supports text-based configuration, only helps with renaming functionality, and doesn’t score very well when it comes to UI.
  • GuardSquare’s DexGuard: It works only on Java and has better features than the ProGuard version. The features are similar to what DashO offers (control flow, encryption, runtime checks, etc.) It offers a multi-layered hardening approach and users can go for these “add-ons” on top of their packages. When it comes to support, it has “basic” and “gold” levels. Just like its lite version, it supports only text-based configuration. Developers can add API calls through its API-based features.

See Also

Source Code


Further Reading