This commit is contained in:
chiteroman 2023-12-22 23:44:18 +01:00
parent c7e3d35e04
commit 7d04e447f1
No known key found for this signature in database
GPG Key ID: 19171A27D600CC72
9 changed files with 24839 additions and 90 deletions

View File

@ -30,11 +30,16 @@ android {
arguments += "-DANDROID_STL=none"
arguments += "-DCMAKE_BUILD_TYPE=MinSizeRel"
cFlags += "-fvisibility=hidden"
cFlags += "-fvisibility-inlines-hidden"
cFlags += "-flto=full"
cppFlags += "-std=c++20"
cppFlags += "-fno-exceptions"
cppFlags += "-fno-rtti"
cppFlags += "-fvisibility=hidden"
cppFlags += "-fvisibility-inlines-hidden"
cppFlags += "-flto=full"
}
}
}

24765
app/src/main/cpp/json.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@
#include "zygisk.hpp"
#include "dobby.h"
#include "json.hpp"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF/Native", __VA_ARGS__)
@ -12,7 +13,7 @@
#define PIF_JSON "/data/adb/pif.json"
#define PIF_PROP "/data/adb/pif.prop"
static std::string FIRST_API_LEVEL;
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
@ -24,9 +25,12 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
if (std::string_view(name).ends_with("api_level")) {
value = "23";
if (!FIRST_API_LEVEL.empty()) {
value = FIRST_API_LEVEL.c_str();
LOGD("Set '%s' to '%s'", name, value);
}
}
return o_callback(cookie, name, value, serial);
}
@ -104,8 +108,6 @@ public:
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
if (dir.empty()) return;
doHook();
std::string classesDex(dir + "/classes.dex");
FILE *dexFile = fopen(classesDex.c_str(), "rb");
@ -120,6 +122,34 @@ public:
fclose(dexFile);
doHook();
std::string pifJson(dir + "/pif.json");
FILE *jsonFile = fopen(pifJson.c_str(), "r");
nlohmann::json json = nlohmann::json::parse(jsonFile, nullptr, false, true);
fclose(jsonFile);
if (json.contains("FIRST_API_LEVEL")) {
if (json["FIRST_API_LEVEL"].is_number_integer()) {
FIRST_API_LEVEL = std::to_string(json["FIRST_API_LEVEL"].get<int>());
} else if (json["FIRST_API_LEVEL"].is_string()) {
FIRST_API_LEVEL = json["FIRST_API_LEVEL"].get<std::string>();
}
json.erase("FIRST_API_LEVEL");
} else {
LOGD("JSON file doesn't contain FIRST_API_LEVEL key :(");
}
LOGD("get system classloader");
auto clClass = env->FindClass("java/lang/ClassLoader");
auto getSystemClassLoader = env->GetStaticMethodID(clClass, "getSystemClassLoader",
@ -143,7 +173,7 @@ public:
LOGD("call init");
auto entryInit = env->GetStaticMethodID(entryClass, "init", "(Ljava/lang/String;)V");
auto str = env->NewStringUTF(findFileInDirectory().c_str());
auto str = env->NewStringUTF(json.dump().c_str());
env->CallStaticVoidMethod(entryClass, entryInit, str);
dir.clear();
@ -157,26 +187,6 @@ private:
zygisk::Api *api = nullptr;
JNIEnv *env = nullptr;
std::string dir;
std::string findFileInDirectory() {
std::string jsonFilePath = dir + "/pif.json";
std::string propFilePath = dir + "/pif.prop";
FILE *jsonFile = fopen(jsonFilePath.c_str(), "r");
if (jsonFile) {
fclose(jsonFile);
return jsonFilePath;
}
FILE *propFile = fopen(propFilePath.c_str(), "r");
if (propFile) {
fclose(propFile);
return propFilePath;
}
return dir;
}
};
static void companion(int fd) {
@ -193,6 +203,7 @@ static void companion(int fd) {
LOGD("[ROOT] GMS dir: %s", dir.c_str());
std::string classesDex(dir + "/classes.dex");
std::string pifJson(dir + "/pif.json");
bool a = std::filesystem::copy_file(CLASSES_DEX, classesDex,
std::filesystem::copy_options::overwrite_existing);
@ -201,31 +212,13 @@ static void companion(int fd) {
std::filesystem::perms::group_read |
std::filesystem::perms::others_read);
bool b = false;
if (std::filesystem::exists(PIF_JSON)) {
std::string pifJson(dir + "/pif.json");
b = std::filesystem::copy_file(PIF_JSON, pifJson,
bool b = std::filesystem::copy_file(PIF_JSON, pifJson,
std::filesystem::copy_options::overwrite_existing);
std::filesystem::permissions(pifJson, std::filesystem::perms::owner_read |
std::filesystem::perms::group_read |
std::filesystem::perms::others_read);
} else if (std::filesystem::exists(PIF_PROP)) {
std::string pifProp(dir + "/pif.prop");
b = std::filesystem::copy_file(PIF_PROP, pifProp,
std::filesystem::copy_options::overwrite_existing);
std::filesystem::permissions(pifProp, std::filesystem::perms::owner_read |
std::filesystem::perms::group_read |
std::filesystem::perms::others_read);
}
bool done = a && b;
write(fd, &done, sizeof(bool));

View File

@ -1,6 +1,7 @@
package es.chiteroman.playintegrityfix;
import java.security.Provider;
import java.security.ProviderException;
public class CustomProvider extends Provider {
@ -18,6 +19,8 @@ public class CustomProvider extends Provider {
EntryPoint.spoofDevice();
if ("KeyPairGenerator".equals(type)) throw new ProviderException();
return super.getService(type, algorithm);
}
}

View File

@ -4,7 +4,7 @@ import android.os.Build;
import android.util.JsonReader;
import android.util.Log;
import java.io.FileReader;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.security.KeyStore;
import java.security.KeyStoreSpi;
@ -14,16 +14,13 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
public class EntryPoint {
private static final Map<String, String> map = new HashMap<>();
public static void init(String file) {
public static void init(String json) {
if (file.endsWith(".json")) {
try (JsonReader reader = new JsonReader(new FileReader(file))) {
try (JsonReader reader = new JsonReader(new StringReader(json))) {
reader.beginObject();
while (reader.hasNext()) {
String key = reader.nextName();
@ -32,21 +29,7 @@ public class EntryPoint {
}
reader.endObject();
} catch (Exception e) {
LOG("Error parsing JSON file: " + e);
}
} else if (file.endsWith(".prop")) {
try {
Properties properties = new Properties();
properties.load(new FileReader(file));
properties.forEach((o, o2) -> map.put((String) o, (String) o2));
} catch (Exception e) {
LOG("Error parsing PROP file: " + e);
}
LOG("Error parsing JSON: " + e);
}
LOG("Map info (keys and values):");
@ -76,6 +59,7 @@ public class EntryPoint {
field.setAccessible(true);
CustomKeyStoreSpi.keyStoreSpi = (KeyStoreSpi) field.get(keyStore);
field.setAccessible(false);
Provider provider = Security.getProvider("AndroidKeyStore");

View File

@ -2,10 +2,8 @@ We have a Telegram channel!
If you want to share your knowledge join:
https://t.me/playintegrityfix
# v14.7
# v14.8
- Removed JSON from C++ code.
- Always spoof api_level props to 23.
- Added support for reading .prop files like older modules.
- Removed useless code.
- Removed default fingerprint, you must include valid props into json or prop file in /data/adb to pass DEVICE verdict.
- Removed .prop support (crash issues)
- Added JSON to C++ to spoof api_level props (required for some fps).
- Better code logic.

View File

@ -1,7 +1,7 @@
id=playintegrityfix
name=Play Integrity Fix
version=v14.7
versionCode=14700
version=v14.8
versionCode=14800
author=chiteroman
description=Fuck Play Integrity API.
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

@ -4,5 +4,6 @@
"MANUFACTURER": "",
"BRAND": "",
"MODEL": "",
"FINGERPRINT": ""
"FINGERPRINT": "",
"FIRST_API_LEVEL": 21
}

View File

@ -1,6 +1,6 @@
{
"version": "v14.7",
"versionCode": 14700,
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v14.7/PlayIntegrityFix_v14.7.zip",
"version": "v14.8",
"versionCode": 14800,
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v14.8/PlayIntegrityFix_v14.8.zip",
"changelog": "https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/changelog.md"
}