Monday, April 15, 2013

Fixing Resource Identifiers in Disassembled Apps

If you have ever attempted to reverse an Android application, you've probably noticed that resource identifiers (think "R" values) show up as cryptic constants in disassembled smali code. This can be frustrating when attempting to reverse and understand the application's flow.  A rather contrived example of this issue is demonstrated below.

Imagine we write an application with a single activity. This activity simply inflates and shows a defined layout, which I've called "my_layout".


We defined this layout in our "res/layout/" directory. Its contents are not really important, but they are listed below anyways.


Once we start reversing this application, we will likely use apktool (or just baksmali) to disassemble the DEX bytecode. If we then examine the disassembled "ExampleActivity.smali" file, we notice that the "onCreate" method looks as follows:


What does the value 0x7f03 mean? What I didn't show before was that while we were coding away, Eclipse was helping us by bridging the gap between our resource files and our Java sources with the "R" class. This class creates an anonymous class for each resource type, and sets an integer value for every resource we define. We can then access our resources in our Java code with the syntax like "R.layout.my_layout", or "R.string.secret_message".  When compiled, this value is replaced with the integer value.

To make the mapping, we could inspect the various R$*.smali anonymous classes, but there is actually a better place to find these value. These values also appear in the "res/values/public.xml" file created by the Android application packaging tool ("aapt") during the build.


Since "public.xml" is an XML file, we can parse it using python with relative ease. This is where "fix_resources.py" comes in. "fix_resources.py" will parse the "public.xml" file, then search for instances of resource identifiers in our smali sources.  It will append a useful string on these lines, to make our job a little easier.


It will also resolve any string-type resource identifiers from the "res/values/strings.xml" file.  Let's say that we changed our "onCreate" method to copy a string from a resource file (no idea why you would want to do this), and print the value to the log:


Now, when we run apktool and "fix_resources.py" on our app, we will see that "fix_resources.py" has actually included the string's value in the code (it will truncate the string if it is too long).


I don't expect many applications to use this technique to obfuscate or hide sensitive strings, but overall "fix_resources.py" is a quick and painless way to add some addition annotations to your disassembled code.  Because the modifications are comments, apktool/smali will have no problem repackaging the code if you want to modify and rebuild the application.

"fix_resources.py" requires the lxml python module to run, but it's a pretty straightforward install.  You can grab the "fix_resources.py" script from my GitHub account.  Feel free to report any bugs or comments with the code!

-jakev