Skip to content
Snippets Groups Projects
Unverified Commit ed330ac3 authored by chiteroman's avatar chiteroman
Browse files

v13.5

parent 9774d68b
No related branches found
No related tags found
No related merge requests found
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) \ No newline at end of file
APP_LDFLAGS := $(FLAGS)
\ No newline at end of file
...@@ -4,8 +4,7 @@ ...@@ -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 @@ ...@@ -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 ...@@ -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 ...@@ -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: ...@@ -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) {
int keyLenght, valueLenght;
std::string key, value;
read(fd, &keyLenght, sizeof(keyLenght));
read(fd, &valueLenght, sizeof(valueLenght));
key.resize(keyLenght); close(fd);
value.resize(valueLenght);
read(fd, key.data(), keyLenght); return;
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: ...@@ -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: ...@@ -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());
dex.seekg(std::ios::beg);
char buffer[size];
dex.read(buffer, size);
dex.close(); std::string file(buffer, bytes);
LOGD("[ROOT] Read file: %s", file.c_str());
write(fd, &size, sizeof(size)); std::string dex = file + "/classes.dex";
write(fd, buffer, size); std::string prop = file + "/pif.prop";
std::ifstream prop(PROP_FILE_PATH); if (std::filesystem::copy_file(DEX_FILE_PATH, dex,
std::filesystem::copy_options::overwrite_existing)) {
if (prop.bad()) { std::filesystem::permissions(dex, std::filesystem::perms::all);
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)
......
...@@ -21,6 +21,7 @@ public final class EntryPoint { ...@@ -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));
} }
......
...@@ -4,11 +4,10 @@ https://t.me/playintegrityfix ...@@ -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.
\ No newline at end of file If you remove this file, module will use default props for attestation.
\ No newline at end of file
{ {
"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"
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment