Decompiling native Kotlin binaries
Kotlin compiles to Java bytecode, which is packaged as DEX (Dalvik Executable) files inside the APK. During a security audit, we use tools like JADX or Apktool to decompile these DEX files back into readable Java and Kotlin source code.
Even when developers use ProGuard to obfuscate class and variable names, the program flow remains easy to trace. We look for:
- Local storage mechanisms, such as unsecured SQLite databases or unprotected SharedPreferences.
- Cryptographic key generation logic and hardcoded salt parameters.
- Intents and Broadcast Receivers that are exported publicly, allowing other malicious apps on the device to trigger actions.
Exported broadcast receiver leaks transaction data
During an audit of a corporate finance app built in Kotlin, we found a broadcast receiver with no permission checks. By installing a custom helper app on the same test device, we listened to the broadcast channel and intercepted all outgoing transaction hashes and customer payment IDs.
Bypassing Biometrics and KeyStore using Frida
Many Kotlin developers implement biometric login by using the BiometricPrompt API and checking the result on the client side:
// VULNERABLE: Client-side verification check
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
startMainActivity() // Hookable endpoint
}
If your code simply opens the next screen upon success, we can use a Frida script to hook the onAuthenticationSucceeded method and trigger it without requiring a fingerprint match.
To secure biometrics, you must use the biometric check to unlock a cryptographic key stored inside the Android KeyStore. The key is then sent to the backend to decrypt a session token. Without the fingerprint, the key cannot be unlocked, and the session cannot be opened.
Kotlin Android Security Checklist
To secure your native Android apps, configure these controls:
- Use EncryptedSharedPreferences: Encrypt all keys and values in local storage using AES-256 keys backed by the Android KeyStore.
- Disable Exported Components: In your
AndroidManifest.xml, setandroid:exported="false"on all activities, services, and receivers unless they explicitly require communication with other apps. - Check Root Status: Implement checks to identify if the device has been rooted or if a debugger is attached at startup.
Audit your native Android applications
At Simpa Labs, we specialize in manual penetration testing of mobile apps. We will reverse-engineer your Kotlin code, test your APIs, and audit your KeyStore configurations to protect your customers.