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;
if(flag3)
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
ariev
August 2, 2010
Is coddec must running under JDE or just in ms-dos?
Antonio
August 24, 2010
Patch file not found 😦
s7ephen
September 19, 2010
We will be fixing all the old articles (links, images, etc) in the next few days.
Ab
October 19, 2010
Hey s7ephen,
Any luck on fixing the link for coddec patch?
s7ephen
October 22, 2010
The codec patch download link is fixed, sorry for the delay. I am in the process of cleaning up all the other broken stuff.
AbTY
September 17, 2010
Hi, can you upload again the coddec.patch.
Tx
s7ephen
October 22, 2010
Ok, sorry for the delay folks, but I have fixed the codec patch link in the article, but here it is also:
http://github.com/s7ephen/dontstuffbeansupyournose.com/blob/master/bberry/coddec.patch
I am in the process of fixing all the other broken links on the site as well. Sorry for the delay.
Reshma
February 14, 2011
Could you please guide us on how to apply the patch to the original coddec?
Thanks
Antonio
March 30, 2011
Yes, it looks like I also have a different version of sources and patch does not match.
fatslim
July 12, 2011
hi, s7ephen
as u now ,the latest jde has added some new opcodes, do u have any interesting to release a new patch for newer jde like jde 6.0 above?
kunss
January 22, 2012
C:\coddec>java.exe -classpath c:\coddec\bin\Release net.rim.tools.compiler.Compi
ler XXXX.cod
null
java.io.EOFException
at net.rim.tools.compiler.io.StructuredInputStream.read(StructuredInputS
tream.java:125)
at net.rim.tools.compiler.io.StructuredInputStream.readByte(StructuredIn
putStream.java:133)
at net.rim.tools.compiler.io.StructuredInputStream.readUnsignedShort1(St
ructuredInputStream.java:184)
at net.rim.tools.compiler.codfile.FixupTableEntry.read(FixupTableEntry.j
ava:52)
at net.rim.tools.compiler.codfile.FixupTableEntry.(FixupTableEntry
.java:72)
at net.rim.tools.compiler.codfile.DataSection._doaZ(DataSection.java:551
)
at net.rim.tools.compiler.codfile.DataSection.addClassRefs(DataSection.j
ava:279)
at net.rim.tools.compiler.codfile.Codfile.processCodeSegment(Codfile.jav
a:144)
at net.rim.tools.a.coddec.enumerateModules(coddec.java:920)
at net.rim.tools.a.coddec.parseFile(coddec.java:955)
at net.rim.tools.a.coddec.main(coddec.java:982)
at net.rim.tools.compiler.Compiler.main(Compiler.java:3836)
kunss
January 22, 2012
I am getting the following error… kindly let me know how to resolve it.
C:\coddec>java.exe -classpath c:\coddec\bin\Release net.rim.tools.compiler.Compi
ler XXXX.cod
null
java.io.EOFException
at net.rim.tools.compiler.io.StructuredInputStream.read(StructuredInputS
tream.java:125)
at net.rim.tools.compiler.io.StructuredInputStream.readByte(StructuredIn
putStream.java:133)
at net.rim.tools.compiler.io.StructuredInputStream.readUnsignedShort1(St
ructuredInputStream.java:184)
at net.rim.tools.compiler.codfile.FixupTableEntry.read(FixupTableEntry.j
ava:52)
at net.rim.tools.compiler.codfile.FixupTableEntry.(FixupTableEntry
.java:72)
at net.rim.tools.compiler.codfile.DataSection._doaZ(DataSection.java:551
)
at net.rim.tools.compiler.codfile.DataSection.addClassRefs(DataSection.j
ava:279)
at net.rim.tools.compiler.codfile.Codfile.processCodeSegment(Codfile.jav
a:144)
at net.rim.tools.a.coddec.enumerateModules(coddec.java:920)
at net.rim.tools.a.coddec.parseFile(coddec.java:955)
at net.rim.tools.a.coddec.main(coddec.java:982)
at net.rim.tools.compiler.Compiler.main(Compiler.java:3836)