phone

Mobile app security: How to avoid reverse engineering of an Android app

 
Mobile app security is the issue of the highest priority for all app developers and an essential part of product quality. However, despite a fast-growing mobile market, the level of piracy is disappointing, especially in Android ecosystem.

Unfortunately, the application is easy to crack, disable advertising, and even untie from verification services. Making strong efforts to create an app and hoping to receive income, in the end, you can not only fail but also “lose” it.

Also, some may wish to crack the app (device, program, software) to find out how it works in order to steal your ideas to make something better or even just reproduce it.

This practice is called reverse engineering and used in many spheres including manufacturing and even military. In this post, we’ll speak about the ways to protect your Android app against reverse engineering.

Applying to Android, reverse engineering process represents the ways of extracting a source code and resources from APK file (a zip archive). APK of a target application can be got from a phone by using ADB or just by downloading it from Google Play Market.

 

PROBLEM:

 

APK decompiling isn’t a big deal. By decompiling of an APK file and transforming dex files -> jar files -> java source codes you can receive the app source code. And here tools like Apktool, dex2jar, jd-gui and JAD are always ready to help you out.

Nevertheless, it’s practically impossible to completely protect the product from reverse engineering and thus ensure the highest mobile app security level.

However, you can make app cracking much harder. Let’s consider our experience in protecting applications.

 

OUR EXPERIENCE:

 

1. Use ProGuard
 
To ensure mobile app security and avoid reverse engineering of an Android application we use a ProGuard tool. ProGuard represents a Java class file shrinker, optimizer, obfuscator, and preverifier as well. It works as follows:
 

  • The shrinking step is responsible for determining and removing of unused classes, fields, methods, and attributes.
  • The optimization step makes the analysis and optimization of the methods’ bytercode.
  • The obfuscation step renames the remaining classes, fields, and methods using short meaningless names.

 
These steps allow making code base smaller, more efficient, and more complicated to a reverse-engineer. The final preverification step is responsible for adding preverification information to the classes, required for Java Micro Edition and for Java 6 and higher.

One should note that obfuscation can be undone by using deobfuscator, where APK De-Guard is one of the most accurate deobfuscators, as it uses machine learning for achieving the best results.

 
2. Move important code parts on the server
 
Speaking about other useful ways and methods that help avoid reverse engineering, we also move the most critical parts of the service out of the application into a web service, hidden behind a server side language.

Imagine, you have a unique algorithm. You obviously don’t want reverse engineers to steal it out of your product. So, you can move the algorithm, making it process the data on a remote server, and use the application to provide it with the data.

 
3. Write important parts of code in C/C++
 
Sometimes we also use the NDK to write important parts of our code natively into .so files and add them as a compiled library.

While it can be disassembled into assembly code, reverse engineering process of a large library from the assembly is rather time-consuming. Comparing to C/C++, Java is easier to decompile.
 

4. Use SSL
 
Apply SSL when interacting between the server and device. In some cases, you’ll need your custom certificate. And the class that implements the X509TrustManager or SSLSocketFactory interface may contain trivial methods.

It can result in a loss of confidentiality of the data transferred an SSL / TSL protocol. Often methods of this class are trivial (accepting all certificates), that makes the application vulnerable in the middle (MitM) attacks.

By providing a valid self-signed certificate an attacker can violate the confidentiality of the connection and get an access to valuable data. Even if the methods of the redefined class aren’t trivial, their implementation is likely to have mistakes leading to the same consequences.

Unfortunately, it’s widespread. Our research showed that about 40% of mobile applications have an incorrect implementation of this class.
 
Follow our recommendations to solve the following SSL problems:

  • Check the validity of the certificate each time when establishing a connection via a SSL / TLS protocol.
  • Use standard implementations of X509TrustManager.
  • If accepting self-signed certificates is necessary, generate your own X509TrustManager implementation using KeyStore. Also, specify the certificates that should be taken and reject all others.

 
5. Don’t store values in a raw format
 
Also, we don’t use a raw format for values’ storage. For example, in case we need to store a user balance (an amount of application currency) or other values, we generally save encoded values (for instance, store them in the form of some algorithm).
 

6. Take care of user credentials
 
Another our recommendation that will help you avoid reverse engineering process refers to user credentials.

  • First, it’s better to minimize the frequency of asking for user credentials in the app. It will allow making phishing attacks more conspicuous, and less likely to be successful. In this case, we recommend using an authorization token (also, remember to refresh it).
  • Second, username and password shouldn’t be stored on the device (where it’s possible). We advise to complete the initial authorization with a username and password and use a short-lived authorization token.

In case you need to allow users to store their credentials to automate future authentication in your app, use Credential object containing a user’s sign-in information.
 

7. Hide your API keys
 
Usually, third party providers use an API key as a convenient authentication mechanism to grant access to these resources. What’s more, they use it as the way to charge for their data.

Don’t store the key in shared preferences, assets, resources folders or hard coded in Java – an attacker can easily unzip and decompile your APK and get this key. Use the NDK or Private/Public API key exchange to save your key.
 

8. Pay attention to hashing algorithm
 
The MD2, MD5, SHA1 hash functions have known vulnerabilities. If they are used to store valuable information (such as passwords), its confidentiality can be violated. Use secure hash functions (SHA-2).

A hash function used to store passwords shouldn’t only be resistant to collisions but also shouldn’t be too fast. This complicates the attack by exhaustive search. For this purpose, specialized hash functions have been developed: PBKDF2, bcrypt, scrypt.
 

9. Insecure use of reflection
 
It’s possible to execute arbitrary malicious code. The method implementing reflection takes data from an untrusted source as an argument. It allows attackers to manage the application control flow graph, as well as to bypass authentication mechanisms and access restrictions.
 
Our recommendations:

  • Create a whitelist of allowed commands and allow the user to choose only from the list. Don’t use user-entered data directly as an argument of methods that implement reflection.    
  • If the reflection is used in conjunction with configuration files, ensure the integrity and uniqueness of these files. Don’t set the reflection parameters in the configuration files in the absence of significant resources for solution security analysis.    

 

10. External storage usage
 
Files written to the external storage device are readable by all applications and can be changed when the user connects the device to the computer in a USB drive mode.

Besides, files stored in external storage will remain there even after the application is deleted. It may result in the valuable data confidentiality loss. That’s why we store files in the internal memory or use SQLite database.

 
Nevertheless, to completely protect an application from reverse engineering is almost impossible. However, these ways and practices help us maximally secure Android apps.

We advise you to use them to protect your mobile solutions from cracking and provide a higher mobile app security level.