This one I didn’t actually solve in time, because I spent too much time trying to a) Use frida and b) RE the args to the two import functions.
Because I am a fan of Frida (first cutting my teeth on it during the 2015 Flare On challenge), I decided I would use it in lieu of a debugger for this challenge (I didn’t want to figure out the toolchain to get the lldb client running on my mac).
Starting with dex2jar
I took the apk apart and took a quick peek at the two main classes. They use JNI to call into two functions in the provided dynamic library, and then generate the flag based on result. Because one function seeds the Java code to generate the flag, and the other takes the same input, but only returns success, I spent almost no time in Java land and instead went directly into looking at the native code.
Loading up the library in IDA, I was a little intimidated because of the unfamiliar ISA and what looked like a parser. I decided to try to do this dynamically, so this is when I decided frida-trace
would be my friend.
Setting up frida
is very straight forward:
adb install Sharif_CTF.apk
adb push frida-server /data/local/tmp
adb shell
su
/data/local/tmp/frida-server
I could then instrument the application and play around with it.
frida-ps -U|grep ctf
frida-trace -U -p <pid> -i '*isCorrect*'
I spent way more time than I would like to admit here, playing with Memory.read<X>
trying to read out the arguments and return value, but the problem was that this function is provided a Java string, whose structure I am unfamiliar with. Part of the complexity of the native functions are surely just getting the C string out of the String
object, but I didn’t feel like figuring that out.
If I wanted to see what was going on easily I’d want to find a function that takes C strings, which are easy to read from. Lucky for me, the isCorrect
function imports strcmp
from libc.so. It can’t be that easy… can it?
frida-trace -U -p <pid> -i '*strcmp*'
Editing the created strcmp.js:
onEnter: function (log, args, state) {
log("strcmp(" + Memory.readUtf8String(args[0]) + "," + Memory.readUtf8String(args[1]) + ")");
},
And then just hitting ‘Login’ on the app:
2059 ms strcmp(Serial Number,ef57f3fe3cf603c03890ee588878c0ec)
Now, remember that this isn’t the flag, but what is compared against to determine if we have the correct login. We could fake the retval from this function to return true, but that would make the flag generation fail. Instead, just enter ‘ef57f3fe3cf603c03890ee588878c0ec’ into the prompt, which will be passed to both lib function, which should properly seed the Java code, and see the flag pop out.
flag: Sharif_CTF{833489ef285e6fa80690099efc5d9c9d}
Last modified on 2016-02-14