# HTB | Supermarket

**Machine** - <https://app.hackthebox.com/challenges/Supermarket>

**File** - Supermarket.apk

**Description** - My supermarket list is too big and I only have $50. Can you help me get the Discount code?

**Skill Learned**

* Android Reverse Engineering.
* Reading decompiled Java code.

## Enumeration

### Running the application

<figure><img src="https://2050535832-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC1JOqzbmZkOvdQTzItEo%2Fuploads%2Ftuyv4qppGorG1eBPWlug%2Fimage.png?alt=media&#x26;token=3e03b8a6-154f-435e-b405-b5303928999c" alt=""><figcaption></figcaption></figure>

### Analyzing the Source code

We have found a class `textWatcher` which have an `onTextChanged` the function which is responsible for decrypting and checking the discount code:

* `String obj = MainActivity.this.f2075q.getText().toString();` - Retrieves the text input from a UI element (likely an `EditText`).
* `stringFromJNI()` seems to return a Base64-encoded encrypted string.
* A secret key is constructed from `stringFromJNI2()` and cipher type from `stringFromJNI3()`.
* The cipher is initialized in decrypt mode (mode `2`).
* `if (!obj.equals(new String(cipher.doFinal(Base64.decode(stringFromJNI, 0)), "utf-8")))`
  * Decrypts the encrypted string and compares it to the user input.
  * If it **doesn't match**, a list is filled from `this.f2085c`, and a variable `f2076r` is set to `5.0d`.
  * If it **matches**, the list is filled from `this.f2084b`, and `f2076r` is set to `2.5d`.
* So if we get the encrypted string, we can get the discount code (maybe ?)

<figure><img src="https://2050535832-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC1JOqzbmZkOvdQTzItEo%2Fuploads%2FFf9QhRDc1NGzURc0cERp%2Fimage.png?alt=media&#x26;token=9a58e2b3-687a-4dfe-b545-019cd4f9fb79" alt=""><figcaption></figcaption></figure>

There is another onCreate which is responsible for all the calculations we see on the UI/ front end

<figure><img src="https://2050535832-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC1JOqzbmZkOvdQTzItEo%2Fuploads%2FqA3CqhVW4vRp2s5I7OTM%2Fimage.png?alt=media&#x26;token=90eaab5f-7d5e-40a4-b74c-e6f08136ae1f" alt=""><figcaption></figcaption></figure>

### Decompiling and analyzing a native library

We can see that the `libsupermarket.so` is being loaded

```jsx
    static {
        System.loadLibrary("supermarket");
    }
```

We can also see the methods `stringFromJNI()`, `stringFromJNI2()`, and `stringFromJNI3()`, which are **native method calls** defined in Java, typically using JNI (Java Native Interface), and implemented in native code — usually C or C++

```jsx
String stringFromJNI = mainActivity.stringFromJNI(); // Encrypted base64 string
SecretKeySpec secretKeySpec = new SecretKeySpec(mainActivity.stringFromJNI2().getBytes(), mainActivity.stringFromJNI3());
Cipher cipher = Cipher.getInstance(mainActivity.stringFromJNI3());
```

| Method             | Purpose                                                                                                             |
| ------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `stringFromJNI()`  | Returns a Base64-encoded string — probably encrypted data (maybe the *correct* discount code).                      |
| `stringFromJNI2()` | Returns the encryption key (used to create `SecretKeySpec`).                                                        |
| `stringFromJNI3()` | Returns the cipher algorithm string, e.g., `"AES"` or `"AES/CBC/PKCS5Padding"` — used in `Cipher.getInstance(...)`. |

Now we need to reverse the `libsupermarket.so` and find all three functions.

For this purpose, we will load the `libsupermarket.so` in the Ghidra tool

#### Analyzing the libsupermarket.so

We can see the three functions

<figure><img src="https://2050535832-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC1JOqzbmZkOvdQTzItEo%2Fuploads%2FEA1fRzTPXKfRchRf6Zwk%2Fimage.png?alt=media&#x26;token=38a66717-dbe4-48e7-90a1-1d2958cdebae" alt=""><figcaption></figcaption></figure>

**stringFromJNI()**

We can see that it is doing some logic and returning the value (probably encrypted discount code)

<figure><img src="https://2050535832-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC1JOqzbmZkOvdQTzItEo%2Fuploads%2FDuFn6WN0Hnwqx06oVZ5F%2Fimage.png?alt=media&#x26;token=fa377ca0-56de-464a-a344-48d09bf8008f" alt=""><figcaption></figcaption></figure>

**stringFromJNI2()**

Same as **stringFromJNI()** it is also doing some logic and math and returning the variable (probably encryption key)

<figure><img src="https://2050535832-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC1JOqzbmZkOvdQTzItEo%2Fuploads%2Fgvj7lISaSxIInvnnZWIQ%2Fimage.png?alt=media&#x26;token=aacf35de-15c4-4c42-a7a0-67c1358cee4b" alt=""><figcaption></figcaption></figure>

**stringFromJNI3()**

Same as **stringFromJNI()** it is also doing some logic and math and returning the variable (probably Cipher encryption algorithm)

<figure><img src="https://2050535832-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC1JOqzbmZkOvdQTzItEo%2Fuploads%2FmS51jOEGyxcsIUFwxyJo%2Fimage.png?alt=media&#x26;token=fdffce9b-b781-4d67-8679-e8726c1dbc22" alt=""><figcaption></figcaption></figure>

## Exploiting the APK

### Frida

We can use Frida to hook the functions and get what is being returned

```jsx
Java.perform(function () {
  var myActivity = Java.use("com.example.supermarket.MainActivity");

  Java.choose("com.example.supermarket.MainActivity", {
    onMatch: function (instance) {
      let JNI = instance.stringFromJNI();
      let JNI2 = instance.stringFromJNI2();
      let JNI3 = instance.stringFromJNI3();

      console.log("JNI: " + JNI);
      console.log("JNI2: " + JNI2);
      console.log("JNI3: " + JNI3);
    },
    onComplete: function () {
      console.log("Search complete.");
    },
  });
});

```

We found encrypted text(discount code ?), key and cipher algorithm

<figure><img src="https://2050535832-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC1JOqzbmZkOvdQTzItEo%2Fuploads%2F6WWHWICnAYLBafaDymdV%2Fimage.png?alt=media&#x26;token=f396e62c-21ce-44a8-b0ea-704aa990bcb9" alt=""><figcaption></figcaption></figure>

Now, to crack this, we will use online [AES decryption](https://www.devglan.com/online-tools/aes-encryption-decryption), and we got the flag

<figure><img src="https://2050535832-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FC1JOqzbmZkOvdQTzItEo%2Fuploads%2F3uHLJLQzYw0WocqPWKKm%2Fimage.png?alt=media&#x26;token=f496113b-99a3-4aa5-87cb-3f85b8dfa3e4" alt=""><figcaption></figcaption></figure>
