Post

DROID - Squirrel CTF Writeup

Walkthrough for the DROID Android reverse engineering challenge from Squirrel CTF.

DROID - Squirrel CTF Writeup

Challenge Info

FieldDetails
CTFSquirrel CTF
ChallengeDROID
CategoryAndroid / Reverse Engineering

Challenge Description

1
this is not the android you're looking for

Solution

We can start by installing the droid.APK to our emulator and check what is it about The first screen is pretty simple, it has a user input and a button that does some kind of checking

alt text

If we input anything random we get textview with a message Incorrect! Now, we can open this APK in Jadx and try to understand the logic

alt text

This main activity is not the actual Main activity, the actual logic behind the Main Activity is stored in some kt/kotlin source file When we input a random string in the app we get a message Incorrect!, So in Jadx we can perform a global search for the string Incorrect! to identify where its coming from

1
2
3
4
5
6
7
8
9
public static final Unit TextBoxWithButton$lambda$13$lambda$12$lambda$11(MutableState isTextChecked$delegate, MutableState text$delegate, MutableState resultText$delegate) {
        Intrinsics.checkNotNullParameter(isTextChecked$delegate, "$isTextChecked$delegate");
        Intrinsics.checkNotNullParameter(text$delegate, "$text$delegate");
        Intrinsics.checkNotNullParameter(resultText$delegate, "$resultText$delegate");
        TextBoxWithButton$lambda$8(isTextChecked$delegate, true);
        resultText$delegate.setValue(check(TextBoxWithButton$lambda$1(text$delegate)) ? "Correct!" : "Incorrect!");
        return Unit.INSTANCE;
    }
}

This code snippet is from the original kotlin file - MainActivitykt, in there we see that a method check is being used

alt text

We see two int arrays key and expected, our input is being xored with the key and compared against expected And since xor is symmetric, we can reverse engineer the correct input be it result by, result[i] = key[i] ^ expected[i]

1
2
private static final int[] key = {29, 231, 186, 121, 34, 225, 137, 22, 224, 209, 63, 142, 249, 193, 157, 144, 124, 72, 5, 96, 157, 221, 103, 68, 40, 45, 109, 136, 123, 173, 37};
private static final int[] expected = {110, 150, ComposerKt.reuseKey, 72, 80, 147, 236, 122, 155, 186, 15, 250, 149, 240, 243, ComposerKt.reuseKey, 21, 59, 90, 3, 173, 237, 86, 27, 70, 28, 30, 188, 23, 153, 88};

The value of ComposerKt.reuseKey is also hardcoded we just need to click on it to view it in Jadx, the value is 207 Finally, we can write a python script to xor the arrays

1
2
3
4
5
6
key = [29,231,186,121,34,225,137,22,224,209,63,142,249,193,157,144,124,72,5,96,157,221,103,68,40,45,109,136,123,173,37]
expected = [110,150,207,72,80,147,236,122,155,186,15,250,149,240,243,207,21,59,90,3,173,237,86,27,70,28,30,188,23,153,88]
result = ""
for i in range(len(expected)):
    result += chr(expected[i] ^ key[i])
print(result)

We just need to run this script, FLAG:squ1rrel{k0tl1n_is_c001_n1s4l4}

This post is licensed under CC BY 4.0 by the author.