mirror of
https://github.com/chiteroman/PlayIntegrityFix.git
synced 2025-01-19 03:22:39 +02:00
v14.6
This commit is contained in:
parent
4b6acccdda
commit
7ab29dd525
@ -12,13 +12,11 @@ static std::string SECURITY_PATCH, FIRST_API_LEVEL, VNDK_VERSION, BUILD_ID;
|
|||||||
|
|
||||||
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
|
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
|
||||||
|
|
||||||
static std::map<void *, T_Callback> callbacks;
|
static volatile T_Callback o_callback = nullptr;
|
||||||
|
|
||||||
static void modify_callback(void *cookie, const char *name, const char *value, uint32_t serial) {
|
static void modify_callback(void *cookie, const char *name, const char *value, uint32_t serial) {
|
||||||
|
|
||||||
if (cookie == nullptr || name == nullptr || value == nullptr ||
|
if (cookie == nullptr || name == nullptr || value == nullptr || o_callback == nullptr) return;
|
||||||
!callbacks.contains(cookie))
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::string_view prop(name);
|
std::string_view prop(name);
|
||||||
|
|
||||||
@ -26,25 +24,23 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
|
|||||||
if (!SECURITY_PATCH.empty()) {
|
if (!SECURITY_PATCH.empty()) {
|
||||||
value = SECURITY_PATCH.c_str();
|
value = SECURITY_PATCH.c_str();
|
||||||
}
|
}
|
||||||
LOGD("[%s]: %s", name, value);
|
|
||||||
} else if (prop.ends_with("api_level")) {
|
} else if (prop.ends_with("api_level")) {
|
||||||
if (!FIRST_API_LEVEL.empty()) {
|
if (!FIRST_API_LEVEL.empty()) {
|
||||||
value = FIRST_API_LEVEL.c_str();
|
value = FIRST_API_LEVEL.c_str();
|
||||||
}
|
}
|
||||||
LOGD("[%s]: %s", name, value);
|
|
||||||
} else if (prop.ends_with("vndk.version")) {
|
} else if (prop.ends_with("vndk.version")) {
|
||||||
if (!VNDK_VERSION.empty()) {
|
if (!VNDK_VERSION.empty()) {
|
||||||
value = VNDK_VERSION.c_str();
|
value = VNDK_VERSION.c_str();
|
||||||
}
|
}
|
||||||
LOGD("[%s]: %s", name, value);
|
|
||||||
} else if (prop == "ro.build.id") {
|
} else if (prop == "ro.build.id") {
|
||||||
if (!BUILD_ID.empty()) {
|
if (!BUILD_ID.empty()) {
|
||||||
value = BUILD_ID.c_str();
|
value = BUILD_ID.c_str();
|
||||||
}
|
}
|
||||||
LOGD("[%s]: %s", name, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return callbacks[cookie](cookie, name, value, serial);
|
if (!prop.starts_with("cache") && !prop.starts_with("debug")) LOGD("[%s]: %s", name, value);
|
||||||
|
|
||||||
|
return o_callback(cookie, name, value, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void (*o_system_property_read_callback)(const prop_info *, T_Callback, void *);
|
static void (*o_system_property_read_callback)(const prop_info *, T_Callback, void *);
|
||||||
@ -54,7 +50,7 @@ my_system_property_read_callback(const prop_info *pi, T_Callback callback, void
|
|||||||
if (pi == nullptr || callback == nullptr || cookie == nullptr) {
|
if (pi == nullptr || callback == nullptr || cookie == nullptr) {
|
||||||
return o_system_property_read_callback(pi, callback, cookie);
|
return o_system_property_read_callback(pi, callback, cookie);
|
||||||
}
|
}
|
||||||
callbacks[cookie] = callback;
|
o_callback = callback;
|
||||||
return o_system_property_read_callback(pi, modify_callback, cookie);
|
return o_system_property_read_callback(pi, modify_callback, cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,37 +77,41 @@ public:
|
|||||||
|
|
||||||
void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
|
void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
|
||||||
|
|
||||||
auto rawProcess = env->GetStringUTFChars(args->nice_name, nullptr);
|
auto name = env->GetStringUTFChars(args->nice_name, nullptr);
|
||||||
std::string process(rawProcess);
|
|
||||||
env->ReleaseStringUTFChars(args->nice_name, rawProcess);
|
|
||||||
|
|
||||||
if (process.starts_with("com.google.android.gms")) {
|
if (name && strncmp(name, "com.google.android.gms", 22) == 0) {
|
||||||
|
|
||||||
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
|
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
|
||||||
|
|
||||||
if (process == "com.google.android.gms.unstable") {
|
if (strcmp(name, "com.google.android.gms.unstable") == 0) {
|
||||||
|
|
||||||
int fd = api->connectCompanion();
|
int fd = api->connectCompanion();
|
||||||
|
|
||||||
read(fd, &dexSize, sizeof(dexSize));
|
read(fd, &dexSize, sizeof(dexSize));
|
||||||
read(fd, &jsonSize, sizeof(jsonSize));
|
read(fd, &jsonSize, sizeof(jsonSize));
|
||||||
|
|
||||||
|
if (dexSize < 1 || jsonSize < 1) {
|
||||||
|
|
||||||
|
LOGD("Couldn't read files in memory!");
|
||||||
|
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
auto vectorSize = dexSize + jsonSize;
|
auto vectorSize = dexSize + jsonSize;
|
||||||
|
|
||||||
if (vectorSize > 0) {
|
if (vectorSize > 0) {
|
||||||
vector.resize(vectorSize);
|
vector.resize(vectorSize);
|
||||||
read(fd, vector.data(), vectorSize);
|
read(fd, vector.data(), vectorSize);
|
||||||
} else {
|
}
|
||||||
LOGD("Couldn't read classes.dex");
|
|
||||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
} else api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
|
|
||||||
|
} else api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
|
|
||||||
|
env->ReleaseStringUTFChars(args->nice_name, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
||||||
@ -148,7 +148,6 @@ private:
|
|||||||
if (json.contains("SECURITY_PATCH")) {
|
if (json.contains("SECURITY_PATCH")) {
|
||||||
if (json["SECURITY_PATCH"].is_null() || json["SECURITY_PATCH"].empty()) {
|
if (json["SECURITY_PATCH"].is_null() || json["SECURITY_PATCH"].empty()) {
|
||||||
LOGD("SECURITY_PATCH is null or empty");
|
LOGD("SECURITY_PATCH is null or empty");
|
||||||
json.erase("SECURITY_PATCH");
|
|
||||||
} else {
|
} else {
|
||||||
SECURITY_PATCH = json["SECURITY_PATCH"].get<std::string>();
|
SECURITY_PATCH = json["SECURITY_PATCH"].get<std::string>();
|
||||||
}
|
}
|
||||||
@ -230,10 +229,7 @@ static void companion(int fd) {
|
|||||||
|
|
||||||
FILE *json = fopen("/data/adb/pif.json", "rb");
|
FILE *json = fopen("/data/adb/pif.json", "rb");
|
||||||
|
|
||||||
if (json == nullptr) {
|
if (json == nullptr) json = fopen("/data/adb/modules/playintegrityfix/pif.json", "rb");
|
||||||
|
|
||||||
json = fopen("/data/adb/modules/playintegrityfix/pif.json", "rb");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
fseek(json, 0, SEEK_END);
|
fseek(json, 0, SEEK_END);
|
||||||
|
@ -0,0 +1,105 @@
|
|||||||
|
package es.chiteroman.playintegrityfix;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.security.Key;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.KeyStoreSpi;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.UnrecoverableKeyException;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
public class CustomKeyStoreSpi extends KeyStoreSpi {
|
||||||
|
protected static volatile KeyStoreSpi keyStoreSpi;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException {
|
||||||
|
return keyStoreSpi.engineGetKey(alias, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Certificate[] engineGetCertificateChain(String alias) {
|
||||||
|
|
||||||
|
if (EntryPoint.isDroidGuard()) {
|
||||||
|
|
||||||
|
EntryPoint.LOG("DroidGuard call certificate chain! Throwing exception.");
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyStoreSpi.engineGetCertificateChain(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Certificate engineGetCertificate(String alias) {
|
||||||
|
return keyStoreSpi.engineGetCertificate(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date engineGetCreationDate(String alias) {
|
||||||
|
return keyStoreSpi.engineGetCreationDate(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException {
|
||||||
|
keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException {
|
||||||
|
keyStoreSpi.engineSetKeyEntry(alias, key, chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException {
|
||||||
|
keyStoreSpi.engineSetCertificateEntry(alias, cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void engineDeleteEntry(String alias) throws KeyStoreException {
|
||||||
|
keyStoreSpi.engineDeleteEntry(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Enumeration<String> engineAliases() {
|
||||||
|
return keyStoreSpi.engineAliases();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean engineContainsAlias(String alias) {
|
||||||
|
return keyStoreSpi.engineContainsAlias(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int engineSize() {
|
||||||
|
return keyStoreSpi.engineSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean engineIsKeyEntry(String alias) {
|
||||||
|
return keyStoreSpi.engineIsKeyEntry(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean engineIsCertificateEntry(String alias) {
|
||||||
|
return keyStoreSpi.engineIsCertificateEntry(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String engineGetCertificateAlias(Certificate cert) {
|
||||||
|
return keyStoreSpi.engineGetCertificateAlias(cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void engineStore(OutputStream stream, char[] password) throws CertificateException, IOException, NoSuchAlgorithmException {
|
||||||
|
keyStoreSpi.engineStore(stream, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void engineLoad(InputStream stream, char[] password) throws CertificateException, IOException, NoSuchAlgorithmException {
|
||||||
|
keyStoreSpi.engineLoad(stream, password);
|
||||||
|
}
|
||||||
|
}
|
@ -1,30 +1,25 @@
|
|||||||
package es.chiteroman.playintegrityfix;
|
package es.chiteroman.playintegrityfix;
|
||||||
|
|
||||||
import java.security.Provider;
|
import java.security.Provider;
|
||||||
import java.security.ProviderException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
public final class CustomProvider extends Provider {
|
public class CustomProvider extends Provider {
|
||||||
|
|
||||||
public CustomProvider(Provider provider) {
|
protected CustomProvider(Provider provider) {
|
||||||
super(provider.getName(), provider.getVersion(), provider.getInfo());
|
super(provider.getName(), provider.getVersion(), provider.getInfo());
|
||||||
|
|
||||||
putAll(provider);
|
putAll(provider);
|
||||||
|
|
||||||
|
remove("KeyStore.AndroidKeyStore");
|
||||||
|
|
||||||
|
put("KeyStore.AndroidKeyStore", CustomKeyStoreSpi.class.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Service getService(String type, String algorithm) {
|
public synchronized Service getService(String type, String algorithm) {
|
||||||
|
EntryPoint.LOG("[SERVICE] Type: " + type + " | Algorithm: " + algorithm);
|
||||||
|
|
||||||
EntryPoint.spoofDevice();
|
EntryPoint.spoofDevice();
|
||||||
|
|
||||||
if ("KeyPairGenerator".equals(type)) {
|
|
||||||
|
|
||||||
if (Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch(e -> e.getClassName().toLowerCase(Locale.US).contains("droidguard"))) {
|
|
||||||
|
|
||||||
throw new ProviderException();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.getService(type, algorithm);
|
return super.getService(type, algorithm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,18 @@ import android.os.Build;
|
|||||||
import android.util.JsonReader;
|
import android.util.JsonReader;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.security.KeyStoreSpi;
|
||||||
import java.security.Provider;
|
import java.security.Provider;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public final class EntryPoint {
|
public class EntryPoint {
|
||||||
private static final Map<String, String> map = new HashMap<>();
|
private static final Map<String, String> map = new HashMap<>();
|
||||||
|
|
||||||
public static void init(String data) {
|
public static void init(String data) {
|
||||||
@ -22,32 +24,41 @@ public final class EntryPoint {
|
|||||||
while (reader.hasNext()) {
|
while (reader.hasNext()) {
|
||||||
String key = reader.nextName();
|
String key = reader.nextName();
|
||||||
String value = reader.nextString();
|
String value = reader.nextString();
|
||||||
|
|
||||||
if (key == null || key.isEmpty() || key.isBlank() || value == null || value.isEmpty() || value.isBlank())
|
|
||||||
throw new JSONException("Empty key or value");
|
|
||||||
|
|
||||||
map.put(key, value);
|
map.put(key, value);
|
||||||
}
|
}
|
||||||
reader.endObject();
|
reader.endObject();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG("Couldn't parse JSON from Zygisk lib: " + e);
|
LOG("Couldn't parse JSON from Zygisk lib: " + e);
|
||||||
LOG("Remove /data/adb/pif.json");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG("Map info (keys and values):");
|
||||||
|
map.forEach((s, s2) -> LOG(String.format("[%s] -> %s", s, s2)));
|
||||||
|
|
||||||
spoofDevice();
|
spoofDevice();
|
||||||
spoofProvider();
|
spoofProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LOG(String msg) {
|
protected static void LOG(String msg) {
|
||||||
Log.d("PIF/Java", msg);
|
Log.d("PIF/Java", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spoofDevice() {
|
protected static void spoofDevice() {
|
||||||
map.forEach(EntryPoint::setFieldValue);
|
map.forEach(EntryPoint::setFieldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static boolean isDroidGuard() {
|
||||||
|
return Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch(e -> e.getClassName().toLowerCase(Locale.ENGLISH).contains("droidguard"));
|
||||||
|
}
|
||||||
|
|
||||||
private static void spoofProvider() {
|
private static void spoofProvider() {
|
||||||
try {
|
try {
|
||||||
|
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||||
|
|
||||||
|
Field field = keyStore.getClass().getDeclaredField("keyStoreSpi");
|
||||||
|
|
||||||
|
field.setAccessible(true);
|
||||||
|
CustomKeyStoreSpi.keyStoreSpi = (KeyStoreSpi) field.get(keyStore);
|
||||||
|
|
||||||
Provider provider = Security.getProvider("AndroidKeyStore");
|
Provider provider = Security.getProvider("AndroidKeyStore");
|
||||||
|
|
||||||
Provider customProvider = new CustomProvider(provider);
|
Provider customProvider = new CustomProvider(provider);
|
||||||
@ -79,12 +90,11 @@ public final class EntryPoint {
|
|||||||
String oldValue = null;
|
String oldValue = null;
|
||||||
try {
|
try {
|
||||||
oldValue = (String) field.get(null);
|
oldValue = (String) field.get(null);
|
||||||
|
if (value.equals(oldValue)) return;
|
||||||
field.set(null, value);
|
field.set(null, value);
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
LOG("Couldn't get or set field: " + e);
|
LOG("Couldn't get or set field: " + e);
|
||||||
}
|
}
|
||||||
field.setAccessible(false);
|
LOG(String.format("Field '%s' with value '%s' is now set to '%s'", name, oldValue, value));
|
||||||
if (value.equals(oldValue)) return;
|
|
||||||
LOG(String.format("[%s]: %s -> %s", name, oldValue, value));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,6 @@ We have a Telegram channel!
|
|||||||
If you want to share your knowledge join:
|
If you want to share your knowledge join:
|
||||||
https://t.me/playintegrityfix
|
https://t.me/playintegrityfix
|
||||||
|
|
||||||
# v14.5
|
# v14.6
|
||||||
|
|
||||||
Fix Google update
|
Updated fingerprint
|
@ -6,12 +6,13 @@ fi
|
|||||||
# safetynet-fix module is obsolete and it's incompatible with PIF.
|
# safetynet-fix module is obsolete and it's incompatible with PIF.
|
||||||
if [ -d /data/adb/modules/safetynet-fix ]; then
|
if [ -d /data/adb/modules/safetynet-fix ]; then
|
||||||
rm -rf /data/adb/modules/safetynet-fix
|
rm -rf /data/adb/modules/safetynet-fix
|
||||||
ui_print "- ! safetynet-fix module will be removed. Do NOT install it again along PIF."
|
rm -f /data/adb/SNFix.dex
|
||||||
|
ui_print "! safetynet-fix module will be removed. Do NOT install it again along PIF."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# MagiskHidePropsConf module is obsolete in Android 8+ but it shouldn't give issues.
|
# MagiskHidePropsConf module is obsolete in Android 8+ but it shouldn't give issues.
|
||||||
if [ -d /data/adb/modules/MagiskHidePropsConf ]; then
|
if [ -d /data/adb/modules/MagiskHidePropsConf ]; then
|
||||||
ui_print "- ! WARNING, MagiskHidePropsConf module may cause issues with PIF."
|
ui_print "! WARNING, MagiskHidePropsConf module may cause issues with PIF."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Remove xiaomi.eu apps
|
# Remove xiaomi.eu apps
|
||||||
@ -29,6 +30,17 @@ fi
|
|||||||
|
|
||||||
# Remove EliteRoms app
|
# Remove EliteRoms app
|
||||||
|
|
||||||
|
if [ -d "/system/app/XInjectModule" ]; then
|
||||||
|
|
||||||
|
directory="$MODPATH/system/app/XInjectModule"
|
||||||
|
|
||||||
|
[ -d "$directory" ] || mkdir -p "$directory"
|
||||||
|
|
||||||
|
touch "$directory/.replace"
|
||||||
|
|
||||||
|
ui_print "- XInjectModule app removed."
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -d "/system/app/EliteDevelopmentModule" ]; then
|
if [ -d "/system/app/EliteDevelopmentModule" ]; then
|
||||||
|
|
||||||
directory="$MODPATH/system/app/EliteDevelopmentModule"
|
directory="$MODPATH/system/app/EliteDevelopmentModule"
|
||||||
@ -39,3 +51,9 @@ if [ -d "/system/app/EliteDevelopmentModule" ]; then
|
|||||||
|
|
||||||
ui_print "- EliteDevelopmentModule app removed."
|
ui_print "- EliteDevelopmentModule app removed."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
ui_print "! DO NOT REMOVE /data/adb/modules/playintegrityfix/pif.json"
|
||||||
|
ui_print "! THIS FILE CONTAINS THE DEFAULT PROPS TO SPOOF A CERTIFIED DEVICE"
|
||||||
|
ui_print "! IF YOU WANT TO USE YOUR CUSTOM PROPS, COPY THIS FILE TO /data/adb/pif.json"
|
||||||
|
ui_print "! MODULE WILL READ FIRST THAT FILE, IF IT ISN'T EXIST, IT WILL READ THE MODULE FOLDER ONE"
|
||||||
|
ui_print "! IF YOU REMOVE BOTH FILES EXPECT CRASHES"
|
@ -1,7 +1,7 @@
|
|||||||
id=playintegrityfix
|
id=playintegrityfix
|
||||||
name=Play Integrity Fix
|
name=Play Integrity Fix
|
||||||
version=v14.5
|
version=v14.6
|
||||||
versionCode=14500
|
versionCode=14600
|
||||||
author=chiteroman
|
author=chiteroman
|
||||||
description=Fuck Play Integrity API.
|
description=Fuck Play Integrity API.
|
||||||
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json
|
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json
|
@ -1,9 +1,12 @@
|
|||||||
{
|
{
|
||||||
"PRODUCT": "b1-780_ww_gen1",
|
"PRODUCT": "c01_ww",
|
||||||
"DEVICE": "acer_barricadewifi",
|
"DEVICE": "acer_c01",
|
||||||
"MANUFACTURER": "Acer",
|
"MANUFACTURER": "Acer Inc.",
|
||||||
"BRAND": "acer",
|
"BRAND": "acer",
|
||||||
"MODEL": "B1-780",
|
"MODEL": "C01",
|
||||||
"FINGERPRINT": "acer/b1-780_ww_gen1/acer_barricadewifi:6.0/MRA58K/1481784106:user/release-keys",
|
"FINGERPRINT": "acer/c01_ww/acer_c01:7.1.1/NMF26F/1521514970:user/release-keys",
|
||||||
"FIRST_API_LEVEL": "21"
|
"FIRST_API_LEVEL": "24",
|
||||||
|
"SECURITY_PATCH": "2018-04-01",
|
||||||
|
"VNDK_VERSION": null,
|
||||||
|
"BUILD_ID": null
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "v14.5",
|
"version": "v14.6",
|
||||||
"versionCode": 14500,
|
"versionCode": 14600,
|
||||||
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v14.5/PlayIntegrityFix_v14.5.zip",
|
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v14.6/PlayIntegrityFix_v14.6.zip",
|
||||||
"changelog": "https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/changelog.md"
|
"changelog": "https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/changelog.md"
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user