diff --git a/app/src/main/cpp/main.cpp b/app/src/main/cpp/main.cpp index e6f8435..54b3fad 100644 --- a/app/src/main/cpp/main.cpp +++ b/app/src/main/cpp/main.cpp @@ -20,6 +20,7 @@ static int spoofBuild = 1; static int spoofProps = 1; static int spoofProvider = 1; static int spoofSignature = 0; +static int spoofVendingFingerprint = 0; static int spoofVendingSdk = 0; static std::map jsonProps; @@ -166,10 +167,10 @@ public: readJson(); if (pkgName == VENDING_PACKAGE) spoofProps = spoofBuild = spoofProvider = spoofSignature = 0; - else spoofVendingSdk = 0; + else spoofVendingFingerprint = spoofVendingSdk = 0; if (spoofProps > 0) doHook(); - if (spoofBuild + spoofProvider + spoofSignature + spoofVendingSdk > 0) inject(); + if (spoofBuild + spoofProvider + spoofSignature + spoofVendingFingerprint + spoofVendingSdk > 0) inject(); dexVector.clear(); json.clear(); @@ -185,6 +186,7 @@ private: std::vector dexVector; nlohmann::json json; std::string pkgName; + std::string spoofFingerprintValue = ""; void readJson() { LOGD("JSON contains %d keys!", static_cast(json.size())); @@ -210,6 +212,17 @@ private: } json.erase("spoofVendingSdk"); } + if (json.contains("spoofVendingFingerprint")) { + if (!json["spoofVendingFingerprint"].is_null() && json["spoofVendingFingerprint"].is_string() && json["spoofVendingFingerprint"] != "" && + json.contains("FINGERPRINT") && !json["FINGERPRINT"].is_null() && json["FINGERPRINT"].is_string() && json["FINGERPRINT"] != "") { + spoofVendingFingerprint = stoi(json["spoofVendingFingerprint"].get()); + spoofFingerprintValue = json["FINGERPRINT"].get(); + if (verboseLogs > 0) LOGD("Spoofing Fingerprint in Play Store %s!", (spoofVendingFingerprint > 0) ? "enabled" : "disabled"); + } else { + LOGD("Error parsing spoofVendingFingerprint or FINGERPRINT field!"); + } + json.erase("spoofVendingFingerprint"); + } if (pkgName == VENDING_PACKAGE) { json.clear(); return; @@ -299,8 +312,9 @@ private: if (pkgName == VENDING_PACKAGE) { LOGD("JNI %s: Calling EntryPointVending.init", niceName); - auto entryInit = env->GetStaticMethodID(entryClass, "init", "(II)V"); - env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofVendingSdk); + auto entryInit = env->GetStaticMethodID(entryClass, "init", "(IIILjava/lang/String;)V"); + auto javaStr = env->NewStringUTF(spoofFingerprintValue.c_str()); + env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofVendingFingerprint, spoofVendingSdk, javaStr); } else { LOGD("JNI %s: Sending JSON", niceName); auto receiveJson = env->GetStaticMethodID(entryClass, "receiveJson", "(Ljava/lang/String;)V"); diff --git a/app/src/main/java/es/chiteroman/playintegrityfix/EntryPointVending.java b/app/src/main/java/es/chiteroman/playintegrityfix/EntryPointVending.java index ec38bea..02271ba 100644 --- a/app/src/main/java/es/chiteroman/playintegrityfix/EntryPointVending.java +++ b/app/src/main/java/es/chiteroman/playintegrityfix/EntryPointVending.java @@ -12,29 +12,51 @@ public final class EntryPointVending { } @SuppressLint("DefaultLocale") - public static void init(int verboseLogs, int spoofVendingSdk) { - if (spoofVendingSdk < 1) return; - int requestSdk = spoofVendingSdk == 1 ? 32 : spoofVendingSdk; - int targetSdk = Math.min(Build.VERSION.SDK_INT, requestSdk); - int oldValue; - try { - Field field = Build.VERSION.class.getDeclaredField("SDK_INT"); - field.setAccessible(true); - oldValue = field.getInt(null); - if (oldValue == targetSdk) { - if (verboseLogs > 2) LOG(String.format("[SDK_INT]: %d (unchanged)", oldValue)); + public static void init(int verboseLogs, int spoofVendingFingerprint, int spoofVendingSdk, String spoofFingerprintValue) { + if (spoofVendingSdk < 1){ + // Only spoof FINGERPRINT to Play Store if not forcing legacy verdict + if (spoofVendingFingerprint < 1) return; + String oldValue; + try { + Field field = Build.class.getDeclaredField("FINGERPRINT"); + field.setAccessible(true); + oldValue = String.valueOf(field.get(null)); + if (oldValue.equals(spoofFingerprintValue)) { + if (verboseLogs > 2) LOG(String.format("[FINGERPRINT]: %s (unchanged)", oldValue)); + field.setAccessible(false); + return; + } + field.set(null, spoofFingerprintValue); field.setAccessible(false); - return; + LOG(String.format("[FINGERPRINT]: %s -> %s", oldValue, spoofFingerprintValue)); + } catch (NoSuchFieldException e) { + LOG("FINGERPRINT field not found: " + e); + } catch (SecurityException | IllegalAccessException | IllegalArgumentException | + NullPointerException | ExceptionInInitializerError e) { + LOG("FINGERPRINT field not accessible: " + e); + } + } else { + int requestSdk = spoofVendingSdk == 1 ? 32 : spoofVendingSdk; + int targetSdk = Math.min(Build.VERSION.SDK_INT, requestSdk); + int oldValue; + try { + Field field = Build.VERSION.class.getDeclaredField("SDK_INT"); + field.setAccessible(true); + oldValue = field.getInt(null); + if (oldValue == targetSdk) { + if (verboseLogs > 2) LOG(String.format("[SDK_INT]: %d (unchanged)", oldValue)); + field.setAccessible(false); + return; + } + field.set(null, targetSdk); + field.setAccessible(false); + LOG(String.format("[SDK_INT]: %d -> %d", oldValue, targetSdk)); + } catch (NoSuchFieldException e) { + LOG("SDK_INT field not found: " + e); + } catch (SecurityException | IllegalAccessException | IllegalArgumentException | + NullPointerException | ExceptionInInitializerError e) { + LOG("SDK_INT field not accessible: " + e); } - field.set(null, targetSdk); - field.setAccessible(false); - LOG(String.format("[SDK_INT]: %d -> %d", oldValue, targetSdk)); - } catch (NoSuchFieldException e) { - LOG("SDK_INT field not found: " + e); - } catch (SecurityException | IllegalAccessException | IllegalArgumentException | - NullPointerException | ExceptionInInitializerError e) { - LOG("SDK_INT field not accessible: " + e); - } } } diff --git a/module/autopif2.sh b/module/autopif2.sh index da9b760..7a187b2 100644 --- a/module/autopif2.sh +++ b/module/autopif2.sh @@ -162,7 +162,7 @@ if [ -f "$MIGRATE" ]; then if [ -n "$ARGS" ]; then grep_json() { [ -f "$2" ] && grep -m1 "$1" $2 | cut -d\" -f4; } verboseLogs=$(grep_json "VERBOSE_LOGS" $OLDJSON); - ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingSdk verboseLogs"; + ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingFingerprint spoofVendingSdk verboseLogs"; for SETTING in $ADVSETTINGS; do eval [ -z \"\$$SETTING\" ] \&\& $SETTING=$(grep_json "$SETTING" $OLDJSON); eval TMPVAL=\$$SETTING; diff --git a/module/example.pif.json b/module/example.pif.json index 7036f41..a1ed701 100644 --- a/module/example.pif.json +++ b/module/example.pif.json @@ -31,6 +31,7 @@ "spoofProps": "1", "spoofProvider": "1", "spoofSignature": "0", + "spoofVendingFingerprint": "0", "spoofVendingSdk": "0", "verboseLogs": "0" } diff --git a/module/migrate.sh b/module/migrate.sh index 39c6c32..aad351a 100644 --- a/module/migrate.sh +++ b/module/migrate.sh @@ -114,12 +114,13 @@ if [ -z "$DEVICE_INITIAL_SDK_INT" -o "$DEVICE_INITIAL_SDK_INT" = "null" ]; then DEVICE_INITIAL_SDK_INT=25; fi; -ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingSdk verboseLogs"; +ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingFingerprint spoofVendingSdk verboseLogs"; spoofBuild=1; spoofProps=1; spoofProvider=1; spoofSignature=0; +spoofVendingFingerprint=0; spoofVendingSdk=0; verboseLogs=0;