feat: add oats challenges

This commit is contained in:
Abel Stuker 2024-11-25 22:31:09 +01:00
parent 209ca55ada
commit 56bb16e94f
12 changed files with 142 additions and 0 deletions

7
oats1/README.md Normal file
View File

@ -0,0 +1,7 @@
# oats1
## Text
The first 'oats' challenge is the easiest one. Take a look at the APK.
## Files
[oats1.apk](oats1.apk)
## How to Deploy
n/a

14
oats1/SOLUTION.md Normal file
View File

@ -0,0 +1,14 @@
## Difficulty
Easy
## Category
Reverse Engineering
## How To Solve
When you run the app on an android device/emulator, you immediately notice that you won't find the flag in the app itself.
Instead, you need to use a tool like `apktool` to reverse engineer the APK file. Running `apktool d oats1.apk` will decode the file. Grep "IGCTF" in the obtained folder to discover the flag.
```
> grep -r "IGCTF" .
./smali_classes3/com/example/oats/MainActivityKt.smali: const-string v14, "IGCTF{Unus3d_vari4bl3}"
```
## Flag
`IGCTF{Unus3d_vari4bl3}`

BIN
oats1/oats1.apk Normal file

Binary file not shown.

7
oats2/README.md Normal file
View File

@ -0,0 +1,7 @@
# oats2
## Text
Second oats challenge.
## Files
[oats2.apk](oats2.apk)
## How to Deploy
n/a

25
oats2/SOLUTION.md Normal file
View File

@ -0,0 +1,25 @@
## Difficulty
Easy
## Category
Reverse Engineering
## How To Solve
When you run the app on an android device/emulator, you see that you are not a nice person. You will need to reverse engineer the APK to discover the flag.
This time, you can use [JADX](https://github.com/skylot/jadx) to analyze the APK. After performing `jadx oats2.apk`, you will be able to navigate to a file named `MainActivityKt.java` located somewhere under `sources/`. The following function provides you with the flag when you are nice:
```java
public static final void Greeting$showFlag(MutableState<String> mutableState, boolean isNice) {
if (isNice) {
int num2 = 42 + 58;
int num3 = (num2 * 42) + num2;
String[] array = {"zefiluhfz", "nelsqefvon", "maqzpeiuvfbqddela", "vcnbdqiyfub", "camw33pus", "woohvfdowinoo", "oiuyqecqer", "lusg9876hdfskj", "igc", "tf"};
String fContent = array[8] + array[9] + '{' + array[num3 % array.length] + array[(num3 * num2) % array.length];
String flag = fContent + '}';
mutableState.setValue(flag);
return;
}
mutableState.setValue("NOPE");
}
```
In order to obtain the flag, you can either modify and recompile entire source code, or simply copy, compile and execute only the function itself.
## Flag
`igctf{zefiluhfzzefiluhfz}`

BIN
oats2/oats2.apk Normal file

Binary file not shown.

7
oats3/README.md Normal file
View File

@ -0,0 +1,7 @@
# oats3
## Text
Third oats challenge. Find the missing topping!
## Files
[oats3.apk](oats3.apk)
## How to Deploy
n/a

80
oats3/SOLUTION.md Normal file
View File

@ -0,0 +1,80 @@
## 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](https://github.com/skylot/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.
```java
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](https://developer.android.com/reference/android/content/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`.
```xml
<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:
```java
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:
```xml
<queries>
<package android:name="com.example.oats" />
</queries>
```
This write-up also contains a full [write-up apk](oats3_writeup.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](https://gchq.github.io/CyberChef/#input=U1VkRFZFWjdUelIwYzE5M01YUm9YMDB4Ykd0OQ) and you can obtain the flag.
![](screenshot1.png)
## Flag
`IGCTF{O4ts_w1th_M1lk}`

2
oats3/TODO.md Normal file
View File

@ -0,0 +1,2 @@
# TODO
- [ ] Check whether code needs more advanced obfuscation in order to force participants to write their own 'exploit app'

BIN
oats3/oats3.apk Normal file

Binary file not shown.

BIN
oats3/oats3_writeup.apk Normal file

Binary file not shown.

BIN
oats3/screenshot1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 MiB