Intive Blog

Protecting our code – ProGuard

After having finished the development of an Android application and having consulted different sources, I found it is very simple to get a decompiled code of an APK file using almost any java decompiler and some other tool to convert the apk into a jar (and its consequent .class)

The problem here is that anyone who can access the APK can access sensitive data of the application, such as passwords or keys that the app uses to authenticate, for instance, with some external service.

On the other hand, it would be possible not only to access all these sensitive data but also all our code, which is perfectly readable once it is decompiled (except for some resources which are referenced by ids that, although they can be traced, they would be a bit more difficult to localize).

Because of this, I suggest to take a look at ProGuard, a tool which will help us protect our code.

 

What is ProGuard?

ProGuard is a utility provided by Android to:

  • Optimize our APK.
  • Eliminate references to a code which is not used.
  • Obfuscate code (useful to prevent reverse engineering attacks).
  • Reduce the APK size.

 

How is it added to my project?

We must compile the project using Gradle or Ant. On Gradle the following is added to the build.gradle file:

By default, the minify is usually in false, to have it disabled. The file by default proguard-android.txt only obfuscates code: getDefaultProguardFile(‘proguard-android.txt’)

The file proguard-android-optimize.txt does some “magic” at the background to check if it can optimize our application, besides obfuscating the code: getDefaultProguardFile(‘proguard-android-optimize.txt’).

 

Could a string be hidden so it is not seen when decompiling?

If you want to hide some key or url that has “hardcode” in the code, ProGuard will not hide it when obfuscating the code since it only changes names of attributes and classes, but not values.

A way of hiding sensitive information is consequently to use cryptography in the source code for keys, urls, etc.

Anyway, the best way to hide them from possible attacks of reverse engineering would be to store this information in a server and query it through a secure connection when needed from the application.

 

What issues may come up?

We can face issues when using libraries to de-serialize or serialize (GSON, Jackson, etc). Attributes get obfuscated and must be defined explicitly. On GSON, for instance, a class can be defined as follows:

The annotation @SerializedName, should be used explicitly, otherwise, the attribute in the json is looked for with the same name of the attribute (this would happen in this case with the email field that does not have the annotation).
It may happen that the classes used by the project are deleted, so they should be excluded by hand (using a custom file of rules):

The default ProGuard configuration file tries to cover general cases, but you might encounter exceptions such as ClassNotFoundException, which happens when ProGuard strips away an entire class that your application calls. You can fix errors when ProGuard strips away your code by adding a -keep line in the ProGuard configuration file. For example: -keep public class.

The lines –keep can be added in the proguard-rules.pro files of each module of the application. If obfuscation of some class or class member is to be avoided the following can be used:

 

What to do with obfuscated stacktraces?

Stacktraces can also be obfuscated and, if we try to read them, it is almost impossible to trace the origin of this issue. For this, the file mapping.txt can be used, which is generated when building the APK that specifies what attribute/class was transformed and what name was given to it eventually. This can also be done automatically using the scripts provided by Android in the sdk:

Crashlytics uses it by default so there is no problem to see obfuscated stacktraces if we use it.

 

An example of non-obfuscated class

An example of obfuscated class

 

Conclusion

ProGuard helps us keep some things “hidden” and to make things a bit tougher for those willing to get data from our code. It is also very useful to reduce the number of classes and methods of the application and, thereby, to reduce the size of the APK generated. However, it is not an ultimate solution to hide sensitive data and should that be the case, we would have a look for a more elaborated solution.

Gastón Goncalves

He has been with intive – FDV since 2012. As of February 2015, he has been an Android developer. Previously he was a Drools and Java EE developer. He is currently studying I.T. engineering at Universidad de Buenos Aires (UBA). He was also a teacher at UBA, teaching Algorithms and Programming II in the Engineering department.

Add comment