Skip to content

Commit

Permalink
New update :D
Browse files Browse the repository at this point in the history
  • Loading branch information
chiteroman committed Nov 30, 2023
1 parent bc1ef14 commit e86246a
Show file tree
Hide file tree
Showing 89 changed files with 325 additions and 16,286 deletions.
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
.externalNativeBuild
.cxx
local.properties
/module/classes.dex
/module/pif.json
/module/zygisk/*
/out/*
/module_resetprop/zygisk/*
*.dex
*.zip
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "app/src/main/cpp/libcxx"]
path = app/src/main/cpp/libcxx
url = https://github.com/topjohnwu/libcxx.git
[submodule "app/src/main/cpp/Dobby"]
path = app/src/main/cpp/Dobby
url = https://github.com/jmpews/Dobby.git
2 changes: 1 addition & 1 deletion .idea/vcs.xml

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

64 changes: 57 additions & 7 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ android {
ndkVersion = "26.1.10909125"
buildToolsVersion = "34.0.0"

buildFeatures {
prefab = true
}

packaging {
jniLibs {
excludes += "**/libdobby.so"
}
}

defaultConfig {
applicationId = "es.chiteroman.playintegrityfix"
minSdk = 26
Expand All @@ -16,10 +26,20 @@ android {
versionName = "1.0"

externalNativeBuild {
ndk {
jobs = Runtime.getRuntime().availableProcessors()
abiFilters += "armeabi-v7a"
abiFilters += "arm64-v8a"
cmake {
arguments += "-DANDROID_STL=none"
arguments += "-DCMAKE_BUILD_TYPE=MinSizeRel"

cFlags += "-fvisibility=hidden"
cFlags += "-fvisibility-inlines-hidden"
cFlags += "-flto"

cppFlags += "-std=c++20"
cppFlags += "-fno-exceptions"
cppFlags += "-fno-rtti"
cppFlags += "-fvisibility=hidden"
cppFlags += "-fvisibility-inlines-hidden"
cppFlags += "-flto"
}
}
}
Expand All @@ -38,12 +58,17 @@ android {
}

externalNativeBuild {
ndkBuild {
path = file("src/main/cpp/Android.mk")
cmake {
path = file("src/main/cpp/CMakeLists.txt")
version = "3.22.1"
}
}
}

dependencies {
implementation("dev.rikka.ndk.thirdparty:cxx:1.2.0")
}

tasks.register("copyFiles") {
doLast {
val moduleFolder = project.rootDir.resolve("module")
Expand All @@ -60,6 +85,22 @@ tasks.register("copyFiles") {
}
}

tasks.register("copyFiles-resetprop") {
doLast {
val moduleFolder = project.rootDir.resolve("module_resetprop")
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)

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>("zip") {
dependsOn("copyFiles")

Expand All @@ -69,6 +110,15 @@ tasks.register<Zip>("zip") {
from(project.rootDir.resolve("module"))
}

tasks.register<Zip>("zip-resetprop") {
dependsOn("copyFiles")

archiveFileName.set("PlayIntegrityFix-resetprop.zip")
destinationDirectory.set(project.rootDir.resolve("out"))

from(project.rootDir.resolve("module_resetprop"))
}

afterEvaluate {
tasks["assembleRelease"].finalizedBy("copyFiles", "zip")
tasks["assembleRelease"].finalizedBy("copyFiles", "zip", "copyFiles-resetprop", "zip-resetprop")
}
33 changes: 0 additions & 33 deletions app/src/main/cpp/Android.mk

This file was deleted.

3 changes: 0 additions & 3 deletions app/src/main/cpp/Application.mk

This file was deleted.

15 changes: 15 additions & 0 deletions app/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.22.1)

project(playintegrityfix)

find_package(cxx REQUIRED CONFIG)

link_libraries(cxx::cxx)

add_library(${CMAKE_PROJECT_NAME} SHARED main.cpp)

add_subdirectory(Dobby)

SET_OPTION(Plugin.Android.BionicLinkerUtil ON)

target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE log dobby_static)
1 change: 1 addition & 0 deletions app/src/main/cpp/Dobby
Submodule Dobby added at b0176d
1 change: 0 additions & 1 deletion app/src/main/cpp/libcxx
Submodule libcxx deleted from 12c8f4
89 changes: 26 additions & 63 deletions app/src/main/cpp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,37 @@
#include <unistd.h>

#include "zygisk.hpp"
#include "shadowhook.h"
#include "dobby.h"
#include "json.hpp"

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF/Native", __VA_ARGS__)

#define DEX_FILE_PATH "/data/adb/modules/playintegrityfix/classes.dex"

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

#define CUSTOM_JSON_FILE_PATH "/data/adb/modules/playintegrityfix/custom.pif.json"

static std::string FIRST_API_LEVEL, SECURITY_PATCH;
static std::string FIRST_API_LEVEL;

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

static std::map<void *, T_Callback> callbacks;
static volatile 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;

std::string_view prop(name);
if (cookie == nullptr || name == nullptr || value == nullptr || o_callback == nullptr) return;

if (prop.ends_with("api_level")) {
if (strcmp(name, "ro.product.first_api_level") == 0) {
if (FIRST_API_LEVEL.empty()) {
LOGD("FIRST_API_LEVEL is empty, ignoring it...");
} else if (FIRST_API_LEVEL == "nullptr") {
value = nullptr;
LOGD("[ro.product.first_api_level]: %s -> 23", value);
return o_callback(cookie, name, "23", serial);
} else {
value = FIRST_API_LEVEL.c_str();
const char *newValue = FIRST_API_LEVEL.c_str();
LOGD("[ro.product.first_api_level]: %s -> %s", value, newValue);
return o_callback(cookie, name, newValue, serial);
}
LOGD("[%s] -> %s", name, value);
} else if (prop.ends_with("security_patch")) {
if (SECURITY_PATCH.empty()) {
LOGD("SECURITY_PATCH is empty, ignoring it...");
} else {
value = SECURITY_PATCH.c_str();
}
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 @@ -56,23 +43,19 @@ 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);
}

static void doHook() {
shadowhook_init(SHADOWHOOK_MODE_UNIQUE, false);
void *handle = shadowhook_hook_sym_name(
"libc.so",
"__system_property_read_callback",
reinterpret_cast<void *>(my_system_property_read_callback),
reinterpret_cast<void **>(&o_system_property_read_callback)
);
void *handle = DobbySymbolResolver(nullptr, "__system_property_read_callback");
if (handle == nullptr) {
LOGD("Couldn't find '__system_property_read_callback' handle. Report to @chiteroman");
return;
}
LOGD("Found '__system_property_read_callback' handle at %p", handle);
DobbyHook(handle, (void *) my_system_property_read_callback,
(void **) &o_system_property_read_callback);
}

class PlayIntegrityFix : public zygisk::ModuleBase {
Expand All @@ -85,16 +68,14 @@ class PlayIntegrityFix : public zygisk::ModuleBase {
void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
bool isGms = false, isGmsUnstable = false;

auto rawProcess = env->GetStringUTFChars(args->nice_name, nullptr);

if (rawProcess) {
std::string_view process(rawProcess);
auto process = env->GetStringUTFChars(args->nice_name, nullptr);

isGms = process.starts_with("com.google.android.gms");
isGmsUnstable = process.compare("com.google.android.gms.unstable") == 0;
if (process) {
isGms = strncmp(process, "com.google.android.gms", 22) == 0;
isGmsUnstable = strcmp(process, "com.google.android.gms.unstable") == 0;
}

env->ReleaseStringUTFChars(args->nice_name, rawProcess);
env->ReleaseStringUTFChars(args->nice_name, process);

if (!isGms) {
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
Expand Down Expand Up @@ -170,22 +151,11 @@ class PlayIntegrityFix : public zygisk::ModuleBase {
nlohmann::json json;

void readJson() {
if (json.contains("SECURITY_PATCH")) {
if (json["SECURITY_PATCH"].is_null()) {
LOGD("Key SECURITY_PATCH is null!");
} else if (json["SECURITY_PATCH"].is_string()) {
SECURITY_PATCH = json["SECURITY_PATCH"].get<std::string>();
} else {
LOGD("Error parsing SECURITY_PATCH!");
}
} else {
LOGD("Key SECURITY_PATCH doesn't exist in JSON file!");
}
LOGD("JSON contains %d keys!", static_cast<int>(json.size()));

if (json.contains("FIRST_API_LEVEL")) {
if (json["FIRST_API_LEVEL"].is_null()) {
LOGD("Key FIRST_API_LEVEL is null!");
FIRST_API_LEVEL = "nullptr";
} else if (json["FIRST_API_LEVEL"].is_string()) {
FIRST_API_LEVEL = json["FIRST_API_LEVEL"].get<std::string>();
} else {
Expand Down Expand Up @@ -220,15 +190,10 @@ class PlayIntegrityFix : public zygisk::ModuleBase {

auto entryClass = (jclass) entryClassObj;

LOGD("read json");
auto readProps = env->GetStaticMethodID(entryClass, "readJson",
"(Ljava/lang/String;)V");
auto javaStr = env->NewStringUTF(json.dump().c_str());
env->CallStaticVoidMethod(entryClass, readProps, javaStr);

LOGD("call init");
auto entryInit = env->GetStaticMethodID(entryClass, "init", "()V");
env->CallStaticVoidMethod(entryClass, entryInit);
auto entryInit = env->GetStaticMethodID(entryClass, "init", "(Ljava/lang/String;)V");
auto javaStr = env->NewStringUTF(json.dump().c_str());
env->CallStaticVoidMethod(entryClass, entryInit, javaStr);
}
};

Expand All @@ -249,9 +214,7 @@ static void companion(int fd) {
fclose(dex);
}

FILE *json = fopen(CUSTOM_JSON_FILE_PATH, "r");
if (!json)
FILE *json = fopen(JSON_FILE_PATH, "r");
FILE *json = fopen(JSON_FILE_PATH, "r");

if (json) {
fseek(json, 0, SEEK_END);
Expand Down
Loading

0 comments on commit e86246a

Please sign in to comment.