Skip to content

Commit

Permalink
Mini update
Browse files Browse the repository at this point in the history
  • Loading branch information
chiteroman committed Apr 23, 2024
1 parent 0287cfc commit 9e2b59e
Show file tree
Hide file tree
Showing 15 changed files with 55 additions and 142 deletions.
2 changes: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 14 additions & 10 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
)
}
}

Expand Down Expand Up @@ -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)

Expand Down
4 changes: 3 additions & 1 deletion app/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
98 changes: 17 additions & 81 deletions app/src/main/cpp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand All @@ -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 *);
Expand All @@ -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);
}

Expand Down Expand Up @@ -134,8 +138,6 @@ class PlayIntegrityFix : public zygisk::ModuleBase {
read(fd, jsonVector.data(), jsonSize);

json = nlohmann::json::parse(jsonVector, nullptr, false, true);

parseJson();
}

close(fd);
Expand Down Expand Up @@ -166,7 +168,6 @@ class PlayIntegrityFix : public zygisk::ModuleBase {
zygisk::Api *api = nullptr;
JNIEnv *env = nullptr;
std::vector<uint8_t> dexVector;
nlohmann::json json;

void injectDex() {
LOGD("get system classloader");
Expand Down Expand Up @@ -195,71 +196,6 @@ class PlayIntegrityFix : public zygisk::ModuleBase {
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,12 @@
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 {
Expand All @@ -28,41 +25,18 @@ public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmExc
@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
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 {
Expand Down Expand Up @@ -82,10 +80,6 @@ static void spoofFields() {
});
}

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;
Expand Down
5 changes: 4 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -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 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion module/META-INF/com/google/android/update-binary
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ mount /data 2>/dev/null
[ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk

install_module
exit 0
exit 0
2 changes: 1 addition & 1 deletion module/customize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions module/module.prop
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion module/pif.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
"SECURITY_PATCH": "2016-07-01",
"ID": "MCC24.246-37",
"FIRST_API_LEVEL": 21
}
}
2 changes: 1 addition & 1 deletion module/service.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
}&
}&

0 comments on commit 9e2b59e

Please sign in to comment.