最近在帮朋友解决一些任务时,有些比较复杂的任务需要批量使用模拟器,但是模拟器存在一个缺点,就是缺少很多物理功能,比如说陀螺仪、温度传感器和生物识别模块等等,但是有些任务是需要这些功能的。没有办法,只能自己去想办法解决这些先天缺陷。
由于模拟器本身不存在指纹,因此我们在询问android
系统时,对应的系统方法是这个:
package android.hardware.biometrics;
public class BiometricManager {
@Deprecated
@RequiresPermission(USE_BIOMETRIC)
@BiometricError
public int canAuthenticate() {
@BiometricError final int result = canAuthenticate(mContext.getUserId(),
Authenticators.BIOMETRIC_WEAK);
FrameworkStatsLog.write(FrameworkStatsLog.AUTH_MANAGER_CAN_AUTHENTICATE_INVOKED,
false /* isAllowedAuthenticatorsSet */, Authenticators.EMPTY_SET, result);
FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED,
AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_BIOMETRIC_MANAGER_CAN_AUTHENTICATE,
mContext.getApplicationInfo().uid,
mContext.getApplicationInfo().targetSdkVersion);
return result;
}
}
如果能 hook 这个方法,返回 success
标志,替代系统告诉使用者,我假装可以进行生物识别(生物识别包含指纹识别和人脸识别),解决完这个问题之后,我们再次需要进入生物验证方法:
@RequiresPermission(USE_BIOMETRIC)
public void authenticate(@NonNull CryptoObject crypto,
@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@NonNull AuthenticationCallback callback) {
FrameworkStatsLog.write(FrameworkStatsLog.AUTH_PROMPT_AUTHENTICATE_INVOKED,
true /* isCrypto */,
mPromptInfo.isConfirmationRequested(),
mPromptInfo.isDeviceCredentialAllowed(),
mPromptInfo.getAuthenticators() != Authenticators.EMPTY_SET,
mPromptInfo.getAuthenticators());
// Disallow explicitly setting any non-Strong biometric authenticator types.
@Authenticators.Types int authenticators = mPromptInfo.getAuthenticators();
if (authenticators == Authenticators.EMPTY_SET) {
authenticators = Authenticators.BIOMETRIC_STRONG;
}
final int biometricStrength = authenticators & Authenticators.BIOMETRIC_WEAK;
if ((biometricStrength & ~Authenticators.BIOMETRIC_STRONG) != 0) {
throw new IllegalArgumentException("Only Strong biometrics supported with crypto");
}
authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId());
}
这个authenticate
方法中存在四个参数,其实我们只需要关注AuthenticationCallback
这个抽象类,可以查看一下这个抽象类:
public abstract static class AuthenticationCallback extends
BiometricAuthenticator.AuthenticationCallback {
// 验证失败时执行
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {}
// 验证成功时执行
public void onAuthenticationSucceeded(AuthenticationResult result) {}
}
那么只需要 hook 这个方法,直接使得AuthenticationCallback
调用onAuthenticationSucceeded
方法即可。
找到了系统需要 hook 的点,那么就可以请出我们的终极武器frida
框架了,这里不说明frida
框架的入门了,大家可以找找其他参考教程。
我们直接启动frida-server
,然后通过frida
注入js hook 代码,覆盖掉系统的返回,即可得到我们的答案。比如可以看到结论图:
当然,这只是我的思路,如果有更好的想法和方案,我们可以共同交流,wx:javainstalling, 暗号:指纹。