You've already forked PlayIntegrityFork
mirror of
https://github.com/osm0sis/PlayIntegrityFork.git
synced 2025-09-06 06:37:06 +00:00
Add spoofVendingSdk to force legacy verdicts from new PI
Squashed: Add spoofVendingSdk for forcing new PI legacy verdicts Squashed: Move vending SDK spoof to EntryPointVending, replace killgms.sh with killpi.sh
This commit is contained in:
committed by
Chris Renshaw
parent
e2b8a3c4b0
commit
4740d2048d
@@ -56,13 +56,13 @@ A migration may also be performed manually with `sh migrate.sh` and custom.pif.j
|
||||
|
||||
You can customize the included default [example.app_replace.list](https://raw.githubusercontent.com/osm0sis/PlayIntegrityFork/main/module/example.app_replace.list) from the module directory (/data/adb/modules/playintegrityfix) then rename it to custom.app_replace.list to systemlessly replace any additional conflicting custom ROM spoof injection app paths to disable them.
|
||||
|
||||
## About 'autopif2.sh' and 'killgms.sh' script files
|
||||
## About 'autopif2.sh' and 'killpi.sh' script files
|
||||
|
||||
There's intentionally no pif.json in the module because the goal remains to be futureproof, and including something that may be banned and obsolete within days would be contrary to that goal. If you don't care to have your own private fingerprint to use or don't have time to look for one currently then simply run the generation script from a root manager app that supports the module Action button, a root prompt with `sh autopif2.sh` in the module directory (/data/adb/modules/playintegrityfix), or from a file explorer app that supports script execution.
|
||||
|
||||
The autopif2 script generates a random device fingerprint from the latest Pixel Beta, ideally only to test an initial setup, since they expire roughly every 6 weeks from the Pixel Beta release date (dates included in the generated fingerprint), and the public mass-used ones from other modules or ROMs may also get banned or may be banned for RCS use while otherwise passing Play Integrity and SafetyNet in that time.
|
||||
|
||||
The killgms script forces the Google Play Services DroidGuard process (com.google.android.gms.unstable) to end, making it restart with the next attestation attempt; useful for testing out different fingerprints without requiring a reboot in between.
|
||||
The killpi script forces the Google Play Services DroidGuard (com.google.android.gms.unstable) and Play Store (com.android.vending) processes to end, making them restart with the next attestation attempt; useful for testing out different fingerprints without requiring a reboot in between.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
1
app/proguard-rules.pro
vendored
1
app/proguard-rules.pro
vendored
@@ -1,4 +1,5 @@
|
||||
-keep class es.chiteroman.playintegrityfix.EntryPoint {public <methods>;}
|
||||
-keep class es.chiteroman.playintegrityfix.EntryPointVending {public <methods>;}
|
||||
-keep class es.chiteroman.playintegrityfix.CustomProvider
|
||||
-keep class es.chiteroman.playintegrityfix.CustomKeyStoreSpi
|
||||
-keep class es.chiteroman.playintegrityfix.CustomPackageInfoCreator
|
||||
|
||||
@@ -12,12 +12,14 @@
|
||||
|
||||
#define JSON_FILE_PATH "/data/adb/modules/playintegrityfix/pif.json"
|
||||
#define CUSTOM_JSON_FILE_PATH "/data/adb/modules/playintegrityfix/custom.pif.json"
|
||||
#define VENDING_PACKAGE "com.android.vending"
|
||||
|
||||
static int verboseLogs = 0;
|
||||
static int spoofBuild = 1;
|
||||
static int spoofProps = 1;
|
||||
static int spoofProvider = 1;
|
||||
static int spoofSignature = 0;
|
||||
static int spoofVendingSdk = 0;
|
||||
|
||||
static std::map<std::string, std::string> jsonProps;
|
||||
|
||||
@@ -95,11 +97,11 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
std::string_view process(rawProcess);
|
||||
pkgName = rawProcess;
|
||||
std::string_view dir(rawDir);
|
||||
|
||||
isGms = dir.ends_with("/com.google.android.gms");
|
||||
isGmsUnstable = process == "com.google.android.gms.unstable";
|
||||
isGms = dir.ends_with("/com.google.android.gms") || dir.ends_with("/com.android.vending");
|
||||
isGmsUnstable = pkgName == "com.google.android.gms.unstable" || pkgName == VENDING_PACKAGE;
|
||||
|
||||
env->ReleaseStringUTFChars(args->nice_name, rawProcess);
|
||||
env->ReleaseStringUTFChars(args->app_data_dir, rawDir);
|
||||
@@ -161,6 +163,10 @@ public:
|
||||
if (dexVector.empty() || json.empty()) return;
|
||||
|
||||
readJson();
|
||||
|
||||
if (pkgName == VENDING_PACKAGE) spoofProps = spoofBuild = spoofProvider = 0;
|
||||
else spoofVendingSdk = 0;
|
||||
|
||||
if (spoofProps > 0) doHook();
|
||||
inject();
|
||||
|
||||
@@ -177,6 +183,7 @@ private:
|
||||
JNIEnv *env = nullptr;
|
||||
std::vector<char> dexVector;
|
||||
nlohmann::json json;
|
||||
std::string pkgName;
|
||||
|
||||
void readJson() {
|
||||
LOGD("JSON contains %d keys!", static_cast<int>(json.size()));
|
||||
@@ -193,6 +200,19 @@ private:
|
||||
}
|
||||
|
||||
// Advanced spoofing settings
|
||||
if (json.contains("spoofVendingSdk")) {
|
||||
if (!json["spoofVendingSdk"].is_null() && json["spoofVendingSdk"].is_string() && json["spoofVendingSdk"] != "") {
|
||||
spoofVendingSdk = stoi(json["spoofVendingSdk"].get<std::string>());
|
||||
if (verboseLogs > 0) LOGD("Spoofing SDK Level in Play Store %s!", (spoofVendingSdk > 0) ? "enabled" : "disabled");
|
||||
} else {
|
||||
LOGD("Error parsing spoofVendingSdk!");
|
||||
}
|
||||
json.erase("spoofVendingSdk");
|
||||
}
|
||||
if (pkgName == VENDING_PACKAGE) {
|
||||
json.clear();
|
||||
return;
|
||||
}
|
||||
if (json.contains("spoofBuild")) {
|
||||
if (!json["spoofBuild"].is_null() && json["spoofBuild"].is_string() && json["spoofBuild"] != "") {
|
||||
spoofBuild = stoi(json["spoofBuild"].get<std::string>());
|
||||
@@ -255,32 +275,39 @@ private:
|
||||
}
|
||||
|
||||
void inject() {
|
||||
LOGD("JNI: Getting system classloader");
|
||||
LOGD("JNI %s: Getting system classloader", pkgName.c_str());
|
||||
auto clClass = env->FindClass("java/lang/ClassLoader");
|
||||
auto getSystemClassLoader = env->GetStaticMethodID(clClass, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
|
||||
auto systemClassLoader = env->CallStaticObjectMethod(clClass, getSystemClassLoader);
|
||||
|
||||
LOGD("JNI: Creating module classloader");
|
||||
LOGD("JNI %s: Creating module classloader", pkgName.c_str());
|
||||
auto dexClClass = env->FindClass("dalvik/system/InMemoryDexClassLoader");
|
||||
auto dexClInit = env->GetMethodID(dexClClass, "<init>", "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
||||
auto buffer = env->NewDirectByteBuffer(dexVector.data(), static_cast<jlong>(dexVector.size()));
|
||||
auto dexCl = env->NewObject(dexClClass, dexClInit, buffer, systemClassLoader);
|
||||
|
||||
LOGD("JNI: Loading module class");
|
||||
LOGD("JNI %s: Loading module class", pkgName.c_str());
|
||||
auto loadClass = env->GetMethodID(clClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
auto entryClassName = env->NewStringUTF("es.chiteroman.playintegrityfix.EntryPoint");
|
||||
const char* className = pkgName == VENDING_PACKAGE ? "es.chiteroman.playintegrityfix.EntryPointVending" : "es.chiteroman.playintegrityfix.EntryPoint";
|
||||
auto entryClassName = env->NewStringUTF(className);
|
||||
auto entryClassObj = env->CallObjectMethod(dexCl, loadClass, entryClassName);
|
||||
|
||||
auto entryClass = (jclass) entryClassObj;
|
||||
|
||||
LOGD("JNI: Sending JSON");
|
||||
auto receiveJson = env->GetStaticMethodID(entryClass, "receiveJson", "(Ljava/lang/String;)V");
|
||||
auto javaStr = env->NewStringUTF(json.dump().c_str());
|
||||
env->CallStaticVoidMethod(entryClass, receiveJson, javaStr);
|
||||
if (pkgName == VENDING_PACKAGE) {
|
||||
LOGD("JNI %s: Calling EntryPointVending.init", pkgName.c_str());
|
||||
auto entryInit = env->GetStaticMethodID(entryClass, "init", "(II)V");
|
||||
env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofVendingSdk);
|
||||
} else {
|
||||
LOGD("JNI %s: Sending JSON", pkgName.c_str());
|
||||
auto receiveJson = env->GetStaticMethodID(entryClass, "receiveJson", "(Ljava/lang/String;)V");
|
||||
auto javaStr = env->NewStringUTF(json.dump().c_str());
|
||||
env->CallStaticVoidMethod(entryClass, receiveJson, javaStr);
|
||||
|
||||
LOGD("JNI: Calling init");
|
||||
auto entryInit = env->GetStaticMethodID(entryClass, "init", "(IIII)V");
|
||||
env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofBuild, spoofProvider, spoofSignature);
|
||||
LOGD("JNI %s: Calling EntryPoint.init", pkgName.c_str());
|
||||
auto entryInit = env->GetStaticMethodID(entryClass, "init", "(IIII)V");
|
||||
env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofBuild, spoofProvider, spoofSignature);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -265,6 +265,6 @@ public final class EntryPoint {
|
||||
}
|
||||
|
||||
static void LOG(String msg) {
|
||||
Log.d("PIF/Java", msg);
|
||||
Log.d("PIF/Java:DG", msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package es.chiteroman.playintegrityfix;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Build;
|
||||
import java.lang.reflect.Field;
|
||||
import android.util.Log;
|
||||
|
||||
public final class EntryPointVending {
|
||||
|
||||
private static void LOG(String msg) {
|
||||
Log.d("PIF/Java:vending", msg);
|
||||
}
|
||||
|
||||
@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));
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,7 +158,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 verboseLogs";
|
||||
ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingSdk verboseLogs";
|
||||
for SETTING in $ADVSETTINGS; do
|
||||
eval [ -z \"\$$SETTING\" ] \&\& $SETTING=$(grep_json "$SETTING" $OLDJSON);
|
||||
eval TMPVAL=\$$SETTING;
|
||||
@@ -182,8 +182,8 @@ if [ "$DIR" = /data/adb/modules/playintegrityfix/autopif2 ]; then
|
||||
fi;
|
||||
item "Installing new json ...";
|
||||
cp -fv $NEWNAME ..;
|
||||
if [ -f /data/adb/modules/playintegrityfix/killgms.sh ]; then
|
||||
item "Killing any running GMS DroidGuard process ...";
|
||||
sh /data/adb/modules/playintegrityfix/killgms.sh 2>&1 || true;
|
||||
if [ -f /data/adb/modules/playintegrityfix/killpi.sh ]; then
|
||||
item "Killing any running GMS DroidGuard/Play Store processes ...";
|
||||
sh /data/adb/modules/playintegrityfix/killpi.sh 2>&1 || true;
|
||||
fi;
|
||||
fi;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/system/bin/sh
|
||||
# killgms.sh by osm0sis @ xda-developers
|
||||
#
|
||||
# Kill the Google Play services DroidGuard process
|
||||
# (com.google.android.gms.unstable)
|
||||
|
||||
if [ "$USER" != "root" -a "$(whoami 2>/dev/null)" != "root" ]; then
|
||||
echo "killgms: need root permissions";
|
||||
exit 1;
|
||||
fi;
|
||||
|
||||
killall -v com.google.android.gms.unstable;
|
||||
13
module/killpi.sh
Normal file
13
module/killpi.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/system/bin/sh
|
||||
# killpi.sh by osm0sis @ xda-developers
|
||||
#
|
||||
# Kill the Google Play services DroidGuard and Play Store processes
|
||||
# (com.google.android.gms.unstable and com.android.vending)
|
||||
|
||||
if [ "$USER" != "root" -a "$(whoami 2>/dev/null)" != "root" ]; then
|
||||
echo "killpi: need root permissions";
|
||||
exit 1;
|
||||
fi;
|
||||
|
||||
killall -v com.google.android.gms.unstable;
|
||||
killall -v com.android.vending;
|
||||
@@ -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 verboseLogs";
|
||||
ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingSdk verboseLogs";
|
||||
|
||||
spoofBuild=1;
|
||||
spoofProps=1;
|
||||
spoofProvider=1;
|
||||
spoofSignature=0;
|
||||
spoofVendingSdk=0;
|
||||
verboseLogs=0;
|
||||
|
||||
if [ -f "$OUT" ]; then
|
||||
|
||||
Reference in New Issue
Block a user