Auto de-obfuscation of crash stacktraces
Bugs in mobile apps as in software in general are a fact of life, no matter how much testing time you invest. There are just too many permutations of hardware and software and of course users do unexpected things. Fault finding can be impacted if you are following security best practise and using a code obfuscator. Obfuscating your app could increase developer time and effort, when trying to understand error stack traces caused by application crashes. This is because the details of the classes have been obfuscated, making it difficult to identify which part of the application has encountered the error.
In this article, we are going to look at how to convert obfuscated crash logs back to something readable and review several popular crash reporting services. We’ll be focusing on the following obfuscation tools:
- ProGuard is the default obfuscator shipped with the Android SDK. It’s free to use and comes with default Android configuration.
- DexGuard is the commercial version of ProGuard that has been enhanced and entirely specialized for Android. Also DexGuard is supported by some popular crash reporting services.
Manual deobfuscation using ReTrace
One of the outputs of the ProGuard obfuscation process is a mapping.txt file. This file in combination with the Retrace tool (part of the ProGuard distribution) allows developers to reconstruct and replace the symbols in the crash stack trace with the original class details.
Example command to deobfuscation
retrace.sh -verbose mapping.txt your_error_stacktrace.txt > deobfuscated_out.txt
There’s a good article on the manual process of obfuscating crash stack traces using the ReTrace tool by Danial Goodwin here. Note that the process is the same for DexGuard.
Crash Reporting / Analytics services
Manual deobfuscation is suitable when the crash occurs on a device you physically have access to, as you can pull the crash details via the Android Debug Bridge (adb). However, once you’ve released the app in to production, obtaining a user’s device is very difficult. This is where crash reporting and/or mobile analytics services can help.
Let’s look at several of the popular mobile analytics and crash reporting services in a head to head comparison.
*Note: since publishing this article Google Play now offers ProGuard support with manual upload of mappings.txt file.*
*BrokenOpenApp is open source self hosted and so could be modified to support DexGuard or other command line deobfuscation tool.
Here’s some more details on each of the services that support deobfuscation out of the box.
Crashlytics is part of Twitter’s Fabric platform which is a collection of SDKs designed to help mobile iOS and Android app developers. Crashlytics is very simple to set up with IDE plugin but can also be configured manually if like me you prefer to know what’s going on. You can track crashes from different app build types separately (i.e debug/test/live). If you’re using gradle, simply configure your build to use different app IDs (package names) for each build type. One of the other pluses is that it’s easy to separate apps into organisations, making it perfect for personal and professional app developers. Non-fatal or handled exceptions are supported out of the box and toggling them on/off in the Crashlytics dashboard is simple. Turning off non-fatal crashes is crucial when trying to focus on errors that are actually causing your application to force close.
Your app’s mappings file is automatically uploaded as part of the Crashlytics gradle plugs (similar features are offered in the Ant plugin) and crashes are auto deobfuscated so they can be grouped accordingly. This makes reviewing them a lot easier.
More info on the Crashlytics Android SDK DexGuard and ProGuard setup
A nice feature of Crittercism is that you can choose where your data is stored either in the EU or US — essential for some businesses. I’d say the Crittercism is more focused as an analytics solution and unfortunately the functionality is quite limited in the free pricing plan. For example, handled exceptions are supported out of the box, but are part of the paid plan.
There is an API to upload your app’s mapping.txt file. Here’s an example curl command to upload a mapping file:
However, it’s a shame Crittercism haven’t wrapped this in a gradle plugin to handle the upload automatically. The issue with manual uploading of mapping.txt is that you have to have a method/system to keep track of each of the mapping files and their corresponding apk files. Once your crashes show up in the console, you have to go into the crashes details and request deobfuscation -this is not immediate and is queued for an undetermined length of time.
More info Crittercism Android SDK docs for ProGuard setup http://docs.crittercism.com/android/android.html#configuring-proguard-symbolication
I’ve used Hockeyapp for several apps and it used to be my default way of distributing app betas. I’ve since switched to the Google Play store alpha/beta distribution as crucially it doesn’t require testers to enable installing apps from unknown sources.
Hockey app is geared towards beta testing and I see the crash reporting feature as an add on. Illustrated by the lack of support for handled exceptions. You can handle it manually by creating and wrapping an exception and using ExceptionHandler.saveException(e, listener); . However if you go down this route there’s no way of separating them in the crash reports console. As mentioned with Crittercism the manual upload of the mappings is cumbersome.
The dashboard for crashes, while is functional and shows which devices/users encountered the crash it gets unwieldy once you move into production and encounter a larger numbers of issues. On the plus side Hockeyapp does support DexGuard even if it’s not mentioned in the documentation.
More info on setting up Hockey app’s Android SDK docs for ProGuard http://support.hockeyapp.net/kb/client-integration-android/hockeyapp-and-proguard
I’ve not used BrokenOpenApp and from what I’ve seen it doesn’t match the other fully featured crash services. However, it does offer automatic ProGuard deobfuscation. I included BrokenOpenApp in this comparison due to it being one of the only self hosted open source options available.
Crashlytics is the clear winner of our little head to head. Not only does it support both DexGuard and ProGuard but it handles the uploading of mapping files and automatic deobfuscation of crashes. So no need for additional developer input which results in no increase in bug/fault finding time. I can honestly say it’s weight off my mind not to have to worry about keeping track of mapping files.
On top of that, the Crashlytics integration is easy and the dashboard puts analysing your app’s crashes as top priority. Oh by the way, did I mention it is free!