mirror of
https://github.com/chiteroman/PlayIntegrityFix.git
synced 2025-01-19 03:22:39 +02:00
v15.0
This commit is contained in:
parent
325fbdc2f5
commit
aa340e742e
3
.idea/.gitignore
vendored
3
.idea/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
@ -1,11 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="jbr-17" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
|
@ -1,3 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/app/src/main/cpp/Dobby" vcs="Git" />
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
3
app/proguard-rules.pro
vendored
3
app/proguard-rules.pro
vendored
@ -1,6 +1,3 @@
|
||||
-ignorewarnings
|
||||
-dontobfuscate
|
||||
-keep class es.chiteroman.playintegrityfix.EntryPoint {public <methods>;}
|
||||
-keep class es.chiteroman.playintegrityfix.CustomProvider
|
||||
-keep class es.chiteroman.playintegrityfix.CustomKeyStoreSpi
|
||||
-keep class es.chiteroman.playintegrityfix.CustomCertificates
|
@ -1,7 +1,6 @@
|
||||
#include <android/log.h>
|
||||
#include <sys/system_properties.h>
|
||||
#include <unistd.h>
|
||||
#include <filesystem>
|
||||
|
||||
#include "zygisk.hpp"
|
||||
#include "dobby.h"
|
||||
@ -48,6 +47,10 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
|
||||
value = BUILD_ID.c_str();
|
||||
LOGD("Set '%s' to '%s'", name, value);
|
||||
}
|
||||
|
||||
} else if (prop == "sys.usb.state") {
|
||||
|
||||
value = "none";
|
||||
}
|
||||
|
||||
return o_callback(cookie, name, value, serial);
|
||||
@ -87,6 +90,11 @@ public:
|
||||
|
||||
void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
|
||||
|
||||
if (args->is_child_zygote && *args->is_child_zygote) {
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
return;
|
||||
}
|
||||
|
||||
auto name = env->GetStringUTFChars(args->nice_name, nullptr);
|
||||
|
||||
if (name && strncmp(name, "com.google.android.gms", 22) == 0) {
|
||||
@ -95,24 +103,39 @@ public:
|
||||
|
||||
if (strcmp(name, "com.google.android.gms.unstable") == 0) {
|
||||
|
||||
auto rawDir = env->GetStringUTFChars(args->app_data_dir, nullptr);
|
||||
dir = rawDir;
|
||||
env->ReleaseStringUTFChars(args->app_data_dir, rawDir);
|
||||
|
||||
long size = dir.size();
|
||||
bool done = false;
|
||||
|
||||
int fd = api->connectCompanion();
|
||||
|
||||
write(fd, &size, sizeof(long));
|
||||
write(fd, dir.data(), size);
|
||||
read(fd, &dexSize, sizeof(long));
|
||||
|
||||
read(fd, &done, sizeof(bool));
|
||||
if (dexSize > 0) {
|
||||
|
||||
dexBuffer = new unsigned char[dexSize];
|
||||
read(fd, dexBuffer, dexSize);
|
||||
|
||||
} else {
|
||||
|
||||
LOGD("Couldn't load classes.dex file in memory!");
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
goto end;
|
||||
}
|
||||
|
||||
read(fd, &jsonSize, sizeof(long));
|
||||
|
||||
if (jsonSize > 0) {
|
||||
|
||||
jsonBuffer = new char[jsonSize];
|
||||
read(fd, jsonBuffer, jsonSize);
|
||||
|
||||
} else {
|
||||
|
||||
LOGD("Couldn't load pif.json file in memory!");
|
||||
delete[] dexBuffer;
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
close(fd);
|
||||
|
||||
LOGD("Files copied: %d", done);
|
||||
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
@ -124,31 +147,10 @@ public:
|
||||
}
|
||||
|
||||
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
||||
if (dir.empty()) return;
|
||||
if (dexSize < 1 || jsonSize < 1 || dexBuffer == nullptr || jsonBuffer == nullptr) return;
|
||||
|
||||
std::string classesDex(dir + "/classes.dex");
|
||||
|
||||
FILE *dexFile = fopen(classesDex.c_str(), "rb");
|
||||
|
||||
if (dexFile == nullptr) {
|
||||
|
||||
LOGD("classes.dex doesn't exist... This is weird.");
|
||||
dir.clear();
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(dexFile);
|
||||
|
||||
doHook();
|
||||
|
||||
std::string pifJson(dir + "/pif.json");
|
||||
|
||||
FILE *jsonFile = fopen(pifJson.c_str(), "r");
|
||||
|
||||
nlohmann::json json = nlohmann::json::parse(jsonFile, nullptr, false, true);
|
||||
|
||||
fclose(jsonFile);
|
||||
std::string_view jsonStr(jsonBuffer, jsonSize);
|
||||
nlohmann::json json = nlohmann::json::parse(jsonStr, nullptr, false, true);
|
||||
|
||||
if (json.contains("FIRST_API_LEVEL")) {
|
||||
|
||||
@ -180,20 +182,20 @@ public:
|
||||
LOGD("JSON file doesn't contain SECURITY_PATCH key :(");
|
||||
}
|
||||
|
||||
if (json.contains("BUILD_ID")) {
|
||||
if (json.contains("ID")) {
|
||||
|
||||
if (json["BUILD_ID"].is_string()) {
|
||||
if (json["ID"].is_string()) {
|
||||
|
||||
BUILD_ID = json["BUILD_ID"].get<std::string>();
|
||||
BUILD_ID = json["ID"].get<std::string>();
|
||||
}
|
||||
|
||||
json.erase("BUILD_ID");
|
||||
|
||||
} else {
|
||||
|
||||
LOGD("JSON file doesn't contain BUILD_ID key :(");
|
||||
}
|
||||
|
||||
doHook();
|
||||
|
||||
LOGD("get system classloader");
|
||||
auto clClass = env->FindClass("java/lang/ClassLoader");
|
||||
auto getSystemClassLoader = env->GetStaticMethodID(clClass, "getSystemClassLoader",
|
||||
@ -201,11 +203,11 @@ public:
|
||||
auto systemClassLoader = env->CallStaticObjectMethod(clClass, getSystemClassLoader);
|
||||
|
||||
LOGD("create class loader");
|
||||
auto dexClClass = env->FindClass("dalvik/system/PathClassLoader");
|
||||
auto dexClClass = env->FindClass("dalvik/system/InMemoryDexClassLoader");
|
||||
auto dexClInit = env->GetMethodID(dexClClass, "<init>",
|
||||
"(Ljava/lang/String;Ljava/lang/ClassLoader;)V");
|
||||
auto dexStr = env->NewStringUTF(classesDex.c_str());
|
||||
auto dexCl = env->NewObject(dexClClass, dexClInit, dexStr, systemClassLoader);
|
||||
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
||||
auto buffer = env->NewDirectByteBuffer(dexBuffer, dexSize);
|
||||
auto dexCl = env->NewObject(dexClClass, dexClInit, buffer, systemClassLoader);
|
||||
|
||||
LOGD("load class");
|
||||
auto loadClass = env->GetMethodID(clClass, "loadClass",
|
||||
@ -220,7 +222,16 @@ public:
|
||||
auto str = env->NewStringUTF(json.dump().c_str());
|
||||
env->CallStaticVoidMethod(entryClass, entryInit, str);
|
||||
|
||||
dir.clear();
|
||||
env->DeleteLocalRef(clClass);
|
||||
env->DeleteLocalRef(dexClClass);
|
||||
env->DeleteLocalRef(buffer);
|
||||
env->DeleteLocalRef(dexCl);
|
||||
env->DeleteLocalRef(entryClassName);
|
||||
env->DeleteLocalRef(entryClassObj);
|
||||
env->DeleteLocalRef(str);
|
||||
|
||||
delete[] dexBuffer;
|
||||
delete[] jsonBuffer;
|
||||
}
|
||||
|
||||
void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override {
|
||||
@ -230,42 +241,53 @@ public:
|
||||
private:
|
||||
zygisk::Api *api = nullptr;
|
||||
JNIEnv *env = nullptr;
|
||||
std::string dir;
|
||||
long dexSize = 0, jsonSize = 0;
|
||||
unsigned char *dexBuffer = nullptr;
|
||||
char *jsonBuffer = nullptr;
|
||||
};
|
||||
|
||||
static void companion(int fd) {
|
||||
long dexSize = 0, jsonSize = 0;
|
||||
unsigned char *dexBuffer = nullptr;
|
||||
char *jsonBuffer = nullptr;
|
||||
|
||||
long size = 0;
|
||||
std::string dir;
|
||||
FILE *dexFile = fopen(CLASSES_DEX, "rb");
|
||||
|
||||
read(fd, &size, sizeof(long));
|
||||
if (dexFile) {
|
||||
|
||||
dir.resize(size);
|
||||
fseek(dexFile, 0, SEEK_END);
|
||||
dexSize = ftell(dexFile);
|
||||
fseek(dexFile, 0, SEEK_SET);
|
||||
|
||||
read(fd, dir.data(), size);
|
||||
dexBuffer = new unsigned char[dexSize];
|
||||
fread(dexBuffer, 1, dexSize, dexFile);
|
||||
|
||||
LOGD("[ROOT] GMS dir: %s", dir.c_str());
|
||||
fclose(dexFile);
|
||||
}
|
||||
|
||||
std::string classesDex(dir + "/classes.dex");
|
||||
std::string pifJson(dir + "/pif.json");
|
||||
write(fd, &dexSize, sizeof(long));
|
||||
write(fd, dexBuffer, dexSize);
|
||||
|
||||
bool a = std::filesystem::copy_file(CLASSES_DEX, classesDex,
|
||||
std::filesystem::copy_options::overwrite_existing);
|
||||
delete[] dexBuffer;
|
||||
|
||||
std::filesystem::permissions(classesDex, std::filesystem::perms::owner_read |
|
||||
std::filesystem::perms::group_read |
|
||||
std::filesystem::perms::others_read);
|
||||
FILE *jsonFile = fopen(PIF_JSON, "r");
|
||||
|
||||
bool b = std::filesystem::copy_file(PIF_JSON, pifJson,
|
||||
std::filesystem::copy_options::overwrite_existing);
|
||||
if (jsonFile) {
|
||||
|
||||
std::filesystem::permissions(pifJson, std::filesystem::perms::owner_read |
|
||||
std::filesystem::perms::group_read |
|
||||
std::filesystem::perms::others_read);
|
||||
fseek(jsonFile, 0, SEEK_END);
|
||||
jsonSize = ftell(jsonFile);
|
||||
fseek(jsonFile, 0, SEEK_SET);
|
||||
|
||||
bool done = a && b;
|
||||
jsonBuffer = new char[jsonSize];
|
||||
fread(jsonBuffer, 1, jsonSize, jsonFile);
|
||||
|
||||
write(fd, &done, sizeof(bool));
|
||||
fclose(jsonFile);
|
||||
}
|
||||
|
||||
write(fd, &jsonSize, sizeof(long));
|
||||
write(fd, jsonBuffer, jsonSize);
|
||||
|
||||
delete[] jsonBuffer;
|
||||
}
|
||||
|
||||
REGISTER_ZYGISK_MODULE(PlayIntegrityFix)
|
||||
|
@ -14,7 +14,8 @@ import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
|
||||
public class CustomKeyStoreSpi extends KeyStoreSpi {
|
||||
public static volatile KeyStoreSpi keyStoreSpi;
|
||||
public static KeyStoreSpi keyStoreSpi;
|
||||
|
||||
|
||||
@Override
|
||||
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException {
|
||||
@ -23,14 +24,8 @@ public class CustomKeyStoreSpi extends KeyStoreSpi {
|
||||
|
||||
@Override
|
||||
public Certificate[] engineGetCertificateChain(String alias) {
|
||||
|
||||
if (EntryPoint.isDroidGuard()) {
|
||||
|
||||
EntryPoint.LOG("engineGetCertificateChain call! Throw exception");
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
return keyStoreSpi.engineGetCertificateChain(alias);
|
||||
EntryPoint.LOG("Tried to get certificate chain, throwing exception!");
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,7 +2,7 @@ package es.chiteroman.playintegrityfix;
|
||||
|
||||
import java.security.Provider;
|
||||
|
||||
public class CustomProvider extends Provider {
|
||||
public final class CustomProvider extends Provider {
|
||||
|
||||
public CustomProvider(Provider provider) {
|
||||
super(provider.getName(), provider.getVersion(), provider.getInfo());
|
||||
@ -14,7 +14,6 @@ public class CustomProvider extends Provider {
|
||||
|
||||
@Override
|
||||
public synchronized Service getService(String type, String algorithm) {
|
||||
EntryPoint.LOG("[SERVICE] Type: " + type + " | Algorithm: " + algorithm);
|
||||
|
||||
EntryPoint.spoofDevice();
|
||||
|
||||
|
@ -1,66 +1,58 @@
|
||||
package es.chiteroman.playintegrityfix;
|
||||
|
||||
import android.os.Build;
|
||||
import android.util.JsonReader;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.StringReader;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreSpi;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class EntryPoint {
|
||||
private static final Map<String, String> map = new HashMap<>();
|
||||
public final class EntryPoint {
|
||||
private static JSONObject jsonObject = new JSONObject();
|
||||
|
||||
public static void init(String json) {
|
||||
|
||||
try (JsonReader reader = new JsonReader(new StringReader(json))) {
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String key = reader.nextName();
|
||||
String value = reader.nextString();
|
||||
map.put(key, value);
|
||||
}
|
||||
reader.endObject();
|
||||
} catch (Exception e) {
|
||||
LOG("Error parsing JSON: " + e);
|
||||
try {
|
||||
jsonObject = new JSONObject(json);
|
||||
} catch (JSONException e) {
|
||||
LOG("Couldn't parse JSON from Zygisk");
|
||||
}
|
||||
|
||||
LOG("Map info (keys and values):");
|
||||
map.forEach((s, s2) -> LOG(String.format("[%s] -> %s", s, s2)));
|
||||
boolean FORCE_BASIC_ATTESTATION = true;
|
||||
|
||||
if (jsonObject.has("FORCE_BASIC_ATTESTATION")) {
|
||||
try {
|
||||
FORCE_BASIC_ATTESTATION = jsonObject.getBoolean("FORCE_BASIC_ATTESTATION");
|
||||
} catch (JSONException e) {
|
||||
LOG("Couldn't parse FORCE_BASIC_ATTESTATION from JSON");
|
||||
}
|
||||
jsonObject.remove("FORCE_BASIC_ATTESTATION");
|
||||
}
|
||||
|
||||
spoofDevice();
|
||||
spoofProvider();
|
||||
|
||||
if (FORCE_BASIC_ATTESTATION) spoofProvider();
|
||||
}
|
||||
|
||||
protected static void LOG(String msg) {
|
||||
static void LOG(String msg) {
|
||||
Log.d("PIF/Java", msg);
|
||||
}
|
||||
|
||||
protected static void spoofDevice() {
|
||||
map.forEach(EntryPoint::setFieldValue);
|
||||
}
|
||||
|
||||
protected static boolean isDroidGuard() {
|
||||
return Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch(e -> e.getClassName().toLowerCase(Locale.US).contains("droidguard"));
|
||||
static void spoofDevice() {
|
||||
jsonObject.keys().forEachRemaining(s -> {
|
||||
try {
|
||||
Object value = jsonObject.get(s);
|
||||
setFieldValue(s, value);
|
||||
} catch (JSONException ignored) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void spoofProvider() {
|
||||
try {
|
||||
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||
|
||||
Field field = keyStore.getClass().getDeclaredField("keyStoreSpi");
|
||||
|
||||
field.setAccessible(true);
|
||||
CustomKeyStoreSpi.keyStoreSpi = (KeyStoreSpi) field.get(keyStore);
|
||||
field.setAccessible(false);
|
||||
|
||||
Provider provider = Security.getProvider("AndroidKeyStore");
|
||||
|
||||
Provider customProvider = new CustomProvider(provider);
|
||||
@ -70,14 +62,18 @@ public class EntryPoint {
|
||||
|
||||
LOG("Spoof KeyStoreSpi and Provider done!");
|
||||
|
||||
} catch (Exception e) {
|
||||
LOG("spoofProvider exception: " + e);
|
||||
} catch (Throwable t) {
|
||||
LOG("spoofProvider exception: " + t);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setFieldValue(String name, String value) {
|
||||
if (name == null || value == null || name.isEmpty() || value.isEmpty()) return;
|
||||
private static void setFieldValue(String name, Object value) {
|
||||
if (name == null || value == null || name.isEmpty()) return;
|
||||
|
||||
if (value instanceof String str) if (str.isEmpty() || str.isBlank()) return;
|
||||
|
||||
Field field = null;
|
||||
|
||||
try {
|
||||
field = Build.class.getDeclaredField(name);
|
||||
} catch (NoSuchFieldException e) {
|
||||
@ -87,16 +83,23 @@ public class EntryPoint {
|
||||
LOG("Couldn't find field: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
if (field == null) return;
|
||||
|
||||
field.setAccessible(true);
|
||||
String oldValue = null;
|
||||
try {
|
||||
oldValue = (String) field.get(null);
|
||||
if (value.equals(oldValue)) return;
|
||||
field.set(null, value);
|
||||
|
||||
Object oldValue = field.get(null);
|
||||
|
||||
if (!value.equals(oldValue)) {
|
||||
|
||||
field.set(null, value);
|
||||
LOG("Set [" + name + "] field value to [" + value + "]");
|
||||
}
|
||||
|
||||
} catch (IllegalAccessException e) {
|
||||
LOG("Couldn't get or set field: " + e);
|
||||
LOG("Couldn't modify field :(");
|
||||
}
|
||||
LOG(String.format("Field '%s' with value '%s' is now set to '%s'", name, oldValue, value));
|
||||
field.setAccessible(false);
|
||||
}
|
||||
}
|
@ -2,6 +2,6 @@ We have a Telegram channel!
|
||||
If you want to share your knowledge join:
|
||||
https://t.me/playintegrityfix
|
||||
|
||||
# v14.9
|
||||
# v15.0
|
||||
|
||||
- Fix DEVICE verdict not passing with some fingerprints.
|
||||
- Fix issues.
|
@ -1,32 +0,0 @@
|
||||
resetprop_if_diff() {
|
||||
local NAME=$1
|
||||
local EXPECTED=$2
|
||||
local CURRENT=$(resetprop $NAME)
|
||||
|
||||
[ -z "$CURRENT" ] || [ "$CURRENT" == "$EXPECTED" ] || resetprop $NAME $EXPECTED
|
||||
}
|
||||
|
||||
resetprop_if_match() {
|
||||
local NAME=$1
|
||||
local CONTAINS=$2
|
||||
local VALUE=$3
|
||||
|
||||
[[ "$(resetprop $NAME)" == *"$CONTAINS"* ]] && resetprop $NAME $VALUE
|
||||
}
|
||||
|
||||
# Avoid breaking Realme fingerprint scanners
|
||||
resetprop_if_diff ro.boot.flash.locked 1
|
||||
|
||||
# Avoid breaking Oppo fingerprint scanners
|
||||
resetprop_if_diff ro.boot.vbmeta.device_state locked
|
||||
|
||||
# Avoid breaking OnePlus display modes/fingerprint scanners
|
||||
resetprop_if_diff vendor.boot.verifiedbootstate green
|
||||
|
||||
# Avoid breaking OnePlus/Oppo display fingerprint scanners on OOS/ColorOS 12+
|
||||
resetprop_if_diff ro.boot.verifiedbootstate green
|
||||
resetprop_if_diff ro.boot.veritymode enforcing
|
||||
resetprop_if_diff vendor.boot.vbmeta.device_state locked
|
||||
|
||||
# Restrict permissions to socket file
|
||||
chmod 440 /proc/net/unix
|
@ -52,7 +52,7 @@ if [ -d "/system/app/EliteDevelopmentModule" ]; then
|
||||
ui_print "- EliteDevelopmentModule app removed."
|
||||
fi
|
||||
|
||||
# Move pif.json file
|
||||
# Move empty pif.json file
|
||||
if [ ! -f "/data/adb/pif.json" ]; then
|
||||
mv -f $MODPATH/pif.json /data/adb/
|
||||
fi
|
||||
|
@ -1,7 +1,7 @@
|
||||
id=playintegrityfix
|
||||
name=Play Integrity Fix
|
||||
version=v14.9
|
||||
versionCode=14900
|
||||
version=v15.0
|
||||
versionCode=15000
|
||||
author=chiteroman
|
||||
description=Universal modular fix for Play Integrity (and SafetyNet) on devices running Android 8+.
|
||||
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json
|
||||
|
@ -1,11 +1,12 @@
|
||||
{
|
||||
"PRODUCT": "",
|
||||
"DEVICE": "",
|
||||
"MANUFACTURER": "",
|
||||
"BRAND": "",
|
||||
"MODEL": "",
|
||||
"FINGERPRINT": "",
|
||||
"FIRST_API_LEVEL": 21,
|
||||
"SECURITY_PATCH": "",
|
||||
"BUILD_ID": ""
|
||||
"PRODUCT": "",
|
||||
"DEVICE": "",
|
||||
"MANUFACTURER": "",
|
||||
"BRAND": "",
|
||||
"MODEL": "",
|
||||
"FINGERPRINT": "",
|
||||
"SECURITY_PATCH": "",
|
||||
"ID": "",
|
||||
"FIRST_API_LEVEL": 24,
|
||||
"FORCE_BASIC_ATTESTATION": true
|
||||
}
|
||||
|
@ -32,29 +32,21 @@ if [ "$(toybox cat /sys/fs/selinux/enforce)" == "0" ]; then
|
||||
chmod 440 /sys/fs/selinux/policy
|
||||
fi
|
||||
|
||||
# KernelSU handles boot completed state in different file.
|
||||
if [ -z "$KSU" ] || [ "$KSU" = false ]; then
|
||||
{
|
||||
# late props which must be set after boot_completed for various OEMs
|
||||
until [ "$(resetprop sys.boot_completed)" == "1" ]; do
|
||||
sleep 1
|
||||
done
|
||||
# late props which must be set after boot_completed for various OEMs
|
||||
until [ "$(resetprop sys.boot_completed)" == "1" ]; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Avoid breaking Realme fingerprint scanners
|
||||
resetprop_if_diff ro.boot.flash.locked 1
|
||||
# Avoid breaking Realme fingerprint scanners
|
||||
resetprop_if_diff ro.boot.flash.locked 1
|
||||
# Avoid breaking Oppo fingerprint scanners
|
||||
resetprop_if_diff ro.boot.vbmeta.device_state locked
|
||||
# Avoid breaking OnePlus display modes/fingerprint scanners
|
||||
resetprop_if_diff vendor.boot.verifiedbootstate green
|
||||
# Avoid breaking OnePlus/Oppo display fingerprint scanners on OOS/ColorOS 12+
|
||||
resetprop_if_diff ro.boot.verifiedbootstate green
|
||||
resetprop_if_diff ro.boot.veritymode enforcing
|
||||
resetprop_if_diff vendor.boot.vbmeta.device_state locked
|
||||
|
||||
# Avoid breaking Oppo fingerprint scanners
|
||||
resetprop_if_diff ro.boot.vbmeta.device_state locked
|
||||
|
||||
# Avoid breaking OnePlus display modes/fingerprint scanners
|
||||
resetprop_if_diff vendor.boot.verifiedbootstate green
|
||||
|
||||
# Avoid breaking OnePlus/Oppo display fingerprint scanners on OOS/ColorOS 12+
|
||||
resetprop_if_diff ro.boot.verifiedbootstate green
|
||||
resetprop_if_diff ro.boot.veritymode enforcing
|
||||
resetprop_if_diff vendor.boot.vbmeta.device_state locked
|
||||
|
||||
# Restrict permissions to socket file
|
||||
chmod 440 /proc/net/unix
|
||||
}&
|
||||
fi
|
||||
# Restrict permissions to socket file
|
||||
chmod 440 /proc/net/unix
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "v14.9",
|
||||
"versionCode": 14900,
|
||||
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v14.9/PlayIntegrityFix_v14.9.zip",
|
||||
"version": "v15.0",
|
||||
"versionCode": 15000,
|
||||
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v15.0/PlayIntegrityFix_v15.0.zip",
|
||||
"changelog": "https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/changelog.md"
|
||||
}
|
Loading…
Reference in New Issue
Block a user