Skip to content

Commit

Permalink
v15.9.8
Browse files Browse the repository at this point in the history
  • Loading branch information
chiteroman committed May 16, 2024
1 parent 9e2b59e commit 763607e
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 88 deletions.
10 changes: 10 additions & 0 deletions .idea/deploymentTargetSelector.xml

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

1 change: 0 additions & 1 deletion .idea/misc.xml

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

10 changes: 3 additions & 7 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ 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 @@ -92,10 +90,8 @@ 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
125 changes: 62 additions & 63 deletions app/src/main/cpp/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <android/log.h>
#include <sys/system_properties.h>
#include <unistd.h>
#include <regex>
#include "dobby.h"
#include "json.hpp"
#include "zygisk.hpp"
Expand All @@ -13,7 +14,7 @@

#define PIF_JSON_DEFAULT "/data/adb/modules/playintegrityfix/pif.json"

static nlohmann::json json;
static nlohmann::json PROPS;

typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);

Expand All @@ -23,35 +24,20 @@ static void modify_callback(void *cookie, const char *name, const char *value, u

if (cookie == nullptr || name == nullptr || value == nullptr || o_callback == nullptr) return;

std::string_view prop(name);
std::string prop(name);

if (prop.ends_with("security_patch")) {

if (json.contains("SECURITY_PATCH")) {
if (json["SECURITY_PATCH"].is_string()) {
value = json["SECURITY_PATCH"].get<std::string>().c_str();
for (auto &[key, val]: PROPS.items()) {
if (key.starts_with('*')) {
if (prop.ends_with(key.substr(1))) {
value = val.get<std::string>().c_str();
break;
}
}

} else if (prop.ends_with("api_level")) {

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 == key) {
value = val.get<std::string>().c_str();
break;
}
}

} else if (prop.ends_with("build.id")) {

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") {

value = "none";
}

if (!prop.starts_with("persist") && !prop.starts_with("cache") && !prop.starts_with("debug")) {
Expand Down Expand Up @@ -92,64 +78,76 @@ class PlayIntegrityFix : public zygisk::ModuleBase {

void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {

if (args != nullptr) {

auto dir = env->GetStringUTFChars(args->app_data_dir, nullptr);

if (dir != nullptr) {
if (!args) {
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}

bool isGms = std::string_view(dir).ends_with("/com.google.android.gms");
const char *rawDir = env->GetStringUTFChars(args->app_data_dir, nullptr);

env->ReleaseStringUTFChars(args->app_data_dir, dir);
if (!rawDir) {
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}

if (isGms) {
const char *rawName = env->GetStringUTFChars(args->nice_name, nullptr);

api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
if (!rawName) {
env->ReleaseStringUTFChars(args->app_data_dir, rawDir);
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}

auto name = env->GetStringUTFChars(args->nice_name, nullptr);
std::string dir(rawDir);
std::string name(rawName);

if (name != nullptr) {
env->ReleaseStringUTFChars(args->app_data_dir, rawDir);
env->ReleaseStringUTFChars(args->nice_name, rawName);

bool isGmsUnstable =
std::string_view(name) == "com.google.android.gms.unstable";
if (!dir.ends_with("/com.google.android.gms")) {
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}

env->ReleaseStringUTFChars(args->nice_name, name);
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);

if (isGmsUnstable) {
if (name != "com.google.android.gms.unstable") {
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}

long dexSize = 0, jsonSize = 0;
long dexSize = 0, jsonSize = 0;

int fd = api->connectCompanion();
int fd = api->connectCompanion();

read(fd, &dexSize, sizeof(long));
read(fd, &jsonSize, sizeof(long));
read(fd, &dexSize, sizeof(long));
read(fd, &jsonSize, sizeof(long));

LOGD("Dex file size: %ld", dexSize);
LOGD("Json file size: %ld", jsonSize);
LOGD("Dex file size: %ld", dexSize);
LOGD("Json file size: %ld", jsonSize);

if (dexSize > 0 && jsonSize > 0) {
if (dexSize < 1 || jsonSize < 1) {
close(fd);
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}

dexVector.resize(dexSize);
read(fd, dexVector.data(), dexSize);
dexVector.resize(dexSize);
read(fd, dexVector.data(), dexSize);

std::vector<uint8_t> jsonVector;
std::vector<uint8_t> jsonVector;

jsonVector.resize(jsonSize);
read(fd, jsonVector.data(), jsonSize);
jsonVector.resize(jsonSize);
read(fd, jsonVector.data(), jsonSize);

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

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

return;
}
}
}
}
if (json.contains("PROPS")) {
PROPS = json["PROPS"];
json.erase("PROPS");
}

api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
}

void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
Expand All @@ -168,6 +166,7 @@ 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
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.security.Key;
import java.security.KeyStoreException;
import java.security.KeyStoreSpi;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.Locale;
Expand All @@ -22,13 +24,32 @@ public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmExc
return keyStoreSpi.engineGetKey(alias, password);
}

private static String getProcessName() {
try {
Class<?> activityThread = Class.forName("android.app.ActivityThread");

Method method = activityThread.getDeclaredMethod("currentProcessName");

method.setAccessible(true);

return (String) method.invoke(null);

} catch (Throwable t) {
EntryPoint.LOG(t.toString());
}
return null;
}

@Override
public Certificate[] engineGetCertificateChain(String alias) {

for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getClassName().toLowerCase(Locale.US).contains("droidguard")) {
throw new UnsupportedOperationException();
}
boolean droidGuard = Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch(e -> e.getClassName().toLowerCase(Locale.US).contains("droidguard"));

String processName = getProcessName();

if (processName != null && droidGuard && processName.equals("com.google.android.gms.unstable")) {
EntryPoint.LOG("DroidGuard call detected. Throw exception!");
throw new UnsupportedOperationException();
}

return keyStoreSpi.engineGetCertificateChain(alias);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ public CustomProvider(Provider provider) {
public synchronized Service getService(String type, String algorithm) {
EntryPoint.LOG(String.format("Service: '%s' | Algorithm: '%s'", type, algorithm));

EntryPoint.spoofFields();
Thread t = new Thread(EntryPoint::spoofFields);
t.setDaemon(true);
t.start();

return super.getService(type, algorithm);
}
Expand Down
6 changes: 4 additions & 2 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ If not, try removing /data/adb/pif.json file.
Donations:
https://www.paypal.com/paypalme/chiteroman

# v15.9.7
# v15.9.8

- Improve code detecting attestation extensions.
- MEETS_DEVICE_INTEGRITY is green again ✅
- Refine code
- You can define your own native props in pif.json!
25 changes: 18 additions & 7 deletions module/pif.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
{
"PRODUCT": "griffin_retcn",
"DEVICE": "griffin",
"MANUFACTURER": "motorola",
"MODEL": "XT1575",
"FINGERPRINT": "motorola/clark_retus/clark:6.0/MPHS24.49-18-8/4:user/release-keys",
"BRAND": "motorola",
"MODEL": "XT1650-05",
"FINGERPRINT": "motorola/griffin_retcn/griffin:6.0.1/MCC24.246-37/42:user/release-keys",
"SECURITY_PATCH": "2016-07-01",
"ID": "MCC24.246-37",
"FIRST_API_LEVEL": 21
"PRODUCT": "clark_retus",
"DEVICE": "clark",
"RELEASE": "6.0",
"ID": "MPHS24.49-18-8",
"INCREMENTAL": "4",
"TYPE": "user",
"TAGS": "release-keys",
"SECURITY_PATCH": "2016-09-01",
"PROPS": {
"*api_level": "25",
"*.security_patch": "2016-09-01",
"*.build.id": "MPHS24.49-18-8",
"*.fingerprint": "motorola/clark_retus/clark:6.0/MPHS24.49-18-8/4:user/release-keys",
"sys.usb.state": "none",
"ro.secureboot.lockstate": "locked"
}

This comment has been minimized.

Copy link
@wedarobi

wedarobi May 16, 2024

Isn't this curly bracket is unnecessary and breaks the .json format?

https://en.wikipedia.org/wiki/JSON#Syntax

}
6 changes: 3 additions & 3 deletions update.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": "v15.9.7",
"versionCode": 15970,
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v15.9.7/PlayIntegrityFix_v15.9.7.zip",
"version": "v15.9.8",
"versionCode": 15980,
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v15.9.8/PlayIntegrityFix_v15.9.8.zip",
"changelog": "https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/changelog.md"
}

1 comment on commit 763607e

@masemoel
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Banned

Please sign in to comment.