This sample checks if the device has a secure lock screen via KeyguardManager.isDeviceSecure and if the device supports strong biometric authentication using BiometricManager.canAuthenticate.
packageorg.owasp.mastestappimportandroid.app.KeyguardManagerimportandroid.content.Contextimportandroid.hardware.biometrics.BiometricManagerimportandroid.os.BuildclassMastgTest(privatevalcontext:Context){funmastgTest():String{valisLocked=isDeviceSecure(context)valbiometricStatus=checkStrongBiometricStatus()return"Device has a passcode: $isLocked\n\n"+"Biometric status: $biometricStatus"}/***Checksifthedevicehasasecurelockscreen(e.g.,PIN,pattern,password).**@return`true`ifthedevicehasasecurelockscreen,`false`otherwise.*/funisDeviceSecure(context:Context):Boolean{valkeyguardManager=context.getSystemService(Context.KEYGUARD_SERVICE)asKeyguardManagerreturnkeyguardManager.isDeviceSecure}/***Checksifthedevicesupportsstrongbiometricauthentication(e.g.,fingerprint,face,iris)*andiftheuserhasenrolledbiometriccredentials.****Note:**ThisAPIisavailableonAPIlevel30(AndroidR)andabove.**@returnAhuman-readablestringdescribingthebiometricstatus.*/funcheckStrongBiometricStatus():String{if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.R){valbiometricManager=context.getSystemService(BiometricManager::class.java)valresult=biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)returnwhen(result){BiometricManager.BIOMETRIC_SUCCESS->"BIOMETRIC_SUCCESS - Strong biometric authentication is available."BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE->"BIOMETRIC_ERROR_NO_HARDWARE - No biometric hardware available."BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE->"BIOMETRIC_ERROR_HW_UNAVAILABLE - Biometric hardware is currently unavailable."BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED->"BIOMETRIC_ERROR_NONE_ENROLLED - No biometrics enrolled."else->"Unknown biometric status: $result"}}else{return"Strong biometric authentication check is not supported on this API level."}}}
Java.perform(()=>{// Function to print backtrace with a configurable number of lines (default: 5)functionprintBacktrace(maxLines=8){letException=Java.use("java.lang.Exception");letstackTrace=Exception.$new().getStackTrace().toString().split(",");console.log("\nBacktrace:");for(leti=0;i<Math.min(maxLines,stackTrace.length);i++){console.log(stackTrace[i]);}}// Hook KeyguardManager.isDeviceSecure()letKeyguardManager=Java.use("android.app.KeyguardManager");KeyguardManager["isDeviceSecure"].overload().implementation=function(){console.log(`\n[*] KeyguardManager.isDeviceSecure() called\n`);// Java stack traceprintBacktrace();letresult=this["isDeviceSecure"]();console.log(`Result: ${result}`);returnresult;};// Hook BiometricManager.canAuthenticate()letBiometricManager=Java.use("android.hardware.biometrics.BiometricManager");BiometricManager["canAuthenticate"].overload("int").implementation=function(authenticators){letresult=this["canAuthenticate"](authenticators);letstatusMessage;// Mapping the authentication result to a readable messageswitch(result){caseBiometricManager.BIOMETRIC_SUCCESS.value:statusMessage="BIOMETRIC_SUCCESS - Strong biometric authentication is available.";break;caseBiometricManager.BIOMETRIC_ERROR_NO_HARDWARE.value:statusMessage="BIOMETRIC_ERROR_NO_HARDWARE - No biometric hardware available.";break;caseBiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE.value:statusMessage="BIOMETRIC_ERROR_HW_UNAVAILABLE - Biometric hardware is currently unavailable.";break;caseBiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED.value:statusMessage="BIOMETRIC_ERROR_NONE_ENROLLED - No biometrics enrolled.";break;default:statusMessage=`Unknown biometric status: ${result}`;break;}console.log(`\n[*] BiometricManager.canAuthenticate(${authenticators}) called with ${statusMessage}\n`);// Java stack traceprintBacktrace();returnresult;};});
The test passes because the output shows the use of KeyguardManager.isDeviceSecure and BiometricManager.canAuthenticate at runtime. We can see that:
KeyguardManager.isDeviceSecure is called from the file MastgTest.kt, class MastgTest, method isDeviceSecure at line 24.
BiometricManager.canAuthenticate is called from the file MastgTest.kt, class MastgTest, method checkStrongBiometricStatus at line 38.
Note that in this case the output contains file names and even line numbers, but in real-world scenarios, this information may not be available or not be that useful (e.g. when using a production build or when the app is obfuscated). The output is still valuable because it shows that the APIs are being used at runtime.