feat: add oats challenges
This commit is contained in:
parent
209ca55ada
commit
56bb16e94f
7
oats1/README.md
Normal file
7
oats1/README.md
Normal 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
14
oats1/SOLUTION.md
Normal 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
BIN
oats1/oats1.apk
Normal file
Binary file not shown.
7
oats2/README.md
Normal file
7
oats2/README.md
Normal 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
25
oats2/SOLUTION.md
Normal 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
BIN
oats2/oats2.apk
Normal file
Binary file not shown.
7
oats3/README.md
Normal file
7
oats3/README.md
Normal 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
80
oats3/SOLUTION.md
Normal 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
2
oats3/TODO.md
Normal 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
BIN
oats3/oats3.apk
Normal file
Binary file not shown.
BIN
oats3/oats3_writeup.apk
Normal file
BIN
oats3/oats3_writeup.apk
Normal file
Binary file not shown.
BIN
oats3/screenshot1.png
Normal file
BIN
oats3/screenshot1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.9 MiB |
Loading…
Reference in New Issue
Block a user