Jni
Decompile JNI.apk with apktool, go direct to fr.heroctf.jni.MainActivity class as indicated in AndroidManifest.xml.
...
<activity android:name="fr.heroctf.jni.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
...
fr.heroctf.jni.MainActivity is defined in smali/fr/heroctf/jni/MainActivity.smali. checkFlag function quickly grabbed eyeballs. As it’s a native function, we need to look for the lower-level implementation, which is in lib
.
...
invoke-virtual {p0, v0}, Lfr/heroctf/jni/MainActivity;->checkFlag(Ljava/lang/String;)Z
...
# virtual methods
.method public native checkFlag(Ljava/lang/String;)Z
.end method
There are 4 so for 4 architectures respectively.
lib/
lib/x86
lib/x86/libnative-lib.so
lib/arm64-v8a
lib/arm64-v8a/libnative-lib.so
lib/armeabi-v7a
lib/armeabi-v7a/libnative-lib.so
lib/x86_64
lib/x86_64/libnative-lib.so
I decompiled the one for x86_64, lib/x86_64/libnative-lib.so.
ulong Java_fr_heroctf_jni_MainActivity_checkFlag
(_JNIEnv *param_1,undefined8 param_2,_jstring *param_3)
{
char *input;
size_t len;
long in_FS_OFFSET;
byte ret;
uchar is_copy;
long canary;
canary = *(long *)(in_FS_OFFSET + 0x28);
input = (char *)GetStringUTFChars(param_1,param_3,&is_copy);
if ((((is_copy == '\x01') && (len = strlen(input), len == 3)) && (*input == '6')) &&
((input[1] == '6' && (input[2] == '6')))) {
ret = 1;
}
else {
ret = 0;
}
if (*(long *)(in_FS_OFFSET + 0x28) == canary) {
return (ulong)ret;
}
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
According to the way it check flag, it’s easy to point out what the kernel is, by adding the flag prefix and suffix, the flag is Hero{666}
.