Prepare v15.2

This commit is contained in:
chiteroman 2024-01-04 22:01:38 +01:00
parent 0b21f031de
commit 0a6f936074
7 changed files with 139 additions and 116 deletions

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/src/main/cpp/Dobby" vcs="Git" />
</component>
</project>

View File

@ -14,6 +14,7 @@ android {
packaging {
jniLibs {
excludes += "**/liblog.so"
excludes += "**/libdobby.so"
}
}
@ -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"
}
}
}
@ -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")
@ -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")
}

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.22.1)
project("playintegrityfix")
project(playintegrityfix)
find_package(cxx REQUIRED CONFIG)
@ -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)

View File

@ -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"
@ -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);
@ -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";
@ -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 *);
@ -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;
@ -87,68 +97,49 @@ public:
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);
std::string_view process(name);
if (name && strncmp(name, "com.google.android.gms", 22) == 0) {
bool isGms = process.starts_with("com.google.android.gms");
bool isGmsUnstable = process == "com.google.android.gms.unstable";
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
env->ReleaseStringUTFChars(args->nice_name, name);
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) {
dexVector.resize(dexSize);
read(fd, dexVector.data(), dexSize);
} else {
LOGD("Couldn't load classes.dex file in memory!");
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
goto end;
}
read(fd, &jsonSize, sizeof(long));
if (jsonSize > 0) {
jsonVector.resize(jsonSize);
read(fd, jsonVector.data(), jsonSize);
} else {
LOGD("Couldn't load pif.json file in memory!");
dexVector.clear();
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
goto end;
}
end:
close(fd);
goto clear;
}
if (!isGms) {
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
clear:
env->ReleaseStringUTFChars(args->nice_name, name);
}
if (!isGmsUnstable) {
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
if (dexVector.empty() || jsonVector.empty()) return;
long dexSize = 0, jsonSize = 0;
std::string jsonStr(jsonVector.cbegin(), jsonVector.cend());
nlohmann::json json = nlohmann::json::parse(jsonStr, nullptr, false, true);
int fd = api->connectCompanion();
read(fd, &dexSize, sizeof(long));
read(fd, &jsonSize, sizeof(long));
vector.resize(dexSize);
read(fd, vector.data(), dexSize);
char jsonBufer[jsonSize];
read(fd, jsonBufer, jsonSize);
close(fd);
std::string_view jsonStr(jsonBufer, jsonSize);
json = nlohmann::json::parse(jsonStr, nullptr, false, true);
if (json.contains("FIRST_API_LEVEL")) {
@ -180,6 +171,29 @@ public:
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");
@ -192,7 +206,7 @@ public:
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");
@ -208,8 +222,8 @@ public:
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 {
@ -219,50 +233,43 @@ public:
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;
std::ifstream dexFile(CLASSES_DEX, std::ios::in | std::ios::binary);
FILE *dexFile = fopen(CLASSES_DEX, "rb");
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;
}
std::vector<char> dexVector((std::istreambuf_iterator<char>(dexFile)),
std::istreambuf_iterator<char>());
long dexSize = dexVector.size();
std::ifstream jsonFile;
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;
}
std::vector<char> jsonVector((std::istreambuf_iterator<char>(jsonFile)),
std::istreambuf_iterator<char>());
long jsonSize = jsonVector.size();
write(fd, &dexSize, sizeof(long));
write(fd, dexVector.data(), dexSize);
FILE *jsonFile = fopen(PIF_JSON, "r");
if (jsonFile == nullptr) {
jsonFile = fopen(PIF_JSON_2, "r");
}
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);
}
write(fd, &jsonSize, sizeof(long));
write(fd, dexVector.data(), dexSize);
write(fd, jsonVector.data(), jsonSize);
}

View File

@ -14,8 +14,9 @@ public final class CustomProvider extends Provider {
@Override
public synchronized Service getService(String type, String algorithm) {
EntryPoint.LOG(String.format("[Service] Type: '%s' | Algorithm: '%s'", type, algorithm));
EntryPoint.spoofDevice();
if ("KeyStore".equals(type)) EntryPoint.spoofDevice();
return super.getService(type, algorithm);
}

View File

@ -1,7 +1,7 @@
id=playintegrityfix
name=Play Integrity Fix
version=v15.1
versionCode=15100
version=v15.2
versionCode=15200
author=chiteroman
description=Universal modular fix for Play Integrity (and SafetyNet) on devices running Android 8+.
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json

View File

@ -7,5 +7,6 @@
"FINGERPRINT": "acer/c01_ww/acer_c01:7.1.1/NMF26F/1521514970:user/release-keys",
"SECURITY_PATCH": "2018-04-01",
"FIRST_API_LEVEL": 24,
"ID": "NMF26F",
"FORCE_BASIC_ATTESTATION": true
}