Thursday, June 9, 2011

Solving Binary 300 From the Defcon 2011 Quals Using AndBug

Binary 300 was provided in the form of a memory dump, a few encrypted files, and a classes.dex. For this walkthrough, we will use AndBug and ApkTool for analysis, and python for implementing a cipher I wouldn't use to protect HBGary's address book.. Let alone my phone pr0n.

The classes.dex had an invalid checksum and version (666); updating the version to 035 and regenerating the checksum let us use dexdump to dump Dalvik pseudocode from classes.dex.

Immediately, it became obvious that this was "LokPixLite," an image-encryption app in the Android Market; we downloaded LPL from the market, compared the dex files to verify our assumption using AndroGuard, and rebuilt the dex file using "apktool d -d" and "apktool b -d" before installing into an emulator.

We then used the emulator to encrypt a few reference images with a known password, then went to the decompiled source, we see there's a rat's nest of obfuscated methods in class "g" that are packed full of references to "XOR" and "SHA1". What we need to sort this out is some context.. A trace of call flow with arguments will do nicely:
$ ./andbug trace -p com.closecrowd.lokpixlite com.closecrowd.lokpixlite.g

This command instructs AndBug to connect to LokPixLite, and use JDWP to produce METHOD_ENTRY events for every method of "g"; we then decrypt one of our images by submitting the password:
[::] setting hooks
[::] hooked com.closecrowd.lokpixlite.g
[::] hooks set
[::] thread <1> main com.closecrowd.lokpixlite.g.d()Ljava/lang/Boolean;:0
this = <obj Lcom/closecrowd/lokpixlite/g; #c1406db458>
[::] thread <1> main com.closecrowd.lokpixlite.g.b()V:0
this = <obj Lcom/closecrowd/lokpixlite/g; #c1406db458>
[::] thread <1> main com.closecrowd.lokpixlite.g.d()Ljava/lang/Boolean;:0
this = <obj Lcom/closecrowd/lokpixlite/g; #c1406db458>
[::] thread <10> password com.closecrowd.lokpixlite.g.a(Ljava/lang/String;)V:0
this = <obj Lcom/closecrowd/lokpixlite/g; #c1406db458>
p1 = test
[::] thread <10> password com.closecrowd.lokpixlite.g.e()V:0
this = <obj Lcom/closecrowd/lokpixlite/g; #c1406db458>
[::] thread <10> password com.closecrowd.lokpixlite.g.b(Ljava/lang/String;)[B:0
p0 = test
[::] thread <1> main com.closecrowd.lokpixlite.g.d()Ljava/lang/Boolean;:0
this = <obj Lcom/closecrowd/lokpixlite/g; #c1406db458>
[::] thread <10> loading com.closecrowd.lokpixlite.g.a()V:0
this = <obj Lcom/closecrowd/lokpixlite/g; #c1406db458>
[::] thread <10> loading com.closecrowd.lokpixlite.g.a()V:0
this = <obj Lcom/closecrowd/lokpixlite/g; #c1406db458>
[::] thread <10> loading com.closecrowd.lokpixlite.g.a()V:0
this = <obj Lcom/closecrowd/lokpixlite/g; #c1406db458>
[::] thread <10> loading com.closecrowd.lokpixlite.g.a([BIZ)[B:0
this = <obj Lcom/closecrowd/lokpixlite/g; #c1406db458>
p2 = 16
p1 = 830009846960
p3 = False
[::] thread <10> loading com.closecrowd.lokpixlite.g.b([BIZ)[B:0
this = <obj Lcom/closecrowd/lokpixlite/g; #c1406db458>
p2 = 16
p1 = 830009846960
p3 = False

We can see our password, "test" is submitted to b(Ljava.lang.String;) to get a [B (byte array) back, which is then stashed in a global variable. Later, we see a byte array with the encrypted data passed to b([BIZ]), which returns our plaintext image.

At this point, we have found the two key functions in the cipher -- the conversion of a password to a key, and applying the key to the ciphertext. We flip back to static analysis, at this point with our context data to analyze the code. The method teases apart pretty easily with context, resulting in the following python implementation:
def decrypt(data, key):
mask = sha1sum(key)[:8]
return strxor(data[16:], cycle(mask))

After that, it is simply a round of using strings to find all the passwords in the heap dump, and applying them in turn until we get a valid JPEG decode. From there, the password's easy to read if you squint, and it's on to the next level.

Wednesday, February 16, 2011

Closing the Loop -- Re-Engineering Android Applications

A lot of people have been asking for slides or more tutorial material for Android reverse engineering after my talks at BSides and Shmoocon. Problem is, neither of these cons have actually recorded the talks -- instead, I have put together a screencast demonstrating the workflow involved in re-engineering an application, adding a password logger and verifying its operation. This has two benefits -- first, it demonstrates some of these techniques without being redundant with my "Android Reverse Engineering Using the Emulator" and "Android Anatomy" talks, and it serves as a good demonstration for non-hackers, showing how easy it is to patch applications.



This technique is very common in the Android Market right now, with people modifying apps for good and bad reasons -- at some point, Google is going to have to do some level of verifing "good" applications and "responsible" developers, because the current market is packed with apps that demonstrate varying levels of naughtiness.

Monday, January 31, 2011

mp3collect.go -- reorganizing mp3 files by hashes of their mpeg-1 content


A friend asked me a couple weeks ago for a sample of what a "real" Go program looks like. I have been using Go quite a bit for fuzzers and analysis packages at IOActive for the last few months, but I obviously can't share those with anyone else. On the flight back from Shmoocon, I decided to write a Go program to solve a problem that has been slowly building up in my ~/music directory.


It's a real trainwreck; between cycles of using iTunes and copying my music between devices I now have this mass of duplicated songs that have tweaked ID3 tags so I cannot simply de-duplicate them using hashes. The solution is to calculate a hash for the actual MPEG frames frames in each file and ignore all the helpful metadata.


The program does just that by constructing hard links between a file and the hash of its media contents; duplicates are reported and left intact. The plan is to go back through those files and normalize their ID3 metadata using a program that doesn't try to "organize" my music -- Quod Libet. (Or the Android music player, which is too dumb to attempt any of this.) There is, of course, room for improvement -- it does not handle FLAC, OGG or M4A files, which do occur in my library due to certain stores using non-MP3 formats. (Trent Reznor, Rhythmbox and iTunes, respectively.) It also should have a way of properly handling cross-filesystem collections by copying the file instead of hardlinking.



mp3collect.go