HackerOne H1-702 – Challenge 3

Description: We could not find the original apk, but we got this. Can you make sense of it?

HackerOne H1-702

We can see, unzipping the file, two files, base.odex and boot.oat
But, what are these files?
OAT and ODEX files are binary formats used in the Android environment to optimize application execution. Each has a specific purpose related to the performance and precompilation of applications on the system.

ODEX (Optimized Dalvik Executable)

Description

  • ODEX files are optimized versions of DEX (Dalvik Executable) files, which contain the bytecode of Android applications. The system generates these files to improve the startup time of applications by optimizing certain parts of the code.

Purpose

  • To reduce the loading time of applications.
  • Prevent the Dalvik/JVM virtual machine from having to perform runtime optimization.

Generation

  • Prior to Android 5.0 (Lollipop), the dexopt optimizer generated ODEX files during application installation.

Location

  • Usually stored in the same directory as the APK or in the system cache (/data/dalvik-cache)

OAT (Optimized Android Runtime)

Description

  • OAT files were introduced with Android 5.0 (Lollipop) as part of the transition from Dalvik to ART (Android Runtime). These files contain precompiled versions of the DEX, but are designed specifically for ART. They can include both the original bytecode and native code optimized for the device architecture.

Purpose

  • Improve runtime performance by precompiling applications with Ahead-Of-Time (AOT) Compilation.
  • Reduce resource consumption on devices with limited hardware.

Generation

  • During the system installation or upgrade process, the dex2oat compiler creates the OAT files.

Location

  • In /data/dalvik-cache/ for user applications.
  • In system partitions (/system/framework/) for system libraries and applications.

So, this is like a dex file basically.
Then, we can use backsmali tool for get dex file.

				
					baksmali deodex -o output/ base.odex
				
			

We get the smali files, so, now we can create the dex file with smali tool.

				
					smali assemble -o base.dex output/
				
			

Now we have the base.dex

Now, just use d2j-dex2jar tool for get the java code.

				
					d2j-dex2jar base.dex
				
			

I just rename the filename

				
					mv base-dex2jar.jar challenge3_h1.jar
				
			

Now, it’s time to use jadx tool.
Let’s take a look to the source code.

We can see 3 functions.

checkFlag
This function checks whether the entered string is a valid flag. Inside function, a comparison is made with a value that is generated from the encryptDecrypt function. From the encryptDecrypt function.

encryptDecrypt
This function uses a character array as a key to perform an XOR operation with a byte array. The input for this function is generated from a string that is manipulated (reverse and replace characters).

hexStringToByteArray
Converts a hexadecimal string into a byte array, which is then used in the encryption function.

We can create a java code (MainActivity.java) that do the work for us

				
					public class MainActivity {
    private static char[] key = {'t', 'h', 'i', 's', '_', 'i', 's', '_', 'a', '_', 'k', '3', 'y'};

    public static String calculateFlag() {
        // Reversed and transformed hex string from the original code
        String reversedString = new StringBuilder("kO13t41Oc1b2z4F5F1b2BO33c2d1c61OzOdOtO")
                .reverse().toString()
                .replace("O", "0")
                .replace("t", "7")
                .replace("B", "8")
                .replace("z", "a")
                .replace("F", "f")
                .replace("k", "e");

        // Convert hex string to byte array
        byte[] decrypted = hexStringToByteArray(reversedString);

        // Decrypt using the provided key
        String decryptedString = encryptDecrypt(key, decrypted);

        // Build the flag in the format "flag{decryptedString}"
        return "flag{" + decryptedString + "}";
    }

    private static String encryptDecrypt(char[] cArr, byte[] bArr) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bArr.length; i++) {
            sb.append((char) (bArr[i] ^ cArr[i % cArr.length]));
        }
        return sb.toString();
    }

    public static byte[] hexStringToByteArray(String str) {
        int length = str.length();
        byte[] bArr = new byte[length / 2];
        for (int i = 0; i < length; i += 2) {
            bArr[i / 2] = (byte) ((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16));
        }
        return bArr;
    }

    public static void main(String[] args) {
        // Calculate the flag
        String flag = calculateFlag();

        // Print the flag
        System.out.println("The flag is: " + flag);
    }
}
				
			

Just compile it with

				
					javac MainActivity.java
				
			

And run

				
					java MainActivity
				
			

Output:

				
					The flag is: flag{secr3t_littl3_th4ng}
				
			

Flag: flag{secr3t_littl3_th4ng}

I hope you found it useful (:

Leave a Reply

Your email address will not be published. Required fields are marked *