2
InsomniDroid – crackme solution

It’s a bit amusing that this solution for the InsomniHack CTF challenge named “InsomniDroid” was written up past midnight because I couldn’t sleep. Regardless, this was typed up as a play-by-play analysis taken from my crib notes when I actually was solving the crackme, so try to bare with me as this may read a bit odd. While some of the steps might seem odd – I find it is often just easier to tackle each APK in the same manner. This sets up a nice way to quickly find the call-stack and how things get executed and where. When tackling this challenge, I attempted to only use baksmali, opposed to any other tools for simplicity and since not everyone has IDA Pro. Anyway, if you haven’t downloaded the challenge yet you can get it from root-me.org or from this local mirror (MD5: c2f94fd52c8f270e66d8b16e07fe93e4). If you haven’t solved the challenge yet, I’d recommend to stop reading here and give it a good try.

Starting off, we shoudl take a quick look at the AndroidManifest.xml through AXMLPrinter shows which is the main activity;

Now we see what where to start our search without opening the app yet, toss that crackme into baksmali and get ready for the output. No baksmali tricks in place, so we can just take a look right at the main activity, InsomniActivity. The only interesting bits for us is the call to compute method on keyBytes and setting an onClick listener for the validate button;

Seems weird that we’re computing something, though never doing anything with the returned result. Let’s just take note of that and come back later. If we look into the onClick listener (InsomniActivity$1) we can see what is going on deeper in the app;

Here we can see the bulk of this onClick listener just grabs the text from the EditText widget and uses it as a parameter for the checkSecret function. Now onward to the checkSecret function;

Ok, this doesn’t help us much. As we can see from the inlined comments I put above, all it’s doing is a SHA-256 hash for our input and comparing it to secretHash – which obviously must also be a SHA-256 digest. Let’s see if we can find this being set anywhere;

Only one hit – this is good. Let’s go back into Compute.smali and check out whats actually going on. Once we get in here we can see what appears to be, some left over code, along with an array-fill for the secretHash which is trigger the sput-object search we just performed. Let’s get the hash;

6152587ede8a26f53fd391b055d4de501ee8b2497fe74f8fd69f2c72e2f3e37a

And toss that into a hashcat… Maybe it’s an easy one to get and I won’t have to do any other work… Probably not – that would seem like a brute force challenge and not a crackme one, definitely not something simple like that for someone named “crypto girl”. So lets keep looking!

Looking back at Compute.smali lets looks back into that function, compute([B) we noticed being called earlier in the APK – but never had the return value used. This one looks interesting because (1) it’s seems left over, is called once but not using the return value and (2) it’s the only place certain left over variables are being touched like c1_null, c2 and is also expecting the parameter keyBytes which we also have a variable for.

This seems interesting… It’s taking in the keyBytes as a parameter, using them to create a SecretKeySpec then using the ivBytes to initialize an IvParameterSpec. Then it attempts to decrypt the c1_null variable, though it does nothing with this return value. After that, we decrypt something that is much larger and again, don’t do anything with the value. Essentially this maps out to the following java code;

At this point I’m assuming I just solved this — run the app, look at the output… Garbage — it’s just not UTF-8 (or UTF-16) characters. That can’t be it — I don’t think the challenge would be to include non-ascii characters!

After staring at this a bit longer I decided to look at the lengths of what is being output. result has a length that will always going to be 16. p2 will end up having a length that is always being divisible by 16… Well – lets try some operations between the two resulting arrays that aren’t being used. First one I tried was XOR’ing them together (everyone loves XOR, malware writers, crackme writers, etc, etc) — and this ended up being exactly what needed to be done.

After running this we get the output;

Ah – Crypto girl left us a nice crypto related message. Essentially explaining what went on here. Fun stuff and definitely glad I didn’t wait for hashcat to try and spit out that password.

Tim
2 Comments
  1. Well done Tim!
    Actually, based on your feedback & of other colleagues, the version I released at InsomniHack was slightly different: the keyBytes contained clearly fake data (deadbeef + a reference to epic fail) and the apk had been obfuscated by proguard.
    I’ll write up the crypto explanation to this soon. Currently busy with BlackHat slides!!
    Cheers

  2. Great Job!

Your Name Email Website