In software development, obfuscation is the act of creating source or machine code that is difficult for humans to understand. Like obfuscation in natural language, it may use needlessly roundabout expressions to compose statements. Programmers may deliberately obfuscate code to conceal its purpose (security through obscurity), or its logic or implicit values embedded in it, primarily, to prevent tampering, deter reverse engineering, or even to create a puzzle or recreational challenge for someone reading the source code. This can be done manually or by using an automated tool, the latter being the preferred technique in industry.
Sensitive code should never be written in Java/Kotlin
Java/Kotlin code obfuscation is infamously easily to de-obfuscate and reverse engineer. The first course of action is that the sensitive part of the code* should never be written in these programming languages. If for some reason it is the only course of action, then its best to protect this sensitive part of the code through a dedicated solution rather than only relying on the obfuscation.
As a best practice for developing high-value applications, languages that compile directly to assembly should be used such as C/C++/Rust etc.
*Sensitive code: the business logic layer of the program that processes/sends/receives sensitive information about the users or processes that has great value for the service provider.
Obfuscation is great to have, yet it brings side-effects when applied to whole application
Many times, the transformations that are applied to obtain an obfuscated code means that:
a) Dead code would be injected into the program
b) Additional layers of dead-ended looping would be created
c) Additional characters and values would be introduced to redirect the code, and much more.
In these cases, a very common result is that the application tends to bulk in size. It could also mean that the performance of the application is also reduced which is a red flag from a programming standpoint and a user experience standpoint. Furthermore, there is also a possibility of the application “breaking” or crashing.
Full applications, upon which obfuscation is applied, makes it harder for the developer to then identify bugs and fix them. They will require some sort of mapping technology solution which will aid in bridging the problem area in the obfuscated code to the original plain code to continue developing.
Application code (full app; written in Java/Kotlin) which is obfuscated through the modern tools, can be easily de-obfuscated and decompiled using tools like JEB tool. For native code, tools like Ghidra or IDA Pro can be used to achieve the same results. Look at the decompiled code (similar to source code) and eventually perform code manipulations. There are videos titled “JEB in action” in which a newbie could investigate the classes and identify the logic as well as articles in which obfuscated applications are looked into via tools like JEB tool. The important thing to understand is that the goal here is to prevent the application from being manipulated . This requires additional steps and a more direct approach around obfuscation.
In addition to the previous point, an obfuscated binary is not fully protected from reverse engineering. True protection from reverse engineering is implemented either in a centralized manner, such as relay of the resources of the application with a central server for proofing instruction sequence patterns, system calls etc or in a decentralized way such as securely embedding important information within the protected part of the application and implementing guard codes and check sums over the important part of the application, which makes it harder for the attacker to pierce through.
Where does obfuscation truly matter?
Obfuscation matters in the sensitive part of the code where important information is being processed. A binary block which 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 safekeeping 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.
Elements which hold far more precedence than obfuscation in application security
To achieve security mechanisms that repels attackers as much as possible, other mechanisms need to be in place. Such as, protection against the use of application in an environment of escalated privileges such as a rooted or jailbroken phone, emulators, hooking frameworks such as FRIDA or Xposed, debugged phone/application and others.
Additionally, the communication between the application and the servers needs to be protected from sniffing and Man-in-the-Middle (MitM) attacks. This means that sensitive applications cannot rely only on the security offered by TLS or other public protocols, and are required to have more layers of security, such as payload encryption and certificate pinning. Protection of API keys – thus protecting the backend from being accessed by unknown parties is equally important.
Storing information in an encrypted form inside the mobile application sandbox and the ability to “self-destruct” this database from memory upon detection of an attack prepares the application for the worst and protects in the event of an attack. Similarly protecting and encrypting the assets that are bundled with the application such as server certificates for TLS is important to keep the integrity of the processes and avoid scalable attacks (When one instance of an app on a device is compromised, the other instances are not affected).
A strong external trust-anchor is also important for the secure attestation of an application instance that requests to be initialized – this increases the trust of service provider on the application that tries to connect to the service backend to carry out the business logic. Providing an additional layer of trust on top of the layers built into the mobile application.
Build38 provides a comprehensive solution to protect Mobile Applications and Mobile Services from attackers. Obfuscation is one of the approaches that our solutions use to prevent threats, but not the only one. We invest continuous efforts in researching and improving obfuscation mechanisms so we can provide the best and strongest in-App protection solution to the market.
To learn more about the role of obfuscation in modern applications and other important security artefacts that hold key importance, reach out to us today, we are keen to understand your challenges in securing your services.