diff --git a/app/src/main/cpp/main.cpp b/app/src/main/cpp/main.cpp index 7036f05..1ae0d3f 100644 --- a/app/src/main/cpp/main.cpp +++ b/app/src/main/cpp/main.cpp @@ -20,6 +20,9 @@ #define CUSTOM_JSON_FORK "/data/adb/modules/playintegrityfix/custom.pif.json" #define CUSTOM_JSON "/data/adb/pif.json" +#define VENDING_PACKAGE "com.android.vending" +#define DROIDGUARD_PACKAGE "com.google.android.gms.unstable" + static ssize_t xread(int fd, void *buffer, size_t count) { ssize_t total = 0; char *buf = static_cast(buffer); @@ -129,7 +132,10 @@ public: return; } - bool isGms = std::string_view(dir).ends_with("/com.google.android.gms"); + std::string_view vDir(dir); + + bool isGms = + vDir.ends_with("/com.google.android.gms") || vDir.ends_with("/com.android.vending"); env->ReleaseStringUTFChars(args->app_data_dir, dir); @@ -147,15 +153,24 @@ public: return; } - bool isGmsUnstable = std::string_view(name) == "com.google.android.gms.unstable"; + std::string_view vName(name); + + isGmsUnstable = vName == DROIDGUARD_PACKAGE; + isVending = vName == VENDING_PACKAGE; env->ReleaseStringUTFChars(args->nice_name, name); - if (!isGmsUnstable) { + if (!isGmsUnstable && !isVending) { api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY); return; } + if (isGmsUnstable) + LOGD("We are in GMS unstable process!"); + + if (isVending) + LOGD("We are in Play Store process!"); + int fd = api->connectCompanion(); size_t dexSize = 0, jsonSize = 0; @@ -202,25 +217,31 @@ public: } void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override { - if (dexVector.empty() || json.empty()) return; + if (dexVector.empty()) return; - UpdateBuildFields(); + if (isGmsUnstable) { + UpdateBuildFields(); - if (spoofProvider || spoofSignature) { - injectDex(); - } else { - LOGD("Dex file won't be injected due spoofProvider and spoofSignature are false"); - } + if (spoofProvider || spoofSignature) { + injectDex(); + } else { + LOGD("Dex file won't be injected due spoofProvider and spoofSignature are false"); + } - if (spoofProps) { - if (!doHook()) { + if (spoofProps) { + if (!doHook()) { + dlclose(); + } + } else { dlclose(); } - } else { + } else if (isVending) { + doSpoofVending(); dlclose(); } json.clear(); + dexVector.clear(); dexVector.shrink_to_fit(); } @@ -232,20 +253,84 @@ public: private: zygisk::Api *api = nullptr; JNIEnv *env = nullptr; + bool isGmsUnstable = false; + bool isVending = false; std::vector dexVector; nlohmann::json json; bool spoofProps = true; bool spoofProvider = true; bool spoofSignature = false; + int spoofVendingSdk = 1; void dlclose() { LOGD("dlclose zygisk lib"); api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY); } + void doSpoofVending() { + if (spoofVendingSdk < 1) return; + int requestSdk = (spoofVendingSdk == 1) ? 32 : spoofVendingSdk; + int targetSdk; + int oldValue; + + jclass buildVersionClass = nullptr; + jfieldID sdkIntFieldID = nullptr; + + buildVersionClass = env->FindClass("android/os/Build$VERSION"); + if (buildVersionClass == nullptr) { + LOGE("Build.VERSION class not found"); + env->ExceptionClear(); + return; + } + + sdkIntFieldID = env->GetStaticFieldID(buildVersionClass, "SDK_INT", "I"); + if (sdkIntFieldID == nullptr) { + LOGE("SDK_INT field not found"); + env->ExceptionClear(); + env->DeleteLocalRef(buildVersionClass); + return; + } + + oldValue = env->GetStaticIntField(buildVersionClass, sdkIntFieldID); + targetSdk = std::min(oldValue, requestSdk); + + if (oldValue == targetSdk) { + env->DeleteLocalRef(buildVersionClass); + return; + } + + env->SetStaticIntField(buildVersionClass, sdkIntFieldID, targetSdk); + + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + LOGE("SDK_INT field not accessible (JNI Exception)"); + } else { + LOGE("[SDK_INT]: %d -> %d", oldValue, targetSdk); + } + + env->DeleteLocalRef(buildVersionClass); + } + void parseJSON() { if (json.empty()) return; + if (json.contains("spoofVendingSdk")) { + if (json["spoofVendingSdk"].is_string()) { + spoofVendingSdk = std::stoi(json["spoofVendingSdk"].get()); + } else if (json["spoofVendingSdk"].is_number_integer()) { + spoofVendingSdk = json["spoofVendingSdk"].get(); + } else { + LOGE("Error parsing spoofVendingSdk!"); + } + json.erase("spoofVendingSdk"); + } + + if (isVending) { + json.clear(); + return; + } + if (json.contains("DEVICE_INITIAL_SDK_INT")) { if (json["DEVICE_INITIAL_SDK_INT"].is_string()) { DEVICE_INITIAL_SDK_INT = json["DEVICE_INITIAL_SDK_INT"].get();