Skip to content

Commit b9641c3

Browse files
kdrag0ngoodmeow
authored andcommitted
Spoof build fingerprint for Google Play Services
SafetyNet's CTS profile attestation checks whether Build.FINGERPRINT matches that of the device's stock OS, which has passed CTS testing. Spoof the fingerprint for Google Play Services to help pass SafetyNet. We used to set the real system build fingerprint to the stock one, but Android relies on each build having a unique fingerprint in order to clear the correct caches and update persistent state for system changes. On devices that no longer receive updates from the OEM, the build fingerprint never changes and Android doesn't account for updates correctly, which causes issues when updating without wiping data. Only spoofing the fingerprint for Google Play Services fixes this issue. Corresponding vendor commit: "Only use stock build fingerprint for Google Play Services" Change-Id: I415b6760ecf4032bd60f886c319d43bc6d63aef6 Signed-off-by: goodmeow <harunbam3@gmail.com>
1 parent 24c0306 commit b9641c3

1 file changed

Lines changed: 35 additions & 24 deletions

File tree

core/java/com/android/internal/os/Zygote.java

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -851,31 +851,43 @@ private static void boostUsapPriority() {
851851

852852
private static native void nativeBoostUsapPriority();
853853

854-
private static void maybeSetGoogleModel(String packageName, String loggingTag) {
854+
private static void setBuildField(String loggingTag, String key, String value) {
855+
/*
856+
* This would be much prettier if we just removed "final" from the Build fields,
857+
* but that requires changing the API.
858+
*
859+
* While this an awful hack, it's technically safe because the fields are
860+
* populated at runtime.
861+
*/
862+
try {
863+
// Unlock
864+
Field field = Build.class.getDeclaredField(key);
865+
field.setAccessible(true);
866+
867+
// Edit
868+
field.set(null, value);
869+
870+
// Lock
871+
field.setAccessible(false);
872+
} catch (NoSuchFieldException | IllegalAccessException e) {
873+
Log.e(loggingTag, "Failed to spoof Build." + key, e);
874+
}
875+
}
876+
877+
private static void maybeSpoofBuild(String packageName, String loggingTag) {
878+
// Set device model to defy NGA in Google Assistant
855879
if (PRODUCT_NEEDS_MODEL_EDIT &&
856880
packageName != null &&
857881
packageName.startsWith("com.google.android.googlequicksearchbox")) {
858-
/*
859-
* This would be much prettier if we just removed "final" from the MODEL field in Build,
860-
* but that requires changing the API.
861-
*
862-
* While this an awful hack, it's technically safe because the field was populated at
863-
* runtime (in pre-fork Zygote) and it's not a primitive.
864-
*/
865-
try {
866-
// Unlock
867-
Field field = Build.class.getDeclaredField("MODEL");
868-
field.setAccessible(true);
869-
870-
// Edit
871-
String newModel = "Pixel 3 XL";
872-
field.set(null, newModel);
873-
874-
// Lock
875-
field.setAccessible(false);
876-
} catch (NoSuchFieldException | IllegalAccessException e) {
877-
Log.w(loggingTag, "Failed to set fake model name for Google", e);
878-
}
882+
setBuildField(loggingTag, "MODEL", "Pixel 3 XL");
883+
}
884+
885+
// Set fingerprint to make SafetyNet pass
886+
String stockFp = SystemProperties.get("ro.build.stock_fingerprint");
887+
if (stockFp != null &&
888+
packageName != null &&
889+
packageName.startsWith("com.google.android.gms")) {
890+
setBuildField(loggingTag, "FINGERPRINT", stockFp);
879891
}
880892
}
881893

@@ -888,8 +900,7 @@ static void setAppProcessName(ZygoteArguments args, String loggingTag) {
888900
Log.w(loggingTag, "Unable to set package name.");
889901
}
890902

891-
// Modify model to defy Next-Generation Assistant in the Google app
892-
maybeSetGoogleModel(args.mPackageName, loggingTag);
903+
maybeSpoofBuild(args.mPackageName, loggingTag);
893904

894905
// Set pixel props
895906
PixelPropsUtils.setProps(args.mPackageName);

0 commit comments

Comments
 (0)