Assembly 101 on Android Dalvik Code

Recently, I have been meddling with Android theme resources to modify the theme for my Android-based Galaxy Tab. It was yet another great learning process,  which involves manipulating the graphic resources, replacing the de-compiled XMLs that control the layouts and styling of the interface, etc. Just as I thought I had enough of them, I fumbled on a theming problem which seemed so impossible to fix. I pinpointed the offending code, created the right “answer” to the problem,  but it just didn’t work!

Almost giving up, I decided to trace the source code of the module. It turns out that the code explicitly sets the color of the text (the theming “bug”), and thus all the layout and style modification attempts would not have any effect at all.

   if (entry.label != null) {
            holder.appName.setText(entry.label);
            holder.appName.setTextColor(getResources().getColorStateList(
            entry.info.enabled ? android.R.color.primary_text_dark : android.R.color.secondary_text_dark));
   }

Instead of going back to source codes for changes, I contemplated reverse-engineering. Thankfully with the help of smali, an assembler/disassembler tool for Android apk,  I could correct the problem on the executable directly. Addictive Tips  gave a good overview of an Android application in ODEX and DEODEX format,

WHAT IS AN ODEX FILE?

In Android file system, applications come in packages with the extension .apk. These application packages, or APKs contain certain .odex files whose supposed function is to save space. These ‘odex’ files are actually collections of parts of an application that are optimized before booting. Doing so speeds up the boot process, as it preloads part of an application. On the other hand, it also makes hacking those applications difficult because a part of the coding has already been extracted to another location before execution.

THEN COMES DEODEX

Deodexing is basically repackaging of these APKs in a certain way, such that they are reassembled intoclasses.dex files. By doing that, all pieces of an application package are put together back in one place, thus eliminating the worry of a modified APK conflicting with some separate odexed parts.

In summary, Deodexed ROMs (or APKs) have all their application packages put back together in one place, allowing for easy modification such as theming. Since no pieces of code are coming from any external location, custom ROMs or APKs are always deodexed to ensure integrity.

So before I could attempt the “hack”, the application must be DEODEX’ed, so that we have the complete executable for disassembly. The executable in Android system is in .dex format, or Dalvik Executable, and is stored as classes.dex within the Android Package (.apk) along with other application resources (graphic resources, layout binaries, etc). I extracted out the classes.dex, and do a disassembly.

java -jar baksmali.jar -o out  classes.dex

This will disassemble the executable classes.dex into assembly codes in the folder named out. This step can be skipped if you have previously used APK Tool to decompile Android package to access to the XML codes. The latter however would not assemble the assembly codes when you compile using the tool, so the subsequent steps would still be required if you have made changes to the assembly code.

In my case, the offending code is ManageApplications$ApplicationsAdapter, and the section of the code matches the

    invoke-virtual {v3, v4}, Landroid/content/res/Resources;->getColorStateList(I)Landroid/content/res/ColorStateList;

    move-result-object v3

    invoke-virtual {v2, v3}, Landroid/widget/TextView;->setTextColor(Landroid/content/res/ColorStateList;)V

I simply commented off the third line in the above section of the code, which effectively eliminates the set color instruction. I proceeded to re-assemble the codes,

 java -jar smali.jar -o  classes.dex  out

The output of the assembler is a modified classes.dex, which I then re-package it to the original APK (Settings.apk).