Protecting the source code of an application can originate from several motivations. Modern applications are becoming more and more the result of an expensive, intensive development cycle and should be protected against adversaries. You don't leave high profile assets unprotected, neither should your source code be. Besides the economical factor, it is also a problem for security. Source code is often the place where crackers or adversaries in general will look when they want to bypass some sort of authentication. The general rule however, still holds: "Never rely on security through obscurity". Nevertheless,
you should not make it too easy, it might throw the attacker off from digging any further. The problem, in particular with distributed applications, is the fact that (malicious) users download the application to their devices and have full control of the execution environment. Nothing stops the adversary from dumping your application and try to reverse engineer (RE) your source code. Some steps can be taken to protect your source code against reverse engineering.
Before we dive into solutions against reverse engineering, it is important to stress that there is no such thing as a silver bullet when it comes to protecting your code. It is not a solvable problem, but very well a manageable problem. Attackers always work with one important question in mind: "Is the effort, that I have to put in, enough to justify the gain I get out of it?". It is your job to slow the attacker down as much as you can, in the ideal case the attacker decides it is not worth his efforts. Several solutions exist against reverse engineering that a developer can deploy, obfuscation being the most important one.
Obfuscators take perfect, human-readable, source code and will transform it to a hard-to-read format. The source code stays 100% syntactically and semantically correct. This strategy results in very difficult to read source code when an attacker tries to decompile your code. However, there is a catch here. If the application uses some public API (like for example system calls to the OS), these calls are not obfuscated. Through these calls the attacker will
work his way back into the code by renaming methods. This will take time, but it is proven numerous times that this is an effective de-obfuscation method. It should be noted that this consumes a huge amount of time and requires a lot of insight in the obfuscated source code.
Guards are pieces in your source code that are inserted at strategical places. These guard will monitor and check the runtime environment. Some common checks that guards can evaluate:
- Application running on a rooted or jailbroken device?
- Running on a debugger?
- Instrumentation used to place hooks in the source code?
- Resource verification, check if resources are tampered with
Guards are able to shutdown the application if one of these checks detect an unwanted execution environment.
Where possible, deploy cryptography to protect modules of the application that are currently not being used. Only decrypt and load modules
when necessary. This is considered something for experts, as it is not an easy task to perform successfully.
In conclusion, it should be clear that protecting code is a very serious and important task. It should be a standard step in your release cycle before you distribute your application.