At last, I have got some free time to put up what I’ve been up to for the past few months. The second round of inCTF ‘14 is over and our team is selected in for the final round. I wouldn’t say it went very well but, that was all I could do alone. I should post a write-up on those challenges too. Hope, it won’t disappear into my always-wanted-to-do list.
The first day of Anokha, there was an announcement in the registration desk about this strange event - Puzzle of Phi. It involves installing an Android app and answering a series of questions and answers to level up. People solving the entire 20 levels are qualified for the next level. Since, it was the first time I’m hearing about this event, I went online and checked out the info. One thing which caught my eye under the Rules & Regulations tab was
Tampering with the application is forbidden and any such practice will lead to disqualification
As far as I heard, the app is completely offline. So, I was quite puzzled by how exactly the Event organizers are going to decide whether there was any tampering involved. I was actually more challenged to find out the method employed for tampering detection.
Coming down to the business. You can download the app from here - Puzzle of Phi
Now, extracting the app, gives the usual directory structure of any standard Android app. Nothing much to see here. Heading over to theres/drawable-hdpi directory gives me the pictures used in the app. First thing, One would noticed that the size of the app is annoyingly large for the purpose it serves. It all comes from the high resolution images in this directory.
Moving on to the XMLs in the layout directory. As suspected earlier, there was 20 layouts for all 20 different questions. Opening any of the layouts in a HEX editor will enable one to look at the elements used in that particular layout. We could get glimpses of question in each levels. But, just getting to know the 20 questions is not enough. We need Q & A in pairs. So, moving on to the dex file at the root of the app package. Running ‘strings’ on it (extracts ASCII string from the binary file), prints out a lot of strings being used in the app. Piping the output to grep with the answers which were already found showed that they are of course, present in it.
strings classes.dex | grep $answer
But still, we just don’t want to check just if the answer string is present. We need to GET the answers from it. I had a really stupid idea for a moment, of writing a script to check the strings in classes.dex with a dictionary. But then, I remembered something I once used some years back. Here, comes APKTool. It’s quite handy when coming to reverse engineering Android apps.
We’ll try looking into the app now
apktool d ./com.example.puzzleofphi.apk I: Baksmaling... I: Loading resource table... I: Loaded. I: Decoding AndroidManifest.xml with resources... I: Loading resource table from file: /home/gTux/bin/apktool/framework/1.apk I: Loaded. I: Regular manifest package... I: Decoding file-resources... I: Decoding values */* XMLs... I: Done. I: Copying assets and libs...
Heading over to the decoded directory, we can see a directory called smali which contains the entire code in smali format. Heading over to
Now, running a simple grep with a wildcard (of course, after a lot of tinkering with the results) will give all the solutions which were hard-coded.
grep 'const-string v2' p*$1.smali -m1
To get a neater solution list, sorted properly, pipe it through sort.
grep 'const-string v2' p*$1.smali -m1 | sort -n -k1
The corresponding output
#!basic p1$1.smali: const-string v2, "newspaper" p2$1.smali: const-string v2, "needle" p3$1.smali: const-string v2, "salt" p4$1.smali: const-string v2, "fallen leaves" p5$1.smali: const-string v2, "hands" p6$1.smali: const-string v2, "river" p7$1.smali: const-string v2, "sand" p8$1.smali: const-string v2, "time" p9$1.smali: const-string v2, "oil" p10$1.smali: const-string v2, "tree" p11$1.smali: const-string v2, "paradox" p12$1.smali: const-string v2, "bee" p13$1.smali: const-string v2, "space" p14$1.smali: const-string v2, "arrow" p15$1.smali: const-string v2, "sun" p16$1.smali: const-string v2, "air" p17$1.smali: const-string v2, "volcano" p18$1.smali: const-string v2, "hourglass" p19$1.smali: const-string v2, "iceberg" p20$1.smali: const-string v2, "secret"
As far as I could see, there was no mechanism to detect whether the app has been tampered with.
I’m no expert when it comes to reversing Android apps. If I had missed anything or if there are any simpler of ways of doing it, please do make a comment accordingly. I’d be happy to correct myself and learn something new.