This content originally appeared on HackerNoon and was authored by Atul
Let’s dive into analyzing the OWASP Uncrackable Level 1
app!
\ This can be solved in two ways,
- Using Frida (not required here!)
- Using normal code analysis and writing your own code from that.
\ I’ll show you both ways. So, let’s buckle up for both ways to solve this challenge.
\
:::info Using Frida
:::
Root Detection
Upon opening the app, it closes due to root detection, as shown below:
\
To understand why, we can decompile the APK using jadx. In the AndroidManifest.xml
, the Launcher activity is defined as owasp.mstg.uncrackable1
.
\
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="owasp.mstg.uncrackable1">
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="28"/>
<application
android:theme="@style/AppTheme"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:allowBackup="true">
<activity
android:label="@string/app_name"
android:name="sg.vantagepoint.uncrackable1.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
\
In MainActivity
, we find the code responsible for detecting the root and closing the app using System.exit(0);
.
\
\
private void a(String str) {
AlertDialog create = new AlertDialog.Builder(this).create();
create.setTitle(str);
create.setMessage("This is unacceptable. The app is now going to exit.");
create.setButton(-3, "OK", new DialogInterface.OnClickListener() { // from class: sg.vantagepoint.uncrackable1.MainActivity.1
@Override // android.content.DialogInterface.OnClickListener
public void onClick(DialogInterface dialogInterface, int i) {
System.exit(0);
}
});
create.setCancelable(false);
create.show();
}
@Override // android.app.Activity
protected void onCreate(Bundle bundle) {
if (c.a() || c.b() || c.c()) {
a("Root detected!");
}
if (b.a(getApplicationContext())) {
a("App is debuggable!");
}
super.onCreate(bundle);
setContentView(R.layout.activity_main);
}
\
Bypassing Root Detection
Let’s write a frida
script to hook and bypass this check.
\
Java.perform(function() {
var hook = Java.use("java.lang.System");
hook.exit.implementation = function() {
console.log("Root Check Bypassed!!! 😎");
};
});
\
App Functionality
Once bypassed, the app presents a text field and a verify button. Clickingverify
shows a message: That's not it. Try again.
\ By searching for this string in the code, we find the verification logic:
\
\ Let’s take this as a reference to move ahead and find this string in the code. After searching this out, you can see a code like below which seems like a comparison between input value and some hard-coded value.
\
\
Analyzing the Verification Logic
We need to inspect the a
method to understand the comparison.
\
\
public class a {
public static boolean a(String str) {
byte[] bArr;
byte[] bArr2 = new byte[0];
try {
bArr = sg.vantagepoint.a.a.a(b("8d127684cbc37c17616d806cf50473cc"), Base64.decode("5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=", 0));
} catch (Exception e) {
Log.d("CodeCheck", "AES error:" + e.getMessage());
bArr = bArr2;
}
return str.equals(new String(bArr));
}
public static byte[] b(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;
}
}
\
The bArr
value is what our input is being compared to. The sg.vantagepoint.a.a.a
method is an AES decryption method.
\
\
public class a {
public static byte[] a(byte[] bArr, byte[] bArr2) {
SecretKeySpec secretKeySpec = new SecretKeySpec(bArr, "AES/ECB/PKCS7Padding");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(2, secretKeySpec);
return cipher.doFinal(bArr2);
}
}
\
Hooking the AES Cipher Function
We can hook this function to get the string value
var a = Java.use('sg.vantagepoint.a.a');
a.a.implementation = function (p0, p1) {
console.log('p0 (byte array): ' + bytesToString(p0));
console.log('p1 (byte array): ' + bytesToString(p1));
var result = this.a(p0, p1);
console.log("Result ->", bytesToString(result))
return result;
};
function bytesToString(bytes) {
var result = '';
for (var i = 0; i < bytes.length; ++i) {
result += String.fromCharCode(bytes[i]);
}
return result;
}
\
Running the Script
Execute the script to see the byte array as a string.
\
(base) C:\Users\booyaa\uncrackable\level> frida -U -l ./hook_level1.js -f owasp.mstg.uncrackable1
____
/ _ | Frida 16.2.3 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://frida.re/docs/home/
. . . .
. . . . Connected to LE2001 (id=4a298ca9)
Spawned `owasp.mstg.uncrackable1`. Resuming main thread!
[LE2101::owasp.mstg.uncrackable1 ]-> Hooked exit()
Root Check Bypassed!!! 😎
p0 (byte array): �vトᅨᅢ|amタl￵sᅩ
p1 (byte array): ï¿¥Bbï¿‹[ï¾šï¿ƒï¾ ï¾µï¿¦ï¾¤ï¾½vレI│￰t￸.￿ユᆱ|vï¿§
Result -> I want to believe
Process terminated
[LE2101::owasp.mstg.uncrackable1 ]->
Thank you for using Frida!
(base) C:\Users\booyaa\uncrackable\level>
\
\
And there we have it; the final string: I want to believe
.
\
:::info Using just Python and no rooted device or Frida.
:::
\
# level1.py
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
def a(key, cipher_text):
cipher = AES.new(key, AES.MODE_ECB)
return unpad(cipher.decrypt(cipher_text), AES.block_size)
def b(hex_string):
return bytes.fromhex(hex_string)
try:
key = b("8d127684cbc37c17616d806cf50473cc")
cipher_text = base64.b64decode("5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=")
returned_bytes = a(key, cipher_text)
print("Solved: ", returned_bytes.decode())
except Exception as e:
print("AES error: ", str(e))
\ Thanks for following along! Cheers �
This content originally appeared on HackerNoon and was authored by Atul

Atul | Sciencx (2024-10-08T01:22:38+00:00) Uncrackable – Level 1 | OWASP. Retrieved from https://www.scien.cx/2024/10/08/uncrackable-level-1-owasp/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.