Disassembling Version 6 BlackBerry apps

Posted on January 7, 2009 by


Now and again I have to disassemble BlackBerry apps.  BlackBerries pretty much run all Java code.  You might think this would mean everything was .class files and you could jad everything, but this is not the case.  Everything gets compiled to “.cod” files, a file format I have found very little information about on the Internets.  (possibly due to poor googling skills, or as I like to call it “living it up” since I have converted to the dark side and love Microsoft now)

“Live it up” enough and you’ll come across Dr. B0lsen who has apparently been reversing BlackBerry apps for quite some time.  His team(?) released “coddec”, a BlackBerry “decompiler”.  Disassembler is more correcter, since the result is pseudo-Java that contains partially reconstructed BlackBerry JVM assembly code.

As mentioned on his site, there is a flaw in the disassembler that causes it to fail on certain files (parsing certain “Member Refs”).  Also, it cannot parse cod files produced by newer JDE’s (any COD file with a version number of 6 will bomb out in coddec).  Typically you’ll get a stacktrace with something about “no class ref found at offset BLAH”

Totally changing gears, if you download the official BlackBerry JDE, unzip rapc.jar, jad the .class files, and compare with coddec you may notice some similarities 🙂

This led me to presume that coddec was derived from perhaps an older BlackBerry JDE that predates “Version 6” COD files.  So I created two workspaces in Eclipse and loaded each version. I really don’t like Eclipse because I have an irrational hatred of GUIs but its code refactoring (for Java anyway) is actually pretty awesome.  Using elite string-searching skills I was able to rename rapc class files to their more sensibly named coddec counterparts, in order to see if there were obvious bugs in the coddec source that could cause it to fail parsing newer Cod files.

The most obvious differences were in “DataSection.java” and “k.java” (RAPC equivalent of DataSection.java).  In the implicit member ref parsing, there is a new class in the 4.7.0 JDE that doesn’t exist in the coddec source:

coddec: net\rim\tools\compiler\codfile\DataSection.java

public boolean _ifaZ(net.rim.tools.compiler.io.StructuredInputStream __input, net.rim.tools.compiler.codfile.CodfileVector __codFileVector, boolean flag)
throws IOException

__input.verifyOffset(__codFileVector.getOffset(), “implied member fixup table”);

net.rim.tools.compiler.codfile.MemberRef memberRef = new net.rim.tools.compiler.codfile.MemberRef(__input, this);
__codFileVector.addElement(new net.rim.tools.compiler.codfile.FixupTableEntry(__input, memberRef, 2, _aliasesFlag, flag1));

rapc: net\rim\tools\compiler\d\k.jad

public boolean _mthif(a a3, ag ag1, boolean flag, boolean flag1)
throws IOException

a3.a(ag1.bT(), “implied member fixup table”);

au au1 = w(a3.gw());
ak ak1 = ae().ai(a3.gw());
int i2 = a3.gw();

int j2 = 0;
j2 = a3.gw();
Object obj = flag3 ? ((Object) (new at(au1, ak1, i2, j2))) : ((Object) (new j(au1, ak1, i2)));
ag1.addElement(new an(a3, ((ap) (obj)), 2, ff, flag2));

You can see some of the obvious similarities.  The newer JDE also appears to benefit (suffer?) from an optimizing compiler that has inlined portions of the “at” and “j” constructor calls into the main body of the _mthif call.  “j” it turns out is the “MemberRef” from coddec, while “at” is some new mysterious class that must be related to “MemberRefs” (whatever they are), but requires an additional 2-byte short in order to parse (the “gw” call, it turns out, reads 2-byte shorts).

Anyway I basically did this sort of comparison for a few classes in order to find those parts that needed to be fixed for Version 6 cod files.  I ended up renaming “at to “AdvancedMemberRef” for lack of a better name.  There were some fixes I had to make to header parsing in DataSection to get it to deal with V4/5/6 files correctly, plus I added labels and corrected jump targets for gotos and other things.

There are some other gotchas too: the BlackBerry JVM is not the same as the standard JVM.  For the most part you can read it like regular Java JVM.  But, for example, the “stringlength” opcode is non-existant in standard Java.  Something to keep in mind especially if you want to rip code out of BlackBerry apps to run standalone.

All this is rolled up into a patch (warning! I curse like a drunken sailor IRL and in code!) you can apply against the original coddec source.  Compiling and running this crap is left as an exercise to the reader.  P’raps some of the patches will inspire a dedicated BlackBerry reverser to take the time to make a beautiful disassembler.  I don’t have the inclination to make beautiful things, but there are apparently many people still running into coddec-limitations so maybe this is better than nothing.  Anyway and thanks to Dr. B0lsen