Skip to content

Commit

Permalink
Prepare v15.2
Browse files Browse the repository at this point in the history
  • Loading branch information
chiteroman committed Jan 4, 2024
1 parent 0b21f03 commit 0a6f936
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 108 deletions.
7 changes: 0 additions & 7 deletions .idea/vcs.xml

This file was deleted.

37 changes: 30 additions & 7 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ android {

packaging {
jniLibs {
excludes += "**/liblog.so"
excludes += "**/libdobby.so"
}
}
Expand All @@ -22,19 +23,22 @@ android {
applicationId = "es.chiteroman.playintegrityfix"
minSdk = 26
targetSdk = 34
versionCode = 1
versionName = "1.0"
versionCode = 15200
versionName = "v15.2"

externalNativeBuild {
cmake {
arguments += "-DANDROID_STL=none"
arguments += "-DCMAKE_BUILD_TYPE=Release"
arguments += "-DCMAKE_CXX_STANDARD=20"
arguments += "-DCMAKE_CXX_STANDARD_REQUIRED=True"
arguments += "-DCMAKE_CXX_EXTENSIONS=False"
arguments += "-DCMAKE_CXX_VISIBILITY_PRESET=hidden"
arguments += "-DCMAKE_VISIBILITY_INLINES_HIDDEN=True"
arguments += "-DPlugin.Android.BionicLinkerUtil=ON"

cppFlags += "-std=c++20"
cppFlags += "-fno-exceptions"
cppFlags += "-fno-rtti"
cppFlags += "-fvisibility=hidden"
cppFlags += "-fvisibility-inlines-hidden"
}
}
}
Expand Down Expand Up @@ -64,7 +68,26 @@ dependencies {
implementation("dev.rikka.ndk.thirdparty:cxx:1.2.0")
}

tasks.register("updateModuleProp") {
doLast {
val versionName = project.android.defaultConfig.versionName
val versionCode = project.android.defaultConfig.versionCode

val modulePropFile = project.rootDir.resolve("module/module.prop")

var content = modulePropFile.readText()

content = content.replace(Regex("version=.*"), "version=$versionName")
content = content.replace(Regex("versionCode=.*"), "versionCode=$versionCode")

modulePropFile.writeText(content)
}
}


tasks.register("copyFiles") {
dependsOn("updateModuleProp")

doLast {
val moduleFolder = project.rootDir.resolve("module")
val dexFile = project.layout.buildDirectory.get().asFile.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex")
Expand All @@ -83,12 +106,12 @@ tasks.register("copyFiles") {
tasks.register<Zip>("zip") {
dependsOn("copyFiles")

archiveFileName.set("PlayIntegrityFix.zip")
archiveFileName.set("PlayIntegrityFix_${project.android.defaultConfig.versionName}.zip")
destinationDirectory.set(project.rootDir.resolve("out"))

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

afterEvaluate {
tasks["assembleRelease"].finalizedBy("copyFiles", "zip")
tasks["assembleRelease"].finalizedBy("updateModuleProp", "copyFiles", "zip")
}
4 changes: 1 addition & 3 deletions app/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.22.1)

project("playintegrityfix")
project(playintegrityfix)

find_package(cxx REQUIRED CONFIG)

Expand All @@ -10,6 +10,4 @@ add_library(${CMAKE_PROJECT_NAME} SHARED module.cpp)

add_subdirectory(Dobby)

SET_OPTION(Plugin.Android.BionicLinkerUtil ON)

target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE log dobby_static)
183 changes: 95 additions & 88 deletions app/src/main/cpp/module.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#include <android/log.h>
#include <sys/system_properties.h>
#include <unistd.h>

#include <fstream>
#include <filesystem>
#include "zygisk.hpp"
#include "dobby.h"
#include "json.hpp"
Expand All @@ -14,15 +15,17 @@

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

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

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

static T_Callback o_callback = nullptr;
static std::map<void *, T_Callback> callbacks;

static void modify_callback(void *cookie, const char *name, const char *value, uint32_t serial) {

if (cookie == nullptr || name == nullptr || o_callback == nullptr) return;
if (cookie == nullptr || name == nullptr || value == nullptr ||
!callbacks.contains(cookie))
return;

std::string_view prop(name);

Expand All @@ -40,6 +43,13 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
value = FIRST_API_LEVEL.c_str();
}

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

if (!BUILD_ID.empty()) {

value = BUILD_ID.c_str();
}

} else if (prop == "sys.usb.state") {

value = "none";
Expand All @@ -50,7 +60,7 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
LOGD("[%s] -> %s", name, value);
}

return o_callback(cookie, name, value, serial);
return callbacks[cookie](cookie, name, value, serial);
}

static void (*o_system_property_read_callback)(const prop_info *, T_Callback, void *);
Expand All @@ -60,12 +70,12 @@ 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);
}
o_callback = callback;
callbacks[cookie] = callback;
return o_system_property_read_callback(pi, modify_callback, cookie);
}

static void doHook() {
void *handle = DobbySymbolResolver(nullptr, "__system_property_read_callback");
void *handle = DobbySymbolResolver("libc.so", "__system_property_read_callback");
if (handle == nullptr) {
LOGD("Couldn't find '__system_property_read_callback' handle. Report to @chiteroman");
return;
Expand All @@ -87,68 +97,49 @@ class PlayIntegrityFix : public zygisk::ModuleBase {

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

if (args->is_child_zygote && *args->is_child_zygote) {
auto name = env->GetStringUTFChars(args->nice_name, nullptr);

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

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

if (name && strncmp(name, "com.google.android.gms", 22) == 0) {

api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);

if (strcmp(name, "com.google.android.gms.unstable") == 0) {

long dexSize = 0, jsonSize = 0;
int fd = api->connectCompanion();

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

if (dexSize > 0) {
std::string_view process(name);

dexVector.resize(dexSize);
read(fd, dexVector.data(), dexSize);
bool isGms = process.starts_with("com.google.android.gms");
bool isGmsUnstable = process == "com.google.android.gms.unstable";

} else {
env->ReleaseStringUTFChars(args->nice_name, name);

LOGD("Couldn't load classes.dex file in memory!");
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
goto end;
}
if (!isGms) {
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}

read(fd, &jsonSize, sizeof(long));
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);

if (jsonSize > 0) {
if (!isGmsUnstable) {
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}

jsonVector.resize(jsonSize);
read(fd, jsonVector.data(), jsonSize);
long dexSize = 0, jsonSize = 0;

} else {
int fd = api->connectCompanion();

LOGD("Couldn't load pif.json file in memory!");
dexVector.clear();
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
goto end;
}
read(fd, &dexSize, sizeof(long));
read(fd, &jsonSize, sizeof(long));

end:
close(fd);
goto clear;
}
}
vector.resize(dexSize);
read(fd, vector.data(), dexSize);

api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
char jsonBufer[jsonSize];
read(fd, jsonBufer, jsonSize);

clear:
env->ReleaseStringUTFChars(args->nice_name, name);
}
close(fd);

void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
if (dexVector.empty() || jsonVector.empty()) return;

std::string jsonStr(jsonVector.cbegin(), jsonVector.cend());
nlohmann::json json = nlohmann::json::parse(jsonStr, nullptr, false, true);
std::string_view jsonStr(jsonBufer, jsonSize);
json = nlohmann::json::parse(jsonStr, nullptr, false, true);

if (json.contains("FIRST_API_LEVEL")) {

Expand Down Expand Up @@ -180,6 +171,29 @@ class PlayIntegrityFix : public zygisk::ModuleBase {
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>();
}

} else {

LOGD("JSON file doesn't contain ID/BUILD_ID keys :(");
}
}

void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
if (vector.empty() || json.empty()) return;

doHook();

LOGD("get system classloader");
Expand All @@ -192,7 +206,7 @@ class PlayIntegrityFix : public zygisk::ModuleBase {
auto dexClClass = env->FindClass("dalvik/system/InMemoryDexClassLoader");
auto dexClInit = env->GetMethodID(dexClClass, "<init>",
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
auto buffer = env->NewDirectByteBuffer(dexVector.data(), dexVector.size());
auto buffer = env->NewDirectByteBuffer(vector.data(), vector.size());
auto dexCl = env->NewObject(dexClClass, dexClInit, buffer, systemClassLoader);

LOGD("load class");
Expand All @@ -208,8 +222,8 @@ class PlayIntegrityFix : public zygisk::ModuleBase {
auto str = env->NewStringUTF(json.dump().c_str());
env->CallStaticVoidMethod(entryClass, entryInit, str);

dexVector.clear();
jsonVector.clear();
vector.clear();
json.clear();
}

void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override {
Expand All @@ -219,50 +233,43 @@ class PlayIntegrityFix : public zygisk::ModuleBase {
private:
zygisk::Api *api = nullptr;
JNIEnv *env = nullptr;
std::vector<char> dexVector, jsonVector;
std::vector<char> vector;
nlohmann::json json;
};

static void companion(int fd) {
long dexSize = 0, jsonSize = 0;
std::vector<char> dexVector, jsonVector;

FILE *dexFile = fopen(CLASSES_DEX, "rb");
std::ifstream dexFile(CLASSES_DEX, std::ios::in | std::ios::binary);

if (dexFile) {

fseek(dexFile, 0, SEEK_END);
dexSize = ftell(dexFile);
fseek(dexFile, 0, SEEK_SET);

dexVector.resize(dexSize);
fread(dexVector.data(), 1, dexSize, dexFile);

fclose(dexFile);
if (!dexFile) {
long i = 0;
write(fd, &i, sizeof(i));
return;
}

write(fd, &dexSize, sizeof(long));
write(fd, dexVector.data(), dexSize);
std::vector<char> dexVector((std::istreambuf_iterator<char>(dexFile)),
std::istreambuf_iterator<char>());
long dexSize = dexVector.size();

FILE *jsonFile = fopen(PIF_JSON, "r");
std::ifstream jsonFile;

if (jsonFile == nullptr) {

jsonFile = fopen(PIF_JSON_2, "r");
if (std::filesystem::exists(PIF_JSON)) {
jsonFile = std::ifstream(PIF_JSON, std::ios::in);
} else if (std::filesystem::exists(PIF_JSON_2)) {
jsonFile = std::ifstream(PIF_JSON_2, std::ios::in);
} else {
long i = 0;
write(fd, &i, sizeof(i));
return;
}

if (jsonFile) {

fseek(jsonFile, 0, SEEK_END);
jsonSize = ftell(jsonFile);
fseek(jsonFile, 0, SEEK_SET);

jsonVector.resize(jsonSize);
fread(jsonVector.data(), 1, jsonSize, jsonFile);

fclose(jsonFile);
}
std::vector<char> jsonVector((std::istreambuf_iterator<char>(jsonFile)),
std::istreambuf_iterator<char>());
long jsonSize = jsonVector.size();

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

write(fd, dexVector.data(), dexSize);
write(fd, jsonVector.data(), jsonSize);
}

Expand Down
Loading

0 comments on commit 0a6f936

Please sign in to comment.