diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..6d89050 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..146ab09 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0ad17cb --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e6e4b14..ca05e7c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -45,20 +45,24 @@ android { } tasks.register("copyFiles") { - val moduleFolder = project.rootDir.resolve("module") - val dexFile = project.buildDir.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex") - val soDir = project.buildDir.resolve("intermediates/stripped_native_libs/release/out/lib") + doLast { + val moduleFolder = project.rootDir.resolve("module") + val dexFile = project.buildDir.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex") + val soDir = project.buildDir.resolve("intermediates/stripped_native_libs/release/out/lib") - dexFile.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true) + dexFile.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true) - soDir.walk().filter { it.isFile && it.extension == "so" }.forEach { soFile -> - val abiFolder = soFile.parentFile.name - val destination = moduleFolder.resolve("zygisk/$abiFolder.so") - soFile.copyTo(destination, overwrite = true) + soDir.walk().filter { it.isFile && it.extension == "so" }.forEach { soFile -> + val abiFolder = soFile.parentFile.name + val destination = moduleFolder.resolve("zygisk/$abiFolder.so") + soFile.copyTo(destination, overwrite = true) + } } } tasks.register("zip") { + dependsOn("copyFiles") + archiveFileName.set("PlayIntegrityFix.zip") destinationDirectory.set(project.rootDir.resolve("out")) @@ -66,7 +70,5 @@ tasks.register("zip") { } afterEvaluate { - tasks.named("assembleRelease") { - dependsOn("copyFiles", "zip") - } + tasks["assembleRelease"].finalizedBy("copyFiles", "zip") } \ No newline at end of file diff --git a/app/src/main/cpp/main.cpp b/app/src/main/cpp/main.cpp index ba44e66..b4e98eb 100644 --- a/app/src/main/cpp/main.cpp +++ b/app/src/main/cpp/main.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "zygisk.hpp" #include "shadowhook.h" @@ -79,15 +80,13 @@ public: } void preAppSpecialize(zygisk::AppSpecializeArgs *args) override { - bool isGms = false; - bool isGmsUnstable = false; - auto rawProcess = env->GetStringUTFChars(args->nice_name, nullptr); - if (rawProcess) { - std::string_view process(rawProcess); - isGms = process.starts_with("com.google.android.gms"); - isGmsUnstable = process.compare("com.google.android.gms.unstable") == 0; - } + + std::string_view process(rawProcess); + + bool isGms = process.starts_with("com.google.android.gms"); + bool isGmsUnstable = process.compare("com.google.android.gms.unstable") == 0; + env->ReleaseStringUTFChars(args->nice_name, rawProcess); if (!isGms) { @@ -102,56 +101,51 @@ public: return; } - long size = 0; + int dexSize = 0; + int jsonSize = 0; + int fd = api->connectCompanion(); - read(fd, &size, sizeof(long)); + read(fd, &dexSize, sizeof(int)); + read(fd, &jsonSize, sizeof(int)); - if (size < 1) { + if (dexSize < 1) { close(fd); - LOGD("Couldn't read from file descriptor 'classes.dex' file!"); + LOGD("Couldn't read classes.dex"); api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY); return; } - dexVector.resize(size); - - read(fd, dexVector.data(), size); - - size = 0; - - read(fd, &size, sizeof(long)); - - if (size < 1) { + if (jsonSize < 1) { close(fd); - LOGD("Couldn't read from file descriptor 'pif.json' file!"); + LOGD("Couldn't read pif.json"); api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY); return; } - propVector.resize(size); + dexVector.resize(dexSize); + jsonVector.resize(jsonSize); - read(fd, propVector.data(), size); + read(fd, dexVector.data(), dexSize); + read(fd, jsonVector.data(), jsonSize); close(fd); - LOGD("Read from file descriptor file 'classes.dex' -> %d bytes", - static_cast(dexVector.size())); - LOGD("Read from file descriptor file 'pif.json' -> %d bytes", - static_cast(propVector.size())); + LOGD("Read from file descriptor file 'classes.dex' -> %d bytes", dexSize); + LOGD("Read from file descriptor file 'pif.json' -> %d bytes", jsonSize); } void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override { - if (dexVector.empty() || propVector.empty()) return; + if (dexVector.empty() || jsonVector.empty()) return; readJson(); - inject(); - doHook(); + inject(); + dexVector.clear(); - propVector.clear(); + jsonVector.clear(); } void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override { @@ -161,10 +155,10 @@ public: private: zygisk::Api *api = nullptr; JNIEnv *env = nullptr; - std::vector dexVector, propVector; + std::vector dexVector, jsonVector; void readJson() { - std::string data(propVector.cbegin(), propVector.cend()); + std::string data(jsonVector.cbegin(), jsonVector.cend()); nlohmann::json json = nlohmann::json::parse(data, nullptr, false, true); if (json.contains("SECURITY_PATCH")) { @@ -220,7 +214,7 @@ private: LOGD("read json"); auto readProps = env->GetStaticMethodID(entryClass, "readJson", "(Ljava/lang/String;)V"); - std::string data(propVector.cbegin(), propVector.cend()); + std::string data(jsonVector.cbegin(), jsonVector.cend()); auto javaStr = env->NewStringUTF(data.c_str()); env->CallStaticVoidMethod(entryClass, readProps, javaStr); @@ -231,46 +225,22 @@ private: }; static void companion(int fd) { - long dexSize = 0; - char *dexBuffer = nullptr; + std::ifstream dex(DEX_FILE_PATH, std::ios::binary); + std::ifstream json(JSON_FILE_PATH); - long jsonSize = 0; - char *jsonBuffer = nullptr; + std::vector dexVector((std::istreambuf_iterator(dex)), + std::istreambuf_iterator()); + std::vector jsonVector((std::istreambuf_iterator(json)), + std::istreambuf_iterator()); - FILE *dex = fopen(DEX_FILE_PATH, "rb"); + int dexSize = static_cast(dexVector.size()); + int jsonSize = static_cast(jsonVector.size()); - if (dex) { - fseek(dex, 0, SEEK_END); - dexSize = ftell(dex); - fseek(dex, 0, SEEK_SET); + write(fd, &dexSize, sizeof(int)); + write(fd, &jsonSize, sizeof(int)); - dexBuffer = static_cast(calloc(1, dexSize)); - fread(dexBuffer, 1, dexSize, dex); - - fclose(dex); - } - - FILE *json = fopen(JSON_FILE_PATH, "r"); - - if (json) { - fseek(json, 0, SEEK_END); - jsonSize = ftell(json); - fseek(json, 0, SEEK_SET); - - jsonBuffer = static_cast(calloc(1, jsonSize)); - fread(jsonBuffer, 1, jsonSize, json); - - fclose(json); - } - - write(fd, &dexSize, sizeof(long)); - write(fd, dexBuffer, dexSize); - - write(fd, &jsonSize, sizeof(long)); - write(fd, jsonBuffer, jsonSize); - - free(dexBuffer); - free(jsonBuffer); + write(fd, dexVector.data(), dexSize); + write(fd, jsonVector.data(), jsonSize); } REGISTER_ZYGISK_MODULE(PlayIntegrityFix) diff --git a/module/bin/arm64-v8a/resetprop b/module/bin/arm64-v8a/resetprop deleted file mode 100644 index 513fdef..0000000 Binary files a/module/bin/arm64-v8a/resetprop and /dev/null differ diff --git a/module/bin/armeabi-v7a/resetprop b/module/bin/armeabi-v7a/resetprop deleted file mode 100644 index dad18cd..0000000 Binary files a/module/bin/armeabi-v7a/resetprop and /dev/null differ diff --git a/module/customize.sh b/module/customize.sh index a6d50c0..ea07489 100644 --- a/module/customize.sh +++ b/module/customize.sh @@ -7,12 +7,4 @@ fi if [ -d "/data/adb/modules/safetynet-fix" ]; then touch "/data/adb/modules/safetynet-fix/remove" ui_print "- 'safetynet-fix' module will be removed in next reboot." -fi - -# Use custom resetprop only in Android 10+ -if [ "$API" -gt 28 ]; then - mv -f "$MODPATH/bin/$ABI/resetprop" "$MODPATH" - ui_print "- Using custom resetprop to avoid detections." -fi - -rm -rf "$MODPATH/bin" \ No newline at end of file +fi \ No newline at end of file diff --git a/module/module.prop b/module/module.prop index 6c77468..a1ae94f 100644 --- a/module/module.prop +++ b/module/module.prop @@ -1,7 +1,7 @@ id=playintegrityfix name=Play Integrity Fix -version=v13.8-beta -versionCode=137 +version=PROPS-v2.0 +versionCode=2000 author=chiteroman description=Fix CTS profile (SafetyNet) and DEVICE verdict (Play Integrity). updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json \ No newline at end of file diff --git a/module/service.sh b/module/service.sh index e032ef2..307ea1c 100644 --- a/module/service.sh +++ b/module/service.sh @@ -1,27 +1,12 @@ # Sensitive properties -RESETPROP="${0%/*}/resetprop" - -if [ -e "$RESETPROP" ]; then - chmod 755 $RESETPROP -else - RESETPROP="resetprop" -fi - -check_resetprop() { - local NAME=$1 - local EXPECTED=$2 - local VALUE=$(resetprop $NAME) - [ -z $VALUE ] || [ $VALUE = $EXPECTED ] || $RESETPROP -n $NAME $EXPECTED -} - maybe_set_prop() { local prop="$1" local contains="$2" local value="$3" if [[ "$(getprop "$prop")" == *"$contains"* ]]; then - $RESETPROP -n "$prop" "$value" + resetprop "$prop" "$value" fi } @@ -31,9 +16,7 @@ maybe_set_prop ro.boot.mode recovery unknown maybe_set_prop vendor.boot.mode recovery unknown # Hiding SELinux | Permissive status -if [ -n "$(getprop ro.build.selinux)" ]; then - $RESETPROP --delete ro.build.selinux -fi +resetprop --delete ro.build.selinux # Hiding SELinux | Use toybox to protect *stat* access time reading if [[ "$(toybox cat /sys/fs/selinux/enforce)" == "0" ]]; then @@ -41,40 +24,23 @@ if [[ "$(toybox cat /sys/fs/selinux/enforce)" == "0" ]]; then chmod 440 /sys/fs/selinux/policy fi -# Reset props after boot completed to avoid breaking some weird devices/ROMs... +# Late props which must be set after boot_completed { until [[ "$(getprop sys.boot_completed)" == "1" ]]; do sleep 1 done # SafetyNet/Play Integrity | Avoid breaking Realme fingerprint scanners - check_resetprop ro.boot.flash.locked 1 + resetprop ro.boot.flash.locked 1 # SafetyNet/Play Integrity | Avoid breaking Oppo fingerprint scanners - check_resetprop ro.boot.vbmeta.device_state locked + resetprop ro.boot.vbmeta.device_state locked # SafetyNet/Play Integrity | Avoid breaking OnePlus display modes/fingerprint scanners - check_resetprop vendor.boot.verifiedbootstate green + resetprop vendor.boot.verifiedbootstate green # SafetyNet/Play Integrity | Avoid breaking OnePlus display modes/fingerprint scanners on OOS 12 - check_resetprop ro.boot.verifiedbootstate green - check_resetprop ro.boot.veritymode enforcing - check_resetprop vendor.boot.vbmeta.device_state locked - - # RootBeer, Microsoft - check_resetprop ro.build.tags release-keys - - # Samsung - check_resetprop ro.boot.warranty_bit 0 - check_resetprop ro.vendor.boot.warranty_bit 0 - check_resetprop ro.vendor.warranty_bit 0 - check_resetprop ro.warranty_bit 0 - - # OnePlus - check_resetprop ro.is_ever_orange 0 - - # Other - check_resetprop ro.build.type user - check_resetprop ro.debuggable 0 - check_resetprop ro.secure 1 + resetprop ro.boot.verifiedbootstate green + resetprop ro.boot.veritymode enforcing + resetprop vendor.boot.vbmeta.device_state locked }& diff --git a/module/system.prop b/module/system.prop new file mode 100644 index 0000000..a1dfa57 --- /dev/null +++ b/module/system.prop @@ -0,0 +1,16 @@ +# RootBeer, Microsoft +ro.build.tags=release-keys + +# Samsung +ro.boot.warranty_bit=0 +ro.vendor.boot.warranty_bit=0 +ro.vendor.warranty_bit=0 +ro.warranty_bit=0 + +# OnePlus +ro.is_ever_orange=0 + +# Other +ro.build.type=user +ro.debuggable=0 +ro.secure=1