This commit is contained in:
chiteroman 2023-11-24 01:57:17 +01:00
parent 9774d68b3b
commit ed330ac37a
No known key found for this signature in database
GPG Key ID: 15FF53015D426D8E
5 changed files with 126 additions and 120 deletions

View File

@ -1,6 +1,2 @@
FLAGS := -DNDEBUG -g0 -Oz -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden -ffunction-sections -fdata-sections -flto=full -Wl,--icf=all -Wl,--exclude-libs,ALL -Wl,--gc-sections
APP_STL := none APP_STL := none
APP_CPPFLAGS := -std=c++20 APP_CPPFLAGS := -std=c++20 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden
APP_CFLAGS := $(FLAGS)
APP_LDFLAGS := $(FLAGS)

View File

@ -4,8 +4,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include <fstream> #include <filesystem>
#include <sstream>
#include "zygisk.hpp" #include "zygisk.hpp"
#include "shadowhook.h" #include "shadowhook.h"
@ -16,6 +15,10 @@
#define PROP_FILE_PATH "/data/adb/modules/playintegrityfix/pif.prop" #define PROP_FILE_PATH "/data/adb/modules/playintegrityfix/pif.prop"
#define DEFAULT_SECURITY_PATCH "2017-08-05"
#define DEFAULT_FIRST_API_LEVEL "23"
static std::string SECURITY_PATCH, FIRST_API_LEVEL; static std::string SECURITY_PATCH, FIRST_API_LEVEL;
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t); typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
@ -26,7 +29,7 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
if (cookie == nullptr || name == nullptr || value == nullptr || o_callback == nullptr) return; if (cookie == nullptr || name == nullptr || value == nullptr || o_callback == nullptr) return;
std::string_view prop(name); std::string prop(name);
if (prop.ends_with("api_level")) { if (prop.ends_with("api_level")) {
if (FIRST_API_LEVEL.empty()) { if (FIRST_API_LEVEL.empty()) {
@ -59,7 +62,7 @@ my_system_property_read_callback(const prop_info *pi, T_Callback callback, void
} }
static void doHook() { static void doHook() {
shadowhook_init(SHADOWHOOK_MODE_UNIQUE, true); shadowhook_init(SHADOWHOOK_MODE_UNIQUE, false);
void *handle = shadowhook_hook_sym_name( void *handle = shadowhook_hook_sym_name(
"libc.so", "libc.so",
"__system_property_read_callback", "__system_property_read_callback",
@ -82,86 +85,49 @@ public:
void preAppSpecialize(zygisk::AppSpecializeArgs *args) override { void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
auto rawProcess = env->GetStringUTFChars(args->nice_name, nullptr); auto rawProcess = env->GetStringUTFChars(args->nice_name, nullptr);
std::string process(rawProcess);
std::string_view process(rawProcess);
bool isGms = process.starts_with("com.google.android.gms");
isGmsUnstable = process.compare("com.google.android.gms.unstable") == 0;
env->ReleaseStringUTFChars(args->nice_name, rawProcess); env->ReleaseStringUTFChars(args->nice_name, rawProcess);
if (isGms) api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT); if (process.starts_with("com.google.android.gms")) {
if (!isGmsUnstable) { api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
int fd = api->connectCompanion(); if (process == "com.google.android.gms.unstable") {
long size = 0; isGmsUnstable = true;
read(fd, &size, sizeof(size));
if (size < 1) { auto rawDir = env->GetStringUTFChars(args->app_data_dir, nullptr);
close(fd); dir = std::string(rawDir);
LOGD("Couldn't read classes.dex from socket! File exists?"); env->ReleaseStringUTFChars(args->app_data_dir, rawDir);
return;
}
moduleDex.resize(size); auto fd = api->connectCompanion();
read(fd, moduleDex.data(), size);
int mapSize = 0; write(fd, dir.data(), dir.size());
read(fd, &mapSize, sizeof(mapSize));
if (mapSize < 1) { int temp;
close(fd); read(fd, &temp, sizeof(temp));
SECURITY_PATCH = "2017-08-05";
FIRST_API_LEVEL = "23";
LOGD("Couldn't read pif.prop from socket! File exists?");
return;
}
for (int i = 0; i < size; ++i) { close(fd);
int keyLenght, valueLenght;
std::string key, value;
read(fd, &keyLenght, sizeof(keyLenght)); return;
read(fd, &valueLenght, sizeof(valueLenght));
key.resize(keyLenght);
value.resize(valueLenght);
read(fd, key.data(), keyLenght);
read(fd, value.data(), valueLenght);
props[key] = value;
}
LOGD("Received from socket %d props!", static_cast<int>(props.size()));
for (const auto &item: props) {
if (item.first == "SECURITY_PATCH") {
SECURITY_PATCH = item.second;
} else if (item.first == "FIRST_API_LEVEL") {
FIRST_API_LEVEL = item.second;
} }
} }
close(fd); api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
} }
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override { void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
if (!isGmsUnstable) return; if (!isGmsUnstable) return;
readDexFile();
readPropsFile();
doHook(); doHook();
inject(); inject();
LOGD("clean"); clean();
moduleDex.clear();
moduleDex.shrink_to_fit();
props.clear();
} }
void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override { void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override {
@ -172,12 +138,85 @@ private:
zygisk::Api *api = nullptr; zygisk::Api *api = nullptr;
JNIEnv *env = nullptr; JNIEnv *env = nullptr;
bool isGmsUnstable = false; bool isGmsUnstable = false;
std::map<std::string, std::string> props; std::string dir;
std::vector<char> moduleDex; std::vector<char> moduleDex;
std::map<std::string, std::string> props;
void clean() {
dir.clear();
moduleDex.clear();
props.clear();
}
void readPropsFile() {
std::string f = dir + "/pif.prop";
FILE *file = fopen(f.c_str(), "r");
if (file == nullptr) {
SECURITY_PATCH = DEFAULT_SECURITY_PATCH;
FIRST_API_LEVEL = DEFAULT_FIRST_API_LEVEL;
LOGD("File pif.prop doesn't exist, using default values");
return;
}
char buffer[256];
while (fgets(buffer, sizeof(buffer), file)) {
char *rawKey = strtok(buffer, "=");
char *rawValue = strtok(nullptr, "=");
if (rawKey == nullptr) continue;
std::string key(rawKey);
std::string value(rawValue);
key.erase(std::remove_if(key.begin(), key.end(), [](unsigned char x) {
return std::isspace(x);
}), key.end());
value.erase(std::remove(value.begin(), value.end(), '\n'), value.end());
props[key] = value;
}
fclose(file);
std::filesystem::remove(f);
LOGD("Read %d props from file!", static_cast<int>(props.size()));
SECURITY_PATCH = props["SECURITY_PATCH"];
FIRST_API_LEVEL = props["FIRST_API_LEVEL"];
}
void readDexFile() {
std::string f = dir + "/classes.dex";
FILE *file = fopen(f.c_str(), "rb");
if (file == nullptr) {
LOGD("File classes.dex doesn't exist. This is weird... Report to @chiteroman");
return;
}
fseek(file, 0, SEEK_END);
long size = ftell(file);
fseek(file, 0, SEEK_SET);
char buffer[size];
fread(buffer, 1, size, file);
fclose(file);
std::filesystem::remove(f);
moduleDex.insert(moduleDex.end(), buffer, buffer + size);
}
void inject() { void inject() {
if (moduleDex.empty()) { if (moduleDex.empty()) {
LOGD("Dex not loaded in memory"); LOGD("ERROR! Dex in memory is empty!");
return; return;
} }
@ -223,56 +262,27 @@ private:
}; };
static void companion(int fd) { static void companion(int fd) {
std::ifstream dex(DEX_FILE_PATH, std::ios::binary | std::ios::ate); char buffer[256];
auto bytes = read(fd, buffer, sizeof(buffer));
long size = static_cast<long>(dex.tellg()); std::string file(buffer, bytes);
dex.seekg(std::ios::beg); LOGD("[ROOT] Read file: %s", file.c_str());
char buffer[size]; std::string dex = file + "/classes.dex";
dex.read(buffer, size); std::string prop = file + "/pif.prop";
dex.close(); if (std::filesystem::copy_file(DEX_FILE_PATH, dex,
std::filesystem::copy_options::overwrite_existing)) {
write(fd, &size, sizeof(size)); std::filesystem::permissions(dex, std::filesystem::perms::all);
write(fd, buffer, size);
std::ifstream prop(PROP_FILE_PATH);
if (prop.bad()) {
prop.close();
int i = 0;
write(fd, &i, sizeof(i));
return;
} }
std::map<std::string, std::string> props; if (std::filesystem::copy_file(PROP_FILE_PATH, prop,
std::filesystem::copy_options::overwrite_existing)) {
std::string line; std::filesystem::permissions(prop, std::filesystem::perms::all);
while (std::getline(prop, line)) {
std::istringstream iss(line);
std::string key, value;
if (std::getline(iss, key, '=') && std::getline(iss, value)) {
props[key] = value;
}
} }
prop.close(); int temp = 1;
write(fd, &temp, sizeof(temp));
int mapSize = static_cast<int>(props.size());
write(fd, &mapSize, sizeof(mapSize));
for (const auto &item: props) {
int keyLenght = static_cast<int>(item.first.size());
int valueLenght = static_cast<int>(item.second.size());
write(fd, &keyLenght, sizeof(keyLenght));
write(fd, &valueLenght, sizeof(valueLenght));
write(fd, item.first.data(), keyLenght);
write(fd, item.second.data(), valueLenght);
}
} }
REGISTER_ZYGISK_MODULE(PlayIntegrityFix) REGISTER_ZYGISK_MODULE(PlayIntegrityFix)

View File

@ -21,6 +21,7 @@ public final class EntryPoint {
} }
public static void addProp(String key, String value) { public static void addProp(String key, String value) {
if (key == null || value == null || key.isEmpty() || value.isEmpty()) return;
map.put(key, value); map.put(key, value);
LOG(String.format("Received from Zygisk lib: [%s] -> '%s'", key, value)); LOG(String.format("Received from Zygisk lib: [%s] -> '%s'", key, value));
} }

View File

@ -4,11 +4,10 @@ https://t.me/playintegrityfix
Also, if Google blacklist the fingerprint (again), you can post your custom pif.prop and I will update the module. Also, if Google blacklist the fingerprint (again), you can post your custom pif.prop and I will update the module.
# v13.4 # v13.5
- Custom resetprop utility! Thanks to @HuskyDG. - Remove custom resetprop.
- Don't write in GMS folder, everything stored in memory. (Issue from @osm0sis :D) - Fixes in code.
- Downgrade to Zygisk API 2.
- Should fix crashes.
This build includes 'pif.prop', you can modify it and use your custom props to pass Device verdict. This module will backup your pif.prop into adb root folder.
If you remove this file, module will use default props for attestation.

View File

@ -1,6 +1,6 @@
{ {
"version": "v13.4", "version": "v13.5",
"versionCode": 134, "versionCode": 135,
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v13.4/PlayIntegrityFix_v13.4.zip", "zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v13.5/PlayIntegrityFix_v13.5.zip",
"changelog": "https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/changelog.md" "changelog": "https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/changelog.md"
} }