Mini update

This commit is contained in:
chiteroman 2024-04-23 16:32:22 +02:00
parent 0287cfcd26
commit 9e2b59e72f
15 changed files with 55 additions and 142 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="CompilerConfiguration"> <component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" /> <bytecodeTargetLevel target="21" />
</component> </component>
</project> </project>

View File

@ -5,7 +5,7 @@
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" /> <option name="gradleJvm" value="#JAVA_HOME" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <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" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View File

@ -5,21 +5,21 @@ plugins {
android { android {
namespace = "es.chiteroman.playintegrityfix" namespace = "es.chiteroman.playintegrityfix"
compileSdk = 34 compileSdk = 34
ndkVersion = "26.2.11394342" ndkVersion = "26.3.11579264"
buildToolsVersion = "34.0.0" buildToolsVersion = "34.0.0"
buildFeatures {
prefab = true
}
defaultConfig { defaultConfig {
applicationId = "es.chiteroman.playintegrityfix" applicationId = "es.chiteroman.playintegrityfix"
minSdk = 26 minSdk = 26
targetSdk = 34 targetSdk = 34
versionCode = 15970 versionCode = 15980
versionName = "v15.9.7" versionName = "v15.9.8"
multiDexEnabled = false multiDexEnabled = false
buildFeatures {
prefab = true
}
packaging { packaging {
jniLibs { jniLibs {
excludes += "**/liblog.so" excludes += "**/liblog.so"
@ -47,7 +47,9 @@ android {
isMinifyEnabled = true isMinifyEnabled = true
isShrinkResources = true isShrinkResources = true
multiDexEnabled = false 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 { doLast {
val moduleFolder = project.rootDir.resolve("module") val moduleFolder = project.rootDir.resolve("module")
val dexFile = project.layout.buildDirectory.get().asFile.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex") val dexFile =
val soDir = project.layout.buildDirectory.get().asFile.resolve("intermediates/stripped_native_libs/release/stripReleaseDebugSymbols/out/lib") 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) dexFile.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true)

View File

@ -4,10 +4,12 @@ project(playintegrityfix)
find_package(cxx REQUIRED CONFIG) find_package(cxx REQUIRED CONFIG)
link_libraries(log)
link_libraries(cxx::cxx) link_libraries(cxx::cxx)
add_library(${CMAKE_PROJECT_NAME} SHARED main.cpp) add_library(${CMAKE_PROJECT_NAME} SHARED main.cpp)
add_subdirectory(Dobby) add_subdirectory(Dobby)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE log dobby_static) target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE dobby_static)

View File

@ -13,36 +13,40 @@
#define PIF_JSON_DEFAULT "/data/adb/modules/playintegrityfix/pif.json" #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); 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) { 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);
if (prop.ends_with("security_patch")) { if (prop.ends_with("security_patch")) {
if (!SECURITY_PATCH.empty()) { if (json.contains("SECURITY_PATCH")) {
value = SECURITY_PATCH.c_str(); if (json["SECURITY_PATCH"].is_string()) {
value = json["SECURITY_PATCH"].get<std::string>().c_str();
}
} }
} else if (prop.ends_with("api_level")) { } else if (prop.ends_with("api_level")) {
if (!FIRST_API_LEVEL.empty()) { if (json.contains("FIRST_API_LEVEL")) {
value = FIRST_API_LEVEL.c_str(); 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")) { } else if (prop.ends_with("build.id")) {
if (!BUILD_ID.empty()) { if (json.contains("BUILD_ID")) {
value = BUILD_ID.c_str(); if (json["BUILD_ID"].is_string()) {
value = json["BUILD_ID"].get<std::string>().c_str();
}
} }
} else if (prop == "sys.usb.state") { } 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); 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 *); 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) { 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);
} }
@ -134,8 +138,6 @@ public:
read(fd, jsonVector.data(), jsonSize); read(fd, jsonVector.data(), jsonSize);
json = nlohmann::json::parse(jsonVector, nullptr, false, true); json = nlohmann::json::parse(jsonVector, nullptr, false, true);
parseJson();
} }
close(fd); close(fd);
@ -166,7 +168,6 @@ private:
zygisk::Api *api = nullptr; zygisk::Api *api = nullptr;
JNIEnv *env = nullptr; JNIEnv *env = nullptr;
std::vector<uint8_t> dexVector; std::vector<uint8_t> dexVector;
nlohmann::json json;
void injectDex() { void injectDex() {
LOGD("get system classloader"); LOGD("get system classloader");
@ -195,71 +196,6 @@ private:
auto str = env->NewStringUTF(json.dump().c_str()); auto str = env->NewStringUTF(json.dump().c_str());
env->CallStaticVoidMethod(entryPointClass, entryInit, 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) { static std::vector<uint8_t> readFile(const char *path) {

View File

@ -10,15 +10,12 @@ import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException; import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date; import java.util.Date;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Locale;
public final class CustomKeyStoreSpi extends KeyStoreSpi { public final class CustomKeyStoreSpi extends KeyStoreSpi {
private static final String EAT_OID = "1.3.6.1.4.1.11129.2.1.25"; public static volatile KeyStoreSpi keyStoreSpi = null;
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;
@Override @Override
public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException { public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException, UnrecoverableKeyException {
@ -28,41 +25,18 @@ public final class CustomKeyStoreSpi extends KeyStoreSpi {
@Override @Override
public Certificate[] engineGetCertificateChain(String alias) { public Certificate[] engineGetCertificateChain(String alias) {
boolean isDroidGuard = EntryPoint.isDroidGuard(); for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getClassName().toLowerCase(Locale.US).contains("droidguard")) {
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...");
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }
return certificates; return keyStoreSpi.engineGetCertificateChain(alias);
} }
@Override @Override
public Certificate engineGetCertificate(String alias) { public Certificate engineGetCertificate(String alias) {
return keyStoreSpi.engineGetCertificate(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;
} }
@Override @Override

View File

@ -10,9 +10,7 @@ import java.security.KeyStore;
import java.security.KeyStoreSpi; 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 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) { private static Field getFieldByName(String name) {
Field field; Field field;

View File

@ -1,3 +1,6 @@
plugins { buildscript {
id("com.android.application") version "8.3.1" apply false val agp_version by extra("8.3.2")
}
plugins {
id("com.android.application") version "8.3.2" apply false
} }

View File

@ -1,7 +1,7 @@
#Wed Feb 07 18:13:12 CET 2024 #Thu Apr 18 12:59:17 CEST 2024
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists 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 networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -1,7 +1,7 @@
id=playintegrityfix id=playintegrityfix
name=Play Integrity Fix name=Play Integrity Fix
version=v15.9.7 version=v15.9.8
versionCode=15970 versionCode=15980
author=chiteroman author=chiteroman
description=Universal modular fix for Play Integrity (and SafetyNet) on devices running Android 8-14. 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 updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json