Rename to spoofVendingFinger, add custom FINGERPRINT support, tidy

0 = disabled
1 = enabled and use FINGERPRINT from json for vending (Play Store)
<string> = enabled and use <string> as FINGERPRINT for vending (Play Store)
This commit is contained in:
osm0sis
2025-08-30 22:06:52 -03:00
parent 9c6f065bb6
commit ed8501d857
5 changed files with 43 additions and 31 deletions

View File

@@ -12,6 +12,7 @@
#define JSON_FILE_PATH "/data/adb/modules/playintegrityfix/pif.json" #define JSON_FILE_PATH "/data/adb/modules/playintegrityfix/pif.json"
#define CUSTOM_JSON_FILE_PATH "/data/adb/modules/playintegrityfix/custom.pif.json" #define CUSTOM_JSON_FILE_PATH "/data/adb/modules/playintegrityfix/custom.pif.json"
#define VENDING_PACKAGE "com.android.vending" #define VENDING_PACKAGE "com.android.vending"
#define DROIDGUARD_PACKAGE "com.google.android.gms.unstable" #define DROIDGUARD_PACKAGE "com.google.android.gms.unstable"
@@ -20,7 +21,7 @@ static int spoofBuild = 1;
static int spoofProps = 1; static int spoofProps = 1;
static int spoofProvider = 1; static int spoofProvider = 1;
static int spoofSignature = 0; static int spoofSignature = 0;
static int spoofVendingFingerprint = 0; static int spoofVendingFinger = 0;
static int spoofVendingSdk = 0; static int spoofVendingSdk = 0;
static std::map<std::string, std::string> jsonProps; static std::map<std::string, std::string> jsonProps;
@@ -166,11 +167,11 @@ public:
readJson(); readJson();
if (pkgName == VENDING_PACKAGE) spoofProps = spoofBuild = spoofProvider = spoofSignature = 0; if (pkgName == VENDING_PACKAGE) spoofBuild = spoofProps = spoofProvider = spoofSignature = 0;
else spoofVendingFingerprint = spoofVendingSdk = 0; else spoofVendingFinger = spoofVendingSdk = 0;
if (spoofProps > 0) doHook(); if (spoofProps > 0) doHook();
if (spoofBuild + spoofProvider + spoofSignature + spoofVendingFingerprint + spoofVendingSdk > 0) inject(); if (spoofBuild + spoofProvider + spoofSignature + spoofVendingFinger + spoofVendingSdk > 0) inject();
dexVector.clear(); dexVector.clear();
json.clear(); json.clear();
@@ -186,7 +187,7 @@ private:
std::vector<char> dexVector; std::vector<char> dexVector;
nlohmann::json json; nlohmann::json json;
std::string pkgName; std::string pkgName;
std::string spoofFingerprintValue = ""; std::string vendingFingerprintValue;
void readJson() { void readJson() {
LOGD("JSON contains %d keys!", static_cast<int>(json.size())); LOGD("JSON contains %d keys!", static_cast<int>(json.size()));
@@ -202,7 +203,7 @@ private:
json.erase("verboseLogs"); json.erase("verboseLogs");
} }
// Advanced spoofing settings // Vending advanced spoofing settings
if (json.contains("spoofVendingSdk")) { if (json.contains("spoofVendingSdk")) {
if (!json["spoofVendingSdk"].is_null() && json["spoofVendingSdk"].is_string() && json["spoofVendingSdk"] != "") { if (!json["spoofVendingSdk"].is_null() && json["spoofVendingSdk"].is_string() && json["spoofVendingSdk"] != "") {
spoofVendingSdk = stoi(json["spoofVendingSdk"].get<std::string>()); spoofVendingSdk = stoi(json["spoofVendingSdk"].get<std::string>());
@@ -212,21 +213,29 @@ private:
} }
json.erase("spoofVendingSdk"); json.erase("spoofVendingSdk");
} }
if (json.contains("spoofVendingFingerprint")) { if (json.contains("spoofVendingFinger")) {
if (!json["spoofVendingFingerprint"].is_null() && json["spoofVendingFingerprint"].is_string() && json["spoofVendingFingerprint"] != "" && if (!json["spoofVendingFinger"].is_null() && json["spoofVendingFinger"].is_string() && json["spoofVendingFinger"] != "") {
json.contains("FINGERPRINT") && !json["FINGERPRINT"].is_null() && json["FINGERPRINT"].is_string() && json["FINGERPRINT"] != "") { if (json["spoofVendingFinger"].get<std::string>().find_first_not_of("01") != std::string::npos) {
spoofVendingFingerprint = stoi(json["spoofVendingFingerprint"].get<std::string>()); spoofVendingFinger = 1;
spoofFingerprintValue = json["FINGERPRINT"].get<std::string>(); vendingFingerprintValue = json["spoofVendingFinger"].get<std::string>();
if (verboseLogs > 0) LOGD("Spoofing Fingerprint in Play Store %s!", (spoofVendingFingerprint > 0) ? "enabled" : "disabled"); } else if (json.contains("FINGERPRINT") && !json["FINGERPRINT"].is_null() && json["FINGERPRINT"].is_string() && json["FINGERPRINT"] != "") {
spoofVendingFinger = stoi(json["spoofVendingFinger"].get<std::string>());
vendingFingerprintValue = json["FINGERPRINT"].get<std::string>();
} else { } else {
LOGD("Error parsing spoofVendingFingerprint or FINGERPRINT field!"); LOGD("Error parsing spoofVendingFinger or FINGERPRINT field!");
} }
json.erase("spoofVendingFingerprint"); if (verboseLogs > 0) LOGD("Spoofing Fingerprint in Play Store %s!", (spoofVendingFinger > 0) ? "enabled" : "disabled");
} else {
LOGD("Error parsing spoofVendingFinger!");
}
json.erase("spoofVendingFinger");
} }
if (pkgName == VENDING_PACKAGE) { if (pkgName == VENDING_PACKAGE) {
json.clear(); json.clear();
return; return;
} }
// DroidGuard advanced spoofing settings
if (json.contains("spoofBuild")) { if (json.contains("spoofBuild")) {
if (!json["spoofBuild"].is_null() && json["spoofBuild"].is_string() && json["spoofBuild"] != "") { if (!json["spoofBuild"].is_null() && json["spoofBuild"].is_string() && json["spoofBuild"] != "") {
spoofBuild = stoi(json["spoofBuild"].get<std::string>()); spoofBuild = stoi(json["spoofBuild"].get<std::string>());
@@ -313,8 +322,9 @@ private:
if (pkgName == VENDING_PACKAGE) { if (pkgName == VENDING_PACKAGE) {
LOGD("JNI %s: Calling EntryPointVending.init", niceName); LOGD("JNI %s: Calling EntryPointVending.init", niceName);
auto entryInit = env->GetStaticMethodID(entryClass, "init", "(IIILjava/lang/String;)V"); auto entryInit = env->GetStaticMethodID(entryClass, "init", "(IIILjava/lang/String;)V");
auto javaStr = env->NewStringUTF(spoofFingerprintValue.c_str()); auto javaStr = env->NewStringUTF(vendingFingerprintValue.c_str());
env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofVendingFingerprint, spoofVendingSdk, javaStr); env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofVendingFinger, spoofVendingSdk, javaStr);
env->DeleteLocalRef(javaStr);
} else { } else {
LOGD("JNI %s: Sending JSON", niceName); LOGD("JNI %s: Sending JSON", niceName);
auto receiveJson = env->GetStaticMethodID(entryClass, "receiveJson", "(Ljava/lang/String;)V"); auto receiveJson = env->GetStaticMethodID(entryClass, "receiveJson", "(Ljava/lang/String;)V");
@@ -327,10 +337,10 @@ private:
env->DeleteLocalRef(javaStr); env->DeleteLocalRef(javaStr);
} }
env->DeleteLocalRef(clClass); env->DeleteLocalRef(clClass);
env->DeleteLocalRef(dexClClass);
env->DeleteLocalRef(systemClassLoader); env->DeleteLocalRef(systemClassLoader);
env->DeleteLocalRef(dexCl); env->DeleteLocalRef(dexClClass);
env->DeleteLocalRef(buffer); env->DeleteLocalRef(buffer);
env->DeleteLocalRef(dexCl);
env->DeleteLocalRef(entryClassName); env->DeleteLocalRef(entryClassName);
env->DeleteLocalRef(entryClassObj); env->DeleteLocalRef(entryClassObj);
} }
@@ -379,8 +389,10 @@ static void companion(int fd) {
} }
/* /*
* - The fix is public now: https://github.com/JingMatrix/NeoZygisk/commit/76d54228c7e6fe14cca93338865008946b94f7ee * Fix for Dobby detections
* - Remeber to add this for all other zygisk c++ library * Must be added to all Zygisk C++ libraries in a project
*
* Reference: https://github.com/JingMatrix/NeoZygisk/commit/76d54228c7e6fe14cca93338865008946b94f7ee
*/ */
extern "C" int __cxa_atexit(void (*func)(void*), void* arg, void* dso) { extern "C" int __cxa_atexit(void (*func)(void*), void* arg, void* dso) {
return 0; return 0;

View File

@@ -12,23 +12,23 @@ public final class EntryPointVending {
} }
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
public static void init(int verboseLogs, int spoofVendingFingerprint, int spoofVendingSdk, String spoofFingerprintValue) { public static void init(int verboseLogs, int spoofVendingFinger, int spoofVendingSdk, String vendingFingerprintValue) {
if (spoofVendingSdk < 1){ // Only spoof FINGERPRINT to Play Store if not forcing Android <13 Play Integrity verdict
// Only spoof FINGERPRINT to Play Store if not forcing legacy verdict if (spoofVendingSdk < 1) {
if (spoofVendingFingerprint < 1) return; if (spoofVendingFinger < 1) return;
String oldValue; String oldValue;
try { try {
Field field = Build.class.getDeclaredField("FINGERPRINT"); Field field = Build.class.getDeclaredField("FINGERPRINT");
field.setAccessible(true); field.setAccessible(true);
oldValue = String.valueOf(field.get(null)); oldValue = String.valueOf(field.get(null));
if (oldValue.equals(spoofFingerprintValue)) { if (oldValue.equals(vendingFingerprintValue)) {
if (verboseLogs > 2) LOG(String.format("[FINGERPRINT]: %s (unchanged)", oldValue)); if (verboseLogs > 2) LOG(String.format("[FINGERPRINT]: %s (unchanged)", oldValue));
field.setAccessible(false); field.setAccessible(false);
return; return;
} }
field.set(null, spoofFingerprintValue); field.set(null, vendingFingerprintValue);
field.setAccessible(false); field.setAccessible(false);
LOG(String.format("[FINGERPRINT]: %s -> %s", oldValue, spoofFingerprintValue)); LOG(String.format("[FINGERPRINT]: %s -> %s", oldValue, vendingFingerprintValue));
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
LOG("FINGERPRINT field not found: " + e); LOG("FINGERPRINT field not found: " + e);
} catch (SecurityException | IllegalAccessException | IllegalArgumentException | } catch (SecurityException | IllegalAccessException | IllegalArgumentException |

View File

@@ -162,7 +162,7 @@ if [ -f "$MIGRATE" ]; then
if [ -n "$ARGS" ]; then if [ -n "$ARGS" ]; then
grep_json() { [ -f "$2" ] && grep -m1 "$1" $2 | cut -d\" -f4; } grep_json() { [ -f "$2" ] && grep -m1 "$1" $2 | cut -d\" -f4; }
verboseLogs=$(grep_json "VERBOSE_LOGS" $OLDJSON); verboseLogs=$(grep_json "VERBOSE_LOGS" $OLDJSON);
ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingFingerprint spoofVendingSdk verboseLogs"; ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingFinger spoofVendingSdk verboseLogs";
for SETTING in $ADVSETTINGS; do for SETTING in $ADVSETTINGS; do
eval [ -z \"\$$SETTING\" ] \&\& $SETTING=$(grep_json "$SETTING" $OLDJSON); eval [ -z \"\$$SETTING\" ] \&\& $SETTING=$(grep_json "$SETTING" $OLDJSON);
eval TMPVAL=\$$SETTING; eval TMPVAL=\$$SETTING;

View File

@@ -31,7 +31,7 @@
"spoofProps": "1", "spoofProps": "1",
"spoofProvider": "1", "spoofProvider": "1",
"spoofSignature": "0", "spoofSignature": "0",
"spoofVendingFingerprint": "0", "spoofVendingFinger": "0",
"spoofVendingSdk": "0", "spoofVendingSdk": "0",
"verboseLogs": "0" "verboseLogs": "0"
} }

View File

@@ -114,13 +114,13 @@ if [ -z "$DEVICE_INITIAL_SDK_INT" -o "$DEVICE_INITIAL_SDK_INT" = "null" ]; then
DEVICE_INITIAL_SDK_INT=25; DEVICE_INITIAL_SDK_INT=25;
fi; fi;
ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingFingerprint spoofVendingSdk verboseLogs"; ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingFinger spoofVendingSdk verboseLogs";
spoofBuild=1; spoofBuild=1;
spoofProps=1; spoofProps=1;
spoofProvider=1; spoofProvider=1;
spoofSignature=0; spoofSignature=0;
spoofVendingFingerprint=0; spoofVendingFinger=0;
spoofVendingSdk=0; spoofVendingSdk=0;
verboseLogs=0; verboseLogs=0;