4.1 KiB
Difficulty
Difficult
Category
Reverse Engineering
How To Solve
You can again use any utility you like to analyze the APK; in this writeup we use JADX. Decompile the APK using jadx oats3.apk
.
Open the the MainActivity.java
file in the obtained folder, and take a look at the following lines. This is where the toppings are defined.
public void onCreate(Bundle savedInstanceState) {
...
String oats3 = getIntent().getStringExtra("oats3");
final Ref.ObjectRef oatsToppings = new Ref.ObjectRef();
oatsToppings.element = new String[]{"Peanut butter", "Strawberry", "Sugar", "Honey", "Peach", "Blueberry", "Pear"};
if (Intrinsics.areEqual(oats3, "oats3")) {
oatsToppings.element = gmFunc.ensure((String[]) oatsToppings.element, gmFunc.function((String[]) oatsToppings.element, oats3, ((Object[]) oatsToppings.element).length, Random.INSTANCE.nextInt()));
} else {
oatsToppings.element = gmFunc.ensureNot((String[]) oatsToppings.element, gmFunc.nofunction((String[]) oatsToppings.element, "oats3", Random.INSTANCE.nextInt()));
}
...
}
You might want to try to find out what the ensure
, ensureNot
, function
and nofunction
, methods are doing. However, we intentionally obfuscated their functionality, so this might not be the easiest path towards the flag.
You may notice that an extra string is retrieved from the intent. That string is then compared to the string `oats3", determining the rest of the program. By default, intents have no 'extra' values. Hence, we need to make sure that the MainActivity is started with an extra value. In this case, both the key and the value need to be "oats3".
When you take a look at the AndroidManifest.xml
file, you can see the following lines containing intent filters that guide deep links into MainActivity
using the scheme app_scheme://flags.all
.
<activity android:exported="true" android:label="@string/app_name" android:name="com.example.oats.MainActivity" ...>
...
<intent-filter>
<data android:host="flags.all" android:scheme="app_scheme"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
You can also see from this file that the app's package name is com.example.oats
.
This information suffices to write our own small app that launches the Oats app and starts the MainActivity
with an extra string payload. Here is an example of a function you might need in this app:
private fun launchOtherAppActivity() {
val packageName = "com.example.oats" // Replace with the target app's package name
val scheme = "app_scheme"
val host = "flags.all"
val intent = Intent(Intent.ACTION_VIEW)
val uri = Uri.parse("$scheme://$host")
intent.data = uri
// Set the oats3 payload
intent.putExtra("oats3", "oats3")
// Set the flag to launch the activity in a new task
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
// Check if the app is installed before launching
val packageManager = packageManager
val isAppInstalled = packageManager.getLaunchIntentForPackage(packageName) != null
if (isAppInstalled) {
startActivity(intent)
}
}
Also don't forget to add the following lines to your AndroidManifest.xml
. You won't be able to launch the other application without this:
<queries>
<package android:name="com.example.oats" />
</queries>
This write-up also contains a full write-up apk that can be used to perform flag extraction.
When you run the exploit app, you are immediately redirected to the Oats app. However, you can now see another topping added at the bottom of the list: SUdDVEZ7TzR0c193MXRoX00xbGt9
. Enter this value into CyberChef and you can obtain the flag.
Flag
IGCTF{O4ts_w1th_M1lk}