mirror of
https://github.com/chiteroman/PlayIntegrityFix.git
synced 2025-01-18 19:12:38 +02:00
Mini update
This commit is contained in:
parent
0287cfcd26
commit
9e2b59e72f
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="17" />
|
||||
<bytecodeTargetLevel target="21" />
|
||||
</component>
|
||||
</project>
|
@ -5,7 +5,7 @@
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="gradleJvm" value="#JAVA_HOME" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?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">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="temurin-21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
@ -5,21 +5,21 @@ plugins {
|
||||
android {
|
||||
namespace = "es.chiteroman.playintegrityfix"
|
||||
compileSdk = 34
|
||||
ndkVersion = "26.2.11394342"
|
||||
ndkVersion = "26.3.11579264"
|
||||
buildToolsVersion = "34.0.0"
|
||||
|
||||
buildFeatures {
|
||||
prefab = true
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "es.chiteroman.playintegrityfix"
|
||||
minSdk = 26
|
||||
targetSdk = 34
|
||||
versionCode = 15970
|
||||
versionName = "v15.9.7"
|
||||
versionCode = 15980
|
||||
versionName = "v15.9.8"
|
||||
multiDexEnabled = false
|
||||
|
||||
buildFeatures {
|
||||
prefab = true
|
||||
}
|
||||
|
||||
packaging {
|
||||
jniLibs {
|
||||
excludes += "**/liblog.so"
|
||||
@ -47,7 +47,9 @@ android {
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
multiDexEnabled = false
|
||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,8 +92,10 @@ tasks.register("copyFiles") {
|
||||
|
||||
doLast {
|
||||
val moduleFolder = project.rootDir.resolve("module")
|
||||
val dexFile = project.layout.buildDirectory.get().asFile.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex")
|
||||
val soDir = project.layout.buildDirectory.get().asFile.resolve("intermediates/stripped_native_libs/release/stripReleaseDebugSymbols/out/lib")
|
||||
val dexFile =
|
||||
project.layout.buildDirectory.get().asFile.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex")
|
||||
val soDir =
|
||||
project.layout.buildDirectory.get().asFile.resolve("intermediates/stripped_native_libs/release/stripReleaseDebugSymbols/out/lib")
|
||||
|
||||
dexFile.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true)
|
||||
|
||||
|
@ -4,10 +4,12 @@ project(playintegrityfix)
|
||||
|
||||
find_package(cxx REQUIRED CONFIG)
|
||||
|
||||
link_libraries(log)
|
||||
|
||||
link_libraries(cxx::cxx)
|
||||
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED main.cpp)
|
||||
|
||||
add_subdirectory(Dobby)
|
||||
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE log dobby_static)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE dobby_static)
|
@ -13,36 +13,40 @@
|
||||
|
||||
#define PIF_JSON_DEFAULT "/data/adb/modules/playintegrityfix/pif.json"
|
||||
|
||||
static std::string FIRST_API_LEVEL, SECURITY_PATCH, BUILD_ID;
|
||||
static nlohmann::json json;
|
||||
|
||||
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
|
||||
|
||||
static std::map<void *, T_Callback> callbacks;
|
||||
static T_Callback o_callback = nullptr;
|
||||
|
||||
static void modify_callback(void *cookie, const char *name, const char *value, uint32_t serial) {
|
||||
|
||||
if (cookie == nullptr || name == nullptr || value == nullptr ||
|
||||
!callbacks.contains(cookie))
|
||||
return;
|
||||
if (cookie == nullptr || name == nullptr || value == nullptr || o_callback == nullptr) return;
|
||||
|
||||
std::string_view prop(name);
|
||||
|
||||
if (prop.ends_with("security_patch")) {
|
||||
|
||||
if (!SECURITY_PATCH.empty()) {
|
||||
value = SECURITY_PATCH.c_str();
|
||||
if (json.contains("SECURITY_PATCH")) {
|
||||
if (json["SECURITY_PATCH"].is_string()) {
|
||||
value = json["SECURITY_PATCH"].get<std::string>().c_str();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (prop.ends_with("api_level")) {
|
||||
|
||||
if (!FIRST_API_LEVEL.empty()) {
|
||||
value = FIRST_API_LEVEL.c_str();
|
||||
if (json.contains("FIRST_API_LEVEL")) {
|
||||
if (json["FIRST_API_LEVEL"].is_number_integer()) {
|
||||
value = std::to_string(json["FIRST_API_LEVEL"].get<int>()).c_str();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (prop.ends_with("build.id")) {
|
||||
|
||||
if (!BUILD_ID.empty()) {
|
||||
value = BUILD_ID.c_str();
|
||||
if (json.contains("BUILD_ID")) {
|
||||
if (json["BUILD_ID"].is_string()) {
|
||||
value = json["BUILD_ID"].get<std::string>().c_str();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (prop == "sys.usb.state") {
|
||||
@ -54,7 +58,7 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
|
||||
LOGD("[%s]: %s", name, value);
|
||||
}
|
||||
|
||||
return callbacks[cookie](cookie, name, value, serial);
|
||||
return o_callback(cookie, name, value, serial);
|
||||
}
|
||||
|
||||
static void (*o_system_property_read_callback)(const prop_info *, T_Callback, void *);
|
||||
@ -64,7 +68,7 @@ my_system_property_read_callback(const prop_info *pi, T_Callback callback, void
|
||||
if (pi == nullptr || callback == nullptr || cookie == nullptr) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -134,8 +138,6 @@ public:
|
||||
read(fd, jsonVector.data(), jsonSize);
|
||||
|
||||
json = nlohmann::json::parse(jsonVector, nullptr, false, true);
|
||||
|
||||
parseJson();
|
||||
}
|
||||
|
||||
close(fd);
|
||||
@ -166,7 +168,6 @@ private:
|
||||
zygisk::Api *api = nullptr;
|
||||
JNIEnv *env = nullptr;
|
||||
std::vector<uint8_t> dexVector;
|
||||
nlohmann::json json;
|
||||
|
||||
void injectDex() {
|
||||
LOGD("get system classloader");
|
||||
@ -195,71 +196,6 @@ private:
|
||||
auto str = env->NewStringUTF(json.dump().c_str());
|
||||
env->CallStaticVoidMethod(entryPointClass, entryInit, str);
|
||||
}
|
||||
|
||||
void parseJson() {
|
||||
if (json.contains("FIRST_API_LEVEL")) {
|
||||
|
||||
if (json["FIRST_API_LEVEL"].is_number_integer()) {
|
||||
|
||||
FIRST_API_LEVEL = std::to_string(json["FIRST_API_LEVEL"].get<int>());
|
||||
|
||||
} else if (json["FIRST_API_LEVEL"].is_string()) {
|
||||
|
||||
FIRST_API_LEVEL = json["FIRST_API_LEVEL"].get<std::string>();
|
||||
}
|
||||
|
||||
json.erase("FIRST_API_LEVEL");
|
||||
|
||||
} else if (json.contains("DEVICE_INITIAL_SDK_INT")) {
|
||||
|
||||
if (json["DEVICE_INITIAL_SDK_INT"].is_number_integer()) {
|
||||
|
||||
FIRST_API_LEVEL = std::to_string(json["DEVICE_INITIAL_SDK_INT"].get<int>());
|
||||
|
||||
} else if (json["DEVICE_INITIAL_SDK_INT"].is_string()) {
|
||||
|
||||
FIRST_API_LEVEL = json["DEVICE_INITIAL_SDK_INT"].get<std::string>();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
LOGD("JSON file doesn't contain FIRST_API_LEVEL or DEVICE_INITIAL_SDK_INT keys :(");
|
||||
}
|
||||
|
||||
if (json.contains("SECURITY_PATCH")) {
|
||||
|
||||
if (json["SECURITY_PATCH"].is_string()) {
|
||||
|
||||
SECURITY_PATCH = json["SECURITY_PATCH"].get<std::string>();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
LOGD("JSON file doesn't contain SECURITY_PATCH key :(");
|
||||
}
|
||||
|
||||
if (json.contains("ID")) {
|
||||
|
||||
if (json["ID"].is_string()) {
|
||||
|
||||
BUILD_ID = json["ID"].get<std::string>();
|
||||
}
|
||||
|
||||
} else if (json.contains("BUILD_ID")) {
|
||||
|
||||
if (json["BUILD_ID"].is_string()) {
|
||||
|
||||
BUILD_ID = json["BUILD_ID"].get<std::string>();
|
||||
}
|
||||
|
||||
json["ID"] = BUILD_ID;
|
||||
json.erase("BUILD_ID");
|
||||
|
||||
} else {
|
||||
|
||||
LOGD("JSON file doesn't contain ID/BUILD_ID keys :(");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static std::vector<uint8_t> readFile(const char *path) {
|
||||
|
@ -10,15 +10,12 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class CustomKeyStoreSpi extends KeyStoreSpi {
|
||||
private static final String EAT_OID = "1.3.6.1.4.1.11129.2.1.25";
|
||||
private static final String ASN1_OID = "1.3.6.1.4.1.11129.2.1.17";
|
||||
private static final String KNOX_OID = "1.3.6.1.4.1.236.11.3.23.7";
|
||||
public static volatile KeyStoreSpi keyStoreSpi;
|
||||
public static volatile KeyStoreSpi keyStoreSpi = null;
|
||||
|
||||
@Override
|
||||
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException {
|
||||
@ -28,41 +25,18 @@ public final class CustomKeyStoreSpi extends KeyStoreSpi {
|
||||
@Override
|
||||
public Certificate[] engineGetCertificateChain(String alias) {
|
||||
|
||||
boolean isDroidGuard = EntryPoint.isDroidGuard();
|
||||
|
||||
Certificate[] certificates = keyStoreSpi.engineGetCertificateChain(alias);
|
||||
|
||||
if (certificates[0] instanceof X509Certificate leaf) {
|
||||
|
||||
boolean attestationExtensions = leaf.getExtensionValue(EAT_OID) != null || leaf.getExtensionValue(ASN1_OID) != null || leaf.getExtensionValue(KNOX_OID) != null;
|
||||
|
||||
if (isDroidGuard && attestationExtensions) {
|
||||
EntryPoint.LOG("DroidGuard and attestation extension detected! Throwing exception...");
|
||||
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
|
||||
if (element.getClassName().toLowerCase(Locale.US).contains("droidguard")) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
return certificates;
|
||||
return keyStoreSpi.engineGetCertificateChain(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate engineGetCertificate(String alias) {
|
||||
|
||||
boolean isDroidGuard = EntryPoint.isDroidGuard();
|
||||
|
||||
Certificate certificate = keyStoreSpi.engineGetCertificate(alias);
|
||||
|
||||
if (certificate instanceof X509Certificate leaf) {
|
||||
|
||||
boolean attestationExtensions = leaf.getExtensionValue(EAT_OID) != null || leaf.getExtensionValue(ASN1_OID) != null || leaf.getExtensionValue(KNOX_OID) != null;
|
||||
|
||||
if (isDroidGuard && attestationExtensions) {
|
||||
EntryPoint.LOG("DroidGuard and attestation extension detected! Throwing exception...");
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
return certificate;
|
||||
return keyStoreSpi.engineGetCertificate(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -10,9 +10,7 @@ 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 final class EntryPoint {
|
||||
@ -82,10 +80,6 @@ public final class EntryPoint {
|
||||
});
|
||||
}
|
||||
|
||||
static boolean isDroidGuard() {
|
||||
return Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch(stackTraceElement -> stackTraceElement.getClassName().toLowerCase(Locale.US).contains("droidguard"));
|
||||
}
|
||||
|
||||
private static Field getFieldByName(String name) {
|
||||
|
||||
Field field;
|
||||
|
@ -1,3 +1,6 @@
|
||||
buildscript {
|
||||
val agp_version by extra("8.3.2")
|
||||
}
|
||||
plugins {
|
||||
id("com.android.application") version "8.3.1" apply false
|
||||
id("com.android.application") version "8.3.2" apply false
|
||||
}
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,7 +1,7 @@
|
||||
#Wed Feb 07 18:13:12 CET 2024
|
||||
#Thu Apr 18 12:59:17 CEST 2024
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -30,4 +30,4 @@ mount /data 2>/dev/null
|
||||
[ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk
|
||||
|
||||
install_module
|
||||
exit 0
|
||||
exit 0
|
@ -20,4 +20,4 @@ if [ -f "/data/adb/pif.json" ]; then
|
||||
ui_print "- You are using custom fingerprint!"
|
||||
ui_print "- If you fail DEVICE verdict, remove /data/adb/pif.json file"
|
||||
ui_print "- If pif.json file doesn't exist, module will use default one"
|
||||
fi
|
||||
fi
|
@ -1,7 +1,7 @@
|
||||
id=playintegrityfix
|
||||
name=Play Integrity Fix
|
||||
version=v15.9.7
|
||||
versionCode=15970
|
||||
version=v15.9.8
|
||||
versionCode=15980
|
||||
author=chiteroman
|
||||
description=Universal modular fix for Play Integrity (and SafetyNet) on devices running Android 8-14.
|
||||
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json
|
||||
|
@ -8,4 +8,4 @@
|
||||
"SECURITY_PATCH": "2016-07-01",
|
||||
"ID": "MCC24.246-37",
|
||||
"FIRST_API_LEVEL": 21
|
||||
}
|
||||
}
|
@ -53,4 +53,4 @@ fi
|
||||
resetprop_if_diff ro.boot.verifiedbootstate green
|
||||
resetprop_if_diff ro.boot.veritymode enforcing
|
||||
resetprop_if_diff vendor.boot.vbmeta.device_state locked
|
||||
}&
|
||||
}&
|
Loading…
Reference in New Issue
Block a user