From 40791425de2903ffc2c0f1bffb004ee9234770de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=8E?= Date: Sun, 16 Apr 2023 00:07:12 +0800 Subject: [PATCH] Patch denylist processes --- .../safetynetfix/proxy/ProxyKeyStoreSpi.kt | 22 +++++++++++++++---- zygisk/module/jni/module.cpp | 12 +++++----- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/java/app/src/main/java/dev/kdrag0n/safetynetfix/proxy/ProxyKeyStoreSpi.kt b/java/app/src/main/java/dev/kdrag0n/safetynetfix/proxy/ProxyKeyStoreSpi.kt index 9005f669..e663fa66 100644 --- a/java/app/src/main/java/dev/kdrag0n/safetynetfix/proxy/ProxyKeyStoreSpi.kt +++ b/java/app/src/main/java/dev/kdrag0n/safetynetfix/proxy/ProxyKeyStoreSpi.kt @@ -21,7 +21,10 @@ class ProxyKeyStoreSpi private constructor( // Avoid breaking other, legitimate uses of key attestation in Google Play Services, e.g. // - com.google.android.gms.auth.cryptauth.register.ReEnrollmentChimeraService // - tk_trace.129-RegisterForKeyPairOperation - private fun isCallerSafetyNet() = Thread.currentThread().stackTrace.any { + private fun isCallerDeniedOrSafetyNet(): Boolean { + var isGMS = false + + // SafetyNet stack trace example: // a.a.engineGetCertificateChain(Unknown Source:15) // java.security.KeyStore.getCertificateChain(KeyStore.java:1087) // com.google.ccc.abuse.droidguard.DroidGuard.initNative(Native Method) @@ -33,14 +36,25 @@ class ProxyKeyStoreSpi private constructor( // dzx.onTransact(:com.google.android.gms@212621053@21.26.21 (190400-387928701):8) // android.os.Binder.execTransactInternal(Binder.java:1179) // android.os.Binder.execTransact(Binder.java:1143) - logDebug("Stack trace element: $it") - it.className.contains("DroidGuard", ignoreCase = true) + for (it in Thread.currentThread().stackTrace) { + logDebug("Stack trace element: $it") + + if (it.className.contains("DroidGuard", ignoreCase = true)) { + return true + } + + if (!isGMS && it.className.contains("com.google.android.gms", ignoreCase = true)) { + isGMS = true + } + } + + return !isGMS } override fun engineGetCertificateChain(alias: String?): Array? { logDebug("Proxy key store: get certificate chain") - if (isCallerSafetyNet()) { + if (isCallerDeniedOrSafetyNet()) { logDebug("Blocking call") throw UnsupportedOperationException() } else { diff --git a/zygisk/module/jni/module.cpp b/zygisk/module/jni/module.cpp index 1c65acf8..93e171cc 100644 --- a/zygisk/module/jni/module.cpp +++ b/zygisk/module/jni/module.cpp @@ -84,20 +84,22 @@ class SafetyNetFixModule : public zygisk::ModuleBase { } void preSpecialize(const std::string& process) { - // Only touch GMS - if (process.rfind("com.google.android.gms", 0) != 0) { - api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY); + api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY); + + // Only touch denied and GMS + auto deny = (api->getFlags() & zygisk::PROCESS_ON_DENYLIST) != 0; + if (!deny && process.rfind("com.google.android.gms", 0) != 0) { return; } - // Force DenyList unmounting for all GMS processes + // Force DenyList unmounting for all touching processes api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT); // The unstable process is where SafetyNet attestation actually runs, so we only need to // spoof the model in that process. Leaving other processes alone fixes various issues // caused by model detection and flag provisioning, such as broken weather with the new // smartspace on Android 12. - if (process == "com.google.android.gms.unstable") { + if (deny || process == "com.google.android.gms.unstable") { // Load the payload, but don't inject it yet until after specialization // Otherwise, specialization fails if any code from the payload still happens to be // running