# OWASP MSTG Crackme 2 writeup (Android)

## The application

To understand more about the application, we extract the source code from the APK and look into interesting classes.&#x20;

The structure of the app is the following

```haskell
├── owasp
│   └── mstg
│       └── uncrackable2
│           └── R.java
└── sg
    └── vantagepoint
        ├── a
        │   ├── a.java
        │   └── b.java
        └── uncrackable2
            ├── CodeCheck.java
            └── MainActivity.java
```

As we can see, the structure is very similar to the previous challenge, but there is a new file `CodeCheck.java`. When we inspect the content of `MainActivity.java`  we can see how the root detection is handled (same as in the previous challenge), and how the secret is checked. The function `verify` handles the secret checks

{% code title="MainActivity.java" %}

```java
 public void verify(View view) {
        String str;
        String obj = ((EditText) findViewById(R.id.edit_text)).getText().toString();
        AlertDialog create = new AlertDialog.Builder(this).create();
        if (this.m.a(obj)) {
            create.setTitle("Success!");
            str = "This is the correct secret.";
        } else {
            create.setTitle("Nope...");
            str = "That's not it. Try again.";
        }
        create.setMessage(str);
        create.setButton(-3, "OK", new DialogInterface.OnClickListener() {
            /* class sg.vantagepoint.uncrackable2.MainActivity.AnonymousClass3 */

            public void onClick(DialogInterface dialogInterface, int i) {
                dialogInterface.dismiss();
            }
        });
        create.show();
    }
```

{% endcode %}

where `this.m.a(obj)` is the function that will check whether the secret is the right one.&#x20;

### Who is this.m?

If we look right after the `MainActivity` class definition, we see

```java
 private CodeCheck m;

    static {
        System.loadLibrary("foo");
    }
```

where the `CodeCheck` class declares a function that is implemented from the native library `foo`.

```java
private native boolean bar(byte[] bArr);
```

So, our next step is to deep dive into the native module.

### CodeCheck native function

To find the logic of the `bar` function we will:

* rename the .apk in .zip
* extract the native module `lib/libfoo.so`
* reverse it using Ghidra

## Ghidra

Analyze the `libfoo.so`

![](https://3622500909-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LpsUccoL9AvW9-dz-sO%2F-Mct6xUD5QJi5RjjSEEd%2F-Mct7e52DI6mOhPgd5R4%2Fghidra.png?alt=media\&token=5e1ce4a5-a0c2-417f-8979-b83910f8ca30)

Looking inside the binary we can identify the native function `Java_sg_vantagepoint_uncrackable2_CodeCheck_bar` that will check whether - the input string has 23 chars (`0x17`) - the string in input matches the secret using the `strncmp` function

The secret is directly passed to the `strncmp` function, so we could&#x20;

![](https://3622500909-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LpsUccoL9AvW9-dz-sO%2F-Mct6xUD5QJi5RjjSEEd%2F-Mct7hJHciCEN9fJrapF%2Fghidra-stcmp.png?alt=media\&token=3179a747-234a-4d91-a0b1-ce2b28ee046f)

Now let's get to Frida, to see how we can intercept and read the inputs passed to the `strncmp` function used in `libfoo.so`.

## Frida

Because we need to trigger the `strcmp` function, we need first to get rid of the root detection block.

#### Root detection control bypass <a href="#toc_6" id="toc_6"></a>

There are different ways of bypassing the root detection controls that will shut down the app once the OK button is clicked. A "dirty" way is to overload the `onClick` event of the OK button, to avoid that the application will call `System.exit(0)`.&#x20;

We can achieve this using the following Frida snippet

```javascript
/*

    Dirty way of bypassing the root detection, avoiding the app to close.

*/

Java.perform(function() {
   
   
    console.log("[*] Hijacking the onClick button")
    var clazz_main = Java.use('sg.vantagepoint.uncrackable2.MainActivity$1')

     clazz_main.onClick.implementation = function () {
        console.log('onCLick() is replaced ');
        
    };
    
});
```

Clicking OK will close the dialog, while the app will still run.

{% hint style="info" %}
Root detection: bypassed
{% endhint %}

### **Exploit**

The `strncmp` function has the following signature:

```cpp
int strncmp(char *__s1,char *__s2,size_t __n)
```

and is used in our `Java_sg_vantagepoint_uncrackable2_CodeCheck_bar` function in this way

```cpp
iVar1 = strncmp(__s1,(char *)&local_30,0x17);
```

where&#x20;

* `*__s1` is the text passed in input from the user
* `(char *)&local_30` is the secret we are looking for
* `0x17` is the length (23 bytes)

To extract the secret we can read the inputs of the compare function and print them out when `*__s1` matches our string **`I want your secret asap`**

The final script looks like

```javascript
function extractSecret(){

    /*
    
        To use this function, we need to pass in input an argument with 23 chars. We chose: I want your secret asap

    */

    console.log()
    console.log('[*] ACTION NEEDED: Insert the string "I want your secret asap" as input')
    console.log()
    setTimeout(function(){
        Interceptor.attach(Module.findExportByName('libfoo.so', 'strncmp'),{

            onEnter: function(args){

                if( Memory.readUtf8String(args[1]).length == 23 && Memory.readUtf8String(args[0]).includes("I want your secret asap")){
                    console.log()
                    console.log()
                    console.log("*******SECRET********")
                    console.log(Memory.readUtf8String(args[1]))
                    console.log("*******SECRET********")
                    console.log()
                    console.log()
                }

            },

            onLeave: function(retval){

            }

        });
    },2000);
}
```

Once we call the function via Frida, and insert our magic string, the secret will be printed in the console

![](https://3622500909-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LpsUccoL9AvW9-dz-sO%2F-Mct6xUD5QJi5RjjSEEd%2F-Mct8MiqfNNVxI-8iBrM%2Ffinal.png?alt=media\&token=10f7d869-f5b5-4a7f-b3c0-a1e26f7a68c3)

and when we insert the new secret in the input field we see

![](https://3622500909-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LpsUccoL9AvW9-dz-sO%2F-Mct6xUD5QJi5RjjSEEd%2F-Mct8QBhoPuMOib_cthR%2Fdone.png?alt=media\&token=2f5c0ab2-d457-43e5-a29b-b1baf9ed36a5)

The full script can be downloaded from our repo

{% embed url="<https://github.com/dcodx/owasp-mstg-crackme>" %}
