From 73c8587a808533c38e47f40c4485579068397205 Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sun, 1 Jan 2023 04:53:41 -0800 Subject: [PATCH] Dynamically patch build fingerprint in GMS process "AndroidCAStore" always seems to be used early in the attestation process, before the fingerprint is checked. Dynamic patching avoids problems with device detection and functionality that can be caused by permanently spoofing another device. Closes #207, closes #224, closes #222, closes #220, closes #218, closes #212, closes #211, closes #210, closes #204, closes #203, closes #201, closes #196, closes #188, closes #171, closes #170 --- .../safetynetfix/proxy/ProxyProvider.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/java/app/src/main/java/dev/kdrag0n/safetynetfix/proxy/ProxyProvider.kt b/java/app/src/main/java/dev/kdrag0n/safetynetfix/proxy/ProxyProvider.kt index 3b797a8..3ffe951 100644 --- a/java/app/src/main/java/dev/kdrag0n/safetynetfix/proxy/ProxyProvider.kt +++ b/java/app/src/main/java/dev/kdrag0n/safetynetfix/proxy/ProxyProvider.kt @@ -1,8 +1,12 @@ package dev.kdrag0n.safetynetfix.proxy +import android.os.Build import dev.kdrag0n.safetynetfix.SecurityHooks import dev.kdrag0n.safetynetfix.logDebug import java.security.Provider +import kotlin.concurrent.thread + +private const val PATCH_DURATION = 2000L // This is mostly just a pass-through provider that exists to change the provider's ClassLoader. // This works because Service looks up the class by name from the *provider* ClassLoader, not @@ -19,6 +23,25 @@ class ProxyProvider( override fun getService(type: String?, algorithm: String?): Service? { logDebug("Provider: get service - type=$type algorithm=$algorithm") + if (algorithm == "AndroidCAStore") { + val orig = Build.FINGERPRINT + val patched = "google/angler/angler:6.0/MDB08L/2343525:user/release-keys" + logDebug("patch build for castore $orig -> $patched") + // Append a space to the device model name + Build::class.java.getDeclaredField("FINGERPRINT").let { field -> + field.isAccessible = true + field.set(null, patched) + } + + thread(isDaemon = true) { + Thread.sleep(PATCH_DURATION) + logDebug("unpatch") + Build::class.java.getDeclaredField("FINGERPRINT").let { field -> + field.isAccessible = true + field.set(null, orig) + } + } + } return super.getService(type, algorithm) }