CSAW'23 - AndroidDropper (Misc)

This is a walkthrough for a relatively easy Android challenge which requires simple knowledge of how to read java code (I am serious).

Challenge

AndroidDropper problem statement

Solution

First off, we open the given dropper.apk file in JADX, an Android Application Decompiler.

In the Main Activity, we can see that it tries to write a dropped.dex to the file system which was base64 encoded.

try {
	byte[] decode = Base64.decode("<<base64 of dropped.dex here>>", 0);
    FileOutputStream openFileOutput = openFileOutput("dropped.dex", 0);
    openFileOutput.write(decode);
    openFileOutput.flush();
    openFileOutput.close();
} catch (IOException e) {
	e.printStackTrace();
}
Dump dropped.dex

It then tries to call the getFlag method presumably from dropped.dex after loading it.

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
File file = new File(getFilesDir(), "dropped.dex");
Method method = null;
try {
  cls = new DexClassLoader(file.getAbsolutePath(), getCacheDir().getAbsolutePath(), null, getClassLoader()).loadClass("com.example.dropped.Dropped");
} catch (ClassNotFoundException e2) {
  e2.printStackTrace();
  cls = null;
}
try {
  obj = cls.newInstance();
} catch (IllegalAccessException | InstantiationException e3) {
  e3.printStackTrace();
  obj = null;
}
try {
  method = cls.getMethod("getFlag", null);
} catch (NoSuchMethodException e4) {
  e4.printStackTrace();
}

There are many ways to get the dropped.dex file, we are lazy so simpy copy the base64 into CyberChef and use the From Base64 function, saving the file as dropped.dex.

Next add the file in JADX. We will see the following in JADX sidebar with the dex loaded

Sidebar showing dropped.dex loaded

To get the flag, simply copy the Dropped code exactly and add a main function calling getFlag

Compile it with javac Dropped.java and run it with java Dropped

Flag: csawctf{dyn4m1c_lo4deRs_r_fuN!}

Full code below:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;

/* loaded from: C:\Users\Adrian\Desktop\download.dex */
public class Dropped {

    public static void main(String[] args) {
        try {
            System.out.println(getFlag());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    static byte[] notTheFlag;

    public static String getFlag() throws IOException {
        String str;
        HttpURLConnection httpURLConnection = (HttpURLConnection) new URL("http://misc.csaw.io:3003").openConnection();
        try {
            try {
                httpURLConnection.connect();
                str = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream())).readLine();
            } catch (Exception e) {
                e.printStackTrace();
                httpURLConnection.disconnect();
                str = "";
            }
            notTheFlag = Base64.getDecoder().decode(str);
            return obf(275, 306, 42);
        } finally {
            httpURLConnection.disconnect();
        }
    }

    public static String obf(int i, int i2, int i3) {
        int i4 = i2 - i;
        char[] cArr = new char[i4];
        for (int i5 = 0; i5 < i4; i5++) {
            cArr[i5] = (char) (notTheFlag[i + i5] ^ i3);
        }
        return new String(cArr);
    }
}