Tools

Android Studio w/ adb

Yes, I know everyone hates it, but it’s the easiest way to setup an Android emulator.

We will need to deal with adb because installing apps, logcating all relies on it. The official documentation is very good.

Apktool

A tool for reverse engineering 3rd party, closed, binary Android apps. It can decode resources to nearly original form and rebuild them after making some modifications. It also makes working with an app easier because of the project like file structure and automation of some repetitive tasks like building apk, etc.

It extracts resources from a given apk file, including smali code, which can be imported into other applications for further investigation. Apktool can be found here.

jadx

It is a “Dex to Java decompiler”. It can create readable Java code from compiled dex classes (smali is more like assembly to me). jadx is in the official archlinux repository. Its GitGub repo can be found here.

Some picoCTF Examples

droids0

Where do droid logs go. Check out this file.

Logs can be found using logcat, which

is a command-line tool that dumps a log of system messages, including stack traces when the device throws an error and messages that you have written from your app with the Log class.

After launching the app, there’s a button with the text below saying “I’m a flag!”

droids0-1

Click on it, the text below changes to “Not Today…”.

droids0-2

Let’s check out the system logs. Use adb logcat to see them. So when clicking on the button, it actually prints the flag into the system log.

❯ adb logcat | grep PICO
04-21 15:41:13.559  3728  3728 I PICO    : picoCTF{a.moose.once.bit.my.sister}
04-21 15:41:33.443  3728  3728 I PICO    : picoCTF{a.moose.once.bit.my.sister}
04-21 16:33:24.460  3728  3728 I PICO    : picoCTF{a.moose.once.bit.my.sister}
04-21 16:36:03.321  4852  4852 I PICO    : picoCTF{a.moose.once.bit.my.sister}

droids1

Find the pass, get the flag. Check out this file.

This time, “brute force is not required”. There’s an input box, so maybe a correct input will print us the flag. Use apktool to extract the resources and open classes.dex in jadx.

It turns out that jadx can extract apk too, so the rest of this section I’m using only jadx.

Starting from MainActivity, there’s a buttonClick method.

public void buttonClick(View view) {
    String content = this.text_input.getText().toString();
    this.text_bottom.setText(FlagstaffHill.getFlag(content, this.ctx));
}

This leads us to the FlagstaffHill class.

public class FlagstaffHill {
    public static native String fenugreek(String str);

    public static String getFlag(String input, Context ctx) {
        String password = ctx.getString(R.string.password);
        return input.equals(password) ? fenugreek(input) : "NOPE";
    }
}

So, Context. It is a

Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.

The getString(int) method returns a string a localized string from the application’s package’s default string table. So check out resources.arsc/res/values/strings.xml and find the entry password.

<string name="password">opossum</string>

Enter the password and we get the flag. picoCTF{pining.for.the.fjords}

droids2

Find the pass, get the flag. Check out this file.

This time also comes with an input box, “smali sounds like an ikea bookcase”.

Take a look at jadx, this time there’s also FlagstaffHill.getFlag() method. But this time it’s a little bit tricky (?).

public static String getFlag(String input, Context ctx) {
    String[] witches = {"weatherwax", "ogg", "garlick", "nitt", "aching", "dismass"};
    int second = 3 - 3;
    int third = (3 / 3) + second;
    int fourth = (third + third) - second;
    int fifth = 3 + fourth;
    int sixth = (fifth + second) - third;
    String password = "".concat(witches[fifth]).concat(".").concat(witches[third]).concat(".").concat(witches[second]).concat(".").concat(witches[sixth]).concat(".").concat(witches[3]).concat(".").concat(witches[fourth]);
    return input.equals(password) ? sesame(input) : "NOPE";
}

This is equivalent to the following python code:

witches = ["weatherwax", "ogg", "garlick", "nitt", "aching", "dismass"]
second = 3 - 3
third = (3//3) + second
fourth = (third + third) - second
fifth = 3 + fourth
sixth = (fifth + second) - third
password = ".".join([witches[fifth], witches[third], witches[second], witches[sixth], witches[3], witches[fourth]])
print(password)

The password is dismass.ogg.weatherwax.aching.nitt.garlick, enter it and get the flag. picoCTF{what.is.your.favourite.colour}

droid3

Find the pass, get the flag. Check out this file.

“make this app your own”

This time the flag will never print because of the implementation

public class FlagstaffHill {
    public static native String cilantro(String str);

    public static String nope(String input) {
        return "don't wanna";
    }

    public static String yep(String input) {
        return cilantro(input);
    }

    public static String getFlag(String input, Context ctx) {
        String flag = nope(input);
        return flag;
    }
}

We have to somehow make getFlag() call yep instead.

Apktool can not only decode apks but also build apks with modified smali code. Let’s extract the apk using apktool. Under three/smali/com/hellocmu/picoctf there’s the FlagstaffHill.smali file. To modify the function being called, replace getFlag’s nope with yep.

.method public static getFlag(Ljava/lang/String;Landroid/content/Context;)Ljava/lang/String;
    .locals 1
    .param p0, "input"    # Ljava/lang/String;
    .param p1, "ctx"    # Landroid/content/Context;

    .line 19
-   invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->nope(Ljava/lang/String;)Ljava/lang/String;
+   invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->yep(Ljava/lang/String;)Ljava/lang/String;

    move-result-object v0

    .line 20
    .local v0, "flag":Ljava/lang/String;
    return-object v0
.end method

Recompile, sign and install the modified apk.

# Re-compile the app
# three is the base folder of the decompiled app
apktool b three

# Change directory to the newly generated APK
cd three/dist

# Generate a new key to sign the build
keytool -genkeypair -v -keystore key.keystore -alias publishingdoc -keyalg RSA -keysize 2048 -validity 10000

# Sign the new build
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ./key.keystore three.apk publishingdoc

# Uninstall previous version of the app and install the new one
adb uninstall com.hellocmu.picoctf
adb install three.apk

Click on the button again and we get the flag. picoCTF{tis.but.a.scratch}

droids4

Reverse the pass, patch the file, get the flag. Check out this file.

This challenge combined the techniques droids2 and droids3.

So the first part, reverse.

public class FlagstaffHill {
    public static native String cardamom(String str);

    public static String getFlag(String input, Context ctx) {
        StringBuilder ace = new StringBuilder("aaa");
        StringBuilder jack = new StringBuilder("aaa");
        StringBuilder queen = new StringBuilder("aaa");
        StringBuilder king = new StringBuilder("aaa");
        ace.setCharAt(0, (char) (ace.charAt(0) + 4));
        ace.setCharAt(1, (char) (ace.charAt(1) + 19));
        ace.setCharAt(2, (char) (ace.charAt(2) + 18));
        jack.setCharAt(0, (char) (jack.charAt(0) + 7));
        jack.setCharAt(1, (char) (jack.charAt(1) + 0));
        jack.setCharAt(2, (char) (jack.charAt(2) + 1));
        queen.setCharAt(0, (char) (queen.charAt(0) + 0));
        queen.setCharAt(1, (char) (queen.charAt(1) + 11));
        queen.setCharAt(2, (char) (queen.charAt(2) + 15));
        king.setCharAt(0, (char) (king.charAt(0) + 14));
        king.setCharAt(1, (char) (king.charAt(1) + 20));
        king.setCharAt(2, (char) (king.charAt(2) + 15));
        String password = "".concat(queen.toString()).concat(jack.toString()).concat(ace.toString()).concat(king.toString());
        return input.equals(password) ? "call it" : "NOPE";
    }
}
❯ javac ./four.java
./four.java:1: error: class FlagstaffHill is public, should be declared in a file named FlagstaffHill.java
public class FlagstaffHill {
       ^
1 error

Java is hard.

Create a modified FlagstaffHill class and print the password.

public class FlagstaffHill {
    public static String getFlag() {
        StringBuilder ace = new StringBuilder("aaa");
        StringBuilder jack = new StringBuilder("aaa");
        StringBuilder queen = new StringBuilder("aaa");
        StringBuilder king = new StringBuilder("aaa");
        ace.setCharAt(0, (char) (ace.charAt(0) + 4));
        ace.setCharAt(1, (char) (ace.charAt(1) + 19));
        ace.setCharAt(2, (char) (ace.charAt(2) + 18));
        jack.setCharAt(0, (char) (jack.charAt(0) + 7));
        jack.setCharAt(1, (char) (jack.charAt(1) + 0));
        jack.setCharAt(2, (char) (jack.charAt(2) + 1));
        queen.setCharAt(0, (char) (queen.charAt(0) + 0));
        queen.setCharAt(1, (char) (queen.charAt(1) + 11));
        queen.setCharAt(2, (char) (queen.charAt(2) + 15));
        king.setCharAt(0, (char) (king.charAt(0) + 14));
        king.setCharAt(1, (char) (king.charAt(1) + 20));
        king.setCharAt(2, (char) (king.charAt(2) + 15));
        String password = "".concat(queen.toString()).concat(jack.toString()).concat(ace.toString()).concat(king.toString());
        return password;
    }

    public static void main(String[] args) {
      System.out.println(getFlag());
    }
}
❯ javac ./FlagstaffHill.java
❯ java FlagstaffHill
alphabetsoup

Next, patch. We’re using the code from the previous challenge.

  if-eqz v5, :cond_0

- const-string v5, "call it"
+ invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->cardamon(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v4

- return-object v5
+ return-object v4

Recompile, sign and install the modified apk. Enter the password and we get the flag. picoCTF{not.particularly.silly}

Reference