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

Release v13.4

parent 78dde206
No related branches found
No related tags found
No related merge requests found
-keep class es.chiteroman.playintegrityfix.EntryPoint {init();}
-keep class es.chiteroman.playintegrityfix.EntryPoint {public <methods>;}
-keep class es.chiteroman.playintegrityfix.CustomProvider
-keep class es.chiteroman.playintegrityfix.CustomKeyStoreSpi
\ No newline at end of file
......@@ -4,16 +4,13 @@
#include <string>
#include <vector>
#include <map>
#include <filesystem>
#include "zygisk.hpp"
#include "dobby.h"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF/Native", __VA_ARGS__)
static std::string API_LEVEL;
static std::string SECURITY_PATCH;
static std::string SECURITY_PATCH, FIRST_API_LEVEL;
#define DEX_FILE_PATH "/data/adb/modules/playintegrityfix/classes.dex"
......@@ -32,10 +29,10 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
std::string_view prop(name);
if (prop.ends_with("api_level")) {
if (API_LEVEL.empty()) {
if (FIRST_API_LEVEL.empty()) {
value = nullptr;
} else {
value = API_LEVEL.c_str();
value = FIRST_API_LEVEL.c_str();
}
} else if (prop.ends_with("security_patch")) {
if (SECURITY_PATCH.empty()) {
......@@ -62,49 +59,15 @@ my_system_property_read_callback(const prop_info *pi, T_Callback callback, void
return o_system_property_read_callback(pi, modify_callback, cookie);
}
static void parsePropsFile(const char *filename) {
LOGD("Proceed to parse '%s' file", filename);
FILE *file = fopen(filename, "r");
char line[256];
while (fgets(line, sizeof(line), file)) {
std::string key, value;
char *data = strtok(line, "=");
while (data) {
if (key.empty()) {
key = data;
} else {
value = data;
}
data = strtok(nullptr, "=");
}
key.erase(std::remove_if(key.begin(), key.end(),
[](unsigned char x) { return std::isspace(x); }), key.end());
value.erase(std::remove_if(value.begin(), value.end(),
[](unsigned char x) { return std::isspace(x); }), value.end());
if (key == "SECURITY_PATCH") {
SECURITY_PATCH = value;
LOGD("Set SECURITY_PATCH to '%s'", value.c_str());
} else if (key == "FIRST_API_LEVEL") {
API_LEVEL = value;
LOGD("Set API_LEVEL to '%s'", value.c_str());
}
key.clear();
key.shrink_to_fit();
value.clear();
value.shrink_to_fit();
static void doHook() {
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;
}
fclose(file);
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 {
......@@ -131,26 +94,26 @@ public:
return;
}
callbacks.clear();
API_LEVEL.clear();
API_LEVEL.shrink_to_fit();
int fd = api->connectCompanion();
SECURITY_PATCH.clear();
SECURITY_PATCH.shrink_to_fit();
int mapSize;
read(fd, &mapSize, sizeof(mapSize));
int fd = api->connectCompanion();
for (int i = 0; i < mapSize; ++i) {
int keyLenght, valueLenght;
std::string key, value;
auto rawDir = env->GetStringUTFChars(args->app_data_dir, nullptr);
propsFile = rawDir;
env->ReleaseStringUTFChars(args->app_data_dir, rawDir);
read(fd, &keyLenght, sizeof(keyLenght));
read(fd, &valueLenght, sizeof(valueLenght));
propsFile = propsFile + "/cache/pif.prop";
key.resize(keyLenght);
value.resize(valueLenght);
int strSize = static_cast<int>(propsFile.size());
read(fd, key.data(), keyLenght);
read(fd, value.data(), valueLenght);
write(fd, &strSize, sizeof(strSize));
write(fd, propsFile.data(), strSize);
props.insert({key, value});
}
long size;
read(fd, &size, sizeof(size));
......@@ -161,6 +124,16 @@ public:
close(fd);
moduleDex.insert(moduleDex.end(), buffer, buffer + size);
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;
}
}
}
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
......@@ -168,13 +141,12 @@ public:
doHook();
injectDex();
inject();
LOGD("clean");
propsFile.clear();
propsFile.shrink_to_fit();
moduleDex.clear();
moduleDex.shrink_to_fit();
props.clear();
}
void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override {
......@@ -185,25 +157,17 @@ private:
zygisk::Api *api = nullptr;
JNIEnv *env = nullptr;
bool isGmsUnstable = false;
std::string propsFile;
std::map<std::string, std::string> props;
std::vector<char> moduleDex;
void doHook() {
if (!propsFile.empty()) parsePropsFile(propsFile.c_str());
void *handle = DobbySymbolResolver("libc.so", "__system_property_read_callback");
if (handle == nullptr) {
LOGD("Couldn't find '__system_property_read_callback' handle. Report to @chiteroman");
void inject() {
if (moduleDex.empty()) {
LOGD("Dex not loaded in memory");
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);
}
void injectDex() {
if (moduleDex.empty()) {
LOGD("Dex not loaded in memory");
if (props.empty()) {
LOGD("No props loaded in memory");
return;
}
......@@ -229,28 +193,82 @@ private:
auto entryClassName = env->NewStringUTF("es.chiteroman.playintegrityfix.EntryPoint");
auto entryClassObj = env->CallObjectMethod(dexCl, loadClass, entryClassName);
LOGD("call init");
auto entryClass = (jclass) entryClassObj;
LOGD("call add prop");
auto addProp = env->GetStaticMethodID(entryClass, "addProp",
"(Ljava/lang/String;Ljava/lang/String;)V");
for (const auto &item: props) {
auto key = env->NewStringUTF(item.first.c_str());
auto value = env->NewStringUTF(item.second.c_str());
env->CallStaticVoidMethod(entryClass, addProp, key, value);
}
LOGD("call init");
auto entryInit = env->GetStaticMethodID(entryClass, "init", "()V");
env->CallStaticVoidMethod(entryClass, entryInit);
}
};
static void companion(int fd) {
int strSize;
read(fd, &strSize, sizeof(strSize));
static void parsePropsFile(int fd) {
LOGD("Proceed to parse '%s' file", PROP_FILE_PATH);
std::map<std::string, std::string> props;
FILE *file = fopen(PROP_FILE_PATH, "r");
std::string propsFile;
char line[256];
propsFile.resize(strSize);
read(fd, propsFile.data(), strSize);
while (fgets(line, sizeof(line), file)) {
std::filesystem::copy_file(PROP_FILE_PATH, propsFile,
std::filesystem::copy_options::overwrite_existing);
std::filesystem::permissions(propsFile, std::filesystem::perms::all);
std::string key, value;
char *data = strtok(line, "=");
while (data) {
if (key.empty()) {
key = data;
} else {
value = data;
}
data = strtok(nullptr, "=");
}
propsFile.clear();
propsFile.shrink_to_fit();
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.cend());
props.insert({key, value});
key.clear();
key.shrink_to_fit();
value.clear();
value.shrink_to_fit();
}
fclose(file);
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);
}
props.clear();
}
static void companion(int fd) {
parsePropsFile(fd);
FILE *dex = fopen(DEX_FILE_PATH, "rb");
......
......@@ -3,33 +3,26 @@ package es.chiteroman.playintegrityfix;
import android.os.Build;
import android.util.Log;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Field;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.KeyStoreSpi;
import java.security.Provider;
import java.security.Security;
import java.util.Properties;
import java.util.HashMap;
import java.util.Map;
public final class EntryPoint {
private static final Properties props = new Properties();
private static final File file = new File("/data/data/com.google.android.gms/cache/pif.prop");
private static final Map<String, String> map = new HashMap<>();
public static void init() {
try (Reader reader = new FileReader(file)) {
props.load(reader);
LOG("Loaded " + props.size() + " fields!");
} catch (IOException e) {
LOG("Couldn't load pif.prop file: " + e);
}
spoofDevice();
spoofProvider();
spoofDevice();
}
public static void addProp(String key, String value) {
map.put(key, value);
LOG(String.format("Received from Zygisk lib: [%s] -> '%s'", key, value));
}
private static void spoofProvider() {
......@@ -60,13 +53,13 @@ public final class EntryPoint {
}
public static void spoofDevice() {
setProp("PRODUCT", props.getProperty("PRODUCT", "bullhead"));
setProp("DEVICE", props.getProperty("DEVICE", "bullhead"));
setProp("MANUFACTURER", props.getProperty("MANUFACTURER", "LGE"));
setProp("BRAND", props.getProperty("BRAND", "google"));
setProp("MODEL", props.getProperty("MODEL", "Nexus 5X"));
setProp("FINGERPRINT", props.getProperty("FINGERPRINT", "google/bullhead/bullhead:8.0.0/OPR6.170623.013/4283548:user/release-keys"));
setVersionProp("SECURITY_PATCH", props.getProperty("SECURITY_PATCH", "2017-08-05"));
setProp("PRODUCT", map.get("PRODUCT"));
setProp("DEVICE", map.get("DEVICE"));
setProp("MANUFACTURER", map.get("MANUFACTURER"));
setProp("BRAND", map.get("BRAND"));
setProp("MODEL", map.get("MODEL"));
setProp("FINGERPRINT", map.get("FINGERPRINT"));
setVersionProp("SECURITY_PATCH", map.get("SECURITY_PATCH"));
}
private static void setProp(String name, String value) {
......
......@@ -4,6 +4,11 @@ https://t.me/playintegrityfix
Also, if Google blacklist the fingerprint (again), you can post your custom pif.prop and I will update the module.
# v13.3
# v13.4
- Spoof security patch and api level to DroidGuard.
\ No newline at end of file
- Custom resetprop utility! Thanks to @HuskyDG.
- Don't write in GMS folder, everything stored in memory. (Issue from @osm0sis :D)
- 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.
\ No newline at end of file
{
"version": "v13.3",
"versionCode": 133,
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v13.3/PlayIntegrityFix_v13.3.zip",
"version": "v13.4",
"versionCode": 134,
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v13.4/PlayIntegrityFix_v13.4.zip",
"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