mirror of
https://github.com/chiteroman/PlayIntegrityFix.git
synced 2025-01-19 03:22:39 +02:00
Custom props!
This commit is contained in:
parent
27c00e2ce7
commit
edffde9b1a
@ -28,7 +28,7 @@ It injects a classes.dex file to modify few fields in android.os.Build class. Al
|
|||||||
it creates a hook to modify system properties.
|
it creates a hook to modify system properties.
|
||||||
The purpose of the module is to avoid a hardware attestation.
|
The purpose of the module is to avoid a hardware attestation.
|
||||||
|
|
||||||
## About 'pif.prop' file
|
## About 'pif.json' file
|
||||||
|
|
||||||
You can modify this file to spoof android.os.Build fields in GMS unstable process and try to pass Device verdict.
|
You can modify this file to spoof android.os.Build fields in GMS unstable process and try to pass Device verdict.
|
||||||
You can't use values from recent devices due this devices must use a hardware attestation.
|
You can't use values from recent devices due this devices must use a hardware attestation.
|
||||||
|
24689
app/src/main/cpp/json.hpp
Normal file
24689
app/src/main/cpp/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,18 +1,19 @@
|
|||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
#include <sys/system_properties.h>
|
#include <sys/system_properties.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string_view>
|
#include <fstream>
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "zygisk.hpp"
|
#include "zygisk.hpp"
|
||||||
#include "dobby.h"
|
#include "dobby.h"
|
||||||
|
#include "json.hpp"
|
||||||
|
|
||||||
|
#define DEX_FILE_PATH "/data/adb/modules/playintegrityfix/classes.dex"
|
||||||
|
|
||||||
|
#define PROP_FILE_PATH "/data/adb/modules/playintegrityfix/pif.json"
|
||||||
|
|
||||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF/Native", __VA_ARGS__)
|
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF/Native", __VA_ARGS__)
|
||||||
|
|
||||||
#define FIRST_API_LEVEL "25"
|
static std::string FIRST_API_LEVEL, SECURITY_PATCH;
|
||||||
|
|
||||||
#define SECURITY_PATCH "2017-08-05"
|
|
||||||
|
|
||||||
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
|
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
|
||||||
|
|
||||||
@ -27,10 +28,18 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
|
|||||||
std::string_view prop(name);
|
std::string_view prop(name);
|
||||||
|
|
||||||
if (prop.ends_with("api_level")) {
|
if (prop.ends_with("api_level")) {
|
||||||
value = FIRST_API_LEVEL;
|
if (FIRST_API_LEVEL == "NULL") {
|
||||||
|
value = nullptr;
|
||||||
|
} else {
|
||||||
|
value = FIRST_API_LEVEL.c_str();
|
||||||
|
}
|
||||||
LOGD("[%s] -> %s", name, value);
|
LOGD("[%s] -> %s", name, value);
|
||||||
} else if (prop.ends_with("security_patch")) {
|
} else if (prop.ends_with("security_patch")) {
|
||||||
value = SECURITY_PATCH;
|
if (SECURITY_PATCH == "NULL") {
|
||||||
|
value = nullptr;
|
||||||
|
} else {
|
||||||
|
value = SECURITY_PATCH.c_str();
|
||||||
|
}
|
||||||
LOGD("[%s] -> %s", name, value);
|
LOGD("[%s] -> %s", name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,23 +99,44 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t size;
|
||||||
|
char buffer[10000];
|
||||||
int fd = api->connectCompanion();
|
int fd = api->connectCompanion();
|
||||||
|
|
||||||
long size;
|
size = read(fd, buffer, sizeof(buffer));
|
||||||
char buffer[1024];
|
|
||||||
|
|
||||||
while ((size = read(fd, buffer, sizeof(buffer))) > 0) {
|
if (size > 0) {
|
||||||
moduleDex.insert(moduleDex.end(), buffer, buffer + size);
|
moduleDex.insert(moduleDex.end(), buffer, buffer + size);
|
||||||
|
} else {
|
||||||
|
LOGD("Couldn't load classes.dex file in memory");
|
||||||
|
close(fd);
|
||||||
|
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
size = read(fd, buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
if (size > 0) {
|
||||||
|
jsonStr.insert(jsonStr.end(), buffer, buffer + size);
|
||||||
|
} else {
|
||||||
|
LOGD("Couldn't load pif.json file in memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
LOGD("Received from socket %lu bytes!", moduleDex.size());
|
LOGD("Received 'classes.dex' file from socket: %d bytes",
|
||||||
|
static_cast<int>(moduleDex.size()));
|
||||||
|
|
||||||
|
LOGD("Received 'pif.json' file from socket: %d bytes", static_cast<int>(jsonStr.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
||||||
if (moduleDex.empty()) return;
|
if (moduleDex.empty()) return;
|
||||||
|
|
||||||
|
readJson();
|
||||||
|
|
||||||
inject();
|
inject();
|
||||||
|
|
||||||
doHook();
|
doHook();
|
||||||
@ -120,6 +150,21 @@ private:
|
|||||||
zygisk::Api *api = nullptr;
|
zygisk::Api *api = nullptr;
|
||||||
JNIEnv *env = nullptr;
|
JNIEnv *env = nullptr;
|
||||||
std::vector<char> moduleDex;
|
std::vector<char> moduleDex;
|
||||||
|
std::string jsonStr;
|
||||||
|
|
||||||
|
void readJson() {
|
||||||
|
nlohmann::json json = nlohmann::json::parse(jsonStr, nullptr, false);
|
||||||
|
|
||||||
|
auto getStringFromJson = [&json](const std::string &key) {
|
||||||
|
return json.contains(key) && !json[key].is_null() ? json[key].get<std::string>()
|
||||||
|
: "NULL";
|
||||||
|
};
|
||||||
|
|
||||||
|
SECURITY_PATCH = getStringFromJson("SECURITY_PATCH");
|
||||||
|
FIRST_API_LEVEL = getStringFromJson("FIRST_API_LEVEL");
|
||||||
|
|
||||||
|
json.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void inject() {
|
void inject() {
|
||||||
LOGD("get system classloader");
|
LOGD("get system classloader");
|
||||||
@ -144,34 +189,34 @@ private:
|
|||||||
|
|
||||||
auto entryClass = (jclass) entryClassObj;
|
auto entryClass = (jclass) entryClassObj;
|
||||||
|
|
||||||
|
LOGD("read json");
|
||||||
|
auto readProps = env->GetStaticMethodID(entryClass, "readJson",
|
||||||
|
"(Ljava/lang/String;)V");
|
||||||
|
auto javaStr = env->NewStringUTF(jsonStr.c_str());
|
||||||
|
env->CallStaticVoidMethod(entryClass, readProps, javaStr);
|
||||||
|
|
||||||
LOGD("call init");
|
LOGD("call init");
|
||||||
auto entryInit = env->GetStaticMethodID(entryClass, "init", "()V");
|
auto entryInit = env->GetStaticMethodID(entryClass, "init", "()V");
|
||||||
env->CallStaticVoidMethod(entryClass, entryInit);
|
env->CallStaticVoidMethod(entryClass, entryInit);
|
||||||
|
|
||||||
moduleDex.clear();
|
moduleDex.clear();
|
||||||
|
jsonStr.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void companion(int fd) {
|
static void companion(int fd) {
|
||||||
FILE *file = fopen("/data/adb/modules/playintegrityfix/classes.dex", "rb");
|
std::ifstream dex(DEX_FILE_PATH, std::ios::binary);
|
||||||
|
std::ifstream prop(PROP_FILE_PATH);
|
||||||
|
|
||||||
if (file == nullptr) {
|
std::vector<char> dexVector((std::istreambuf_iterator<char>(dex)),
|
||||||
write(fd, nullptr, 0);
|
std::istreambuf_iterator<char>());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(file, 0, SEEK_END);
|
std::vector<char> propVector((std::istreambuf_iterator<char>(prop)),
|
||||||
long size = ftell(file);
|
std::istreambuf_iterator<char>());
|
||||||
fseek(file, 0, SEEK_SET);
|
|
||||||
|
|
||||||
std::vector<char> vector(size);
|
write(fd, dexVector.data(), dexVector.size());
|
||||||
fread(vector.data(), 1, size, file);
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
write(fd, propVector.data(), propVector.size());
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
write(fd, vector.data(), size);
|
|
||||||
|
|
||||||
vector.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_ZYGISK_MODULE(PlayIntegrityFix)
|
REGISTER_ZYGISK_MODULE(PlayIntegrityFix)
|
||||||
|
@ -1,29 +1,40 @@
|
|||||||
package es.chiteroman.playintegrityfix;
|
package es.chiteroman.playintegrityfix;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.util.JsonReader;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.KeyStoreSpi;
|
import java.security.KeyStoreSpi;
|
||||||
import java.security.Provider;
|
import java.security.Provider;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public final class EntryPoint {
|
public final class EntryPoint {
|
||||||
private static final String PRODUCT = "sailfish";
|
private static final Map<String, String> map = new HashMap<>();
|
||||||
private static final String DEVICE = "sailfish";
|
|
||||||
private static final String MANUFACTURER = "Google";
|
|
||||||
private static final String BRAND = "google";
|
|
||||||
private static final String MODEL = "Pixel";
|
|
||||||
private static final String FINGERPRINT = "google/sailfish/sailfish:7.1.2/NZH54D/4146044:user/release-keys";
|
|
||||||
private static final String SECURITY_PATCH = "2017-08-05";
|
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
spoofProvider();
|
spoofProvider();
|
||||||
spoofDevice();
|
spoofDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void readJson(String data) {
|
||||||
|
try (JsonReader reader = new JsonReader(new StringReader(data))) {
|
||||||
|
reader.beginObject();
|
||||||
|
while (reader.hasNext()) {
|
||||||
|
map.put(reader.nextName(), reader.nextString());
|
||||||
|
}
|
||||||
|
reader.endObject();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG("Couldn't read JSON from Zygisk: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void spoofProvider() {
|
private static void spoofProvider() {
|
||||||
final String KEYSTORE = "AndroidKeyStore";
|
final String KEYSTORE = "AndroidKeyStore";
|
||||||
|
|
||||||
@ -52,13 +63,15 @@ public final class EntryPoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void spoofDevice() {
|
static void spoofDevice() {
|
||||||
setProp("PRODUCT", PRODUCT);
|
if (map.isEmpty()) return;
|
||||||
setProp("DEVICE", DEVICE);
|
|
||||||
setProp("MANUFACTURER", MANUFACTURER);
|
setProp("PRODUCT", map.get("PRODUCT"));
|
||||||
setProp("BRAND", BRAND);
|
setProp("DEVICE", map.get("DEVICE"));
|
||||||
setProp("MODEL", MODEL);
|
setProp("MANUFACTURER", map.get("MANUFACTURER"));
|
||||||
setProp("FINGERPRINT", FINGERPRINT);
|
setProp("BRAND", map.get("BRAND"));
|
||||||
setVersionProp("SECURITY_PATCH", SECURITY_PATCH);
|
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) {
|
private static void setProp(String name, String value) {
|
||||||
|
@ -10,8 +10,7 @@ https://t.me/playintegrityfix
|
|||||||
|
|
||||||
If you want an undetectable resetprop, use Kitsune Magisk.
|
If you want an undetectable resetprop, use Kitsune Magisk.
|
||||||
If you want to spoof your own props, modify the props in source code and build by yourself.
|
If you want to spoof your own props, modify the props in source code and build by yourself.
|
||||||
|
Or you can use unstable build, you can download in GitHub repo.
|
||||||
Should work and don't crash nothing.
|
Should work and don't crash nothing.
|
||||||
|
|
||||||
Maybe in a future I do a custom spoof version... But I won't release it as stable build.
|
|
||||||
|
|
||||||
I recommend to clear GMS data and cache before reboot.
|
I recommend to clear GMS data and cache before reboot.
|
@ -1,7 +1,6 @@
|
|||||||
id=playintegrityfix
|
id=playintegrityfix
|
||||||
name=Play Integrity Fix
|
name=Play Integrity Fix
|
||||||
version=v13.7
|
version=v1.1-PROPS
|
||||||
versionCode=137
|
versionCode=1
|
||||||
author=chiteroman
|
author=chiteroman
|
||||||
description=Fix CTS profile (SafetyNet) and DEVICE verdict (Play Integrity).
|
description=Fix CTS profile (SafetyNet) and DEVICE verdict (Play Integrity).
|
||||||
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json
|
|
10
module/pif.json
Normal file
10
module/pif.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"PRODUCT": "taimen",
|
||||||
|
"DEVICE": "taimen",
|
||||||
|
"MANUFACTURER": "Google",
|
||||||
|
"BRAND": "google",
|
||||||
|
"MODEL": "Pixel 2 XL",
|
||||||
|
"FINGERPRINT": "google/taimen/taimen:8.1.0/OPM4.171019.021.R1/4833808:user/release-keys",
|
||||||
|
"SECURITY_PATCH": "2018-07-05",
|
||||||
|
"FIRST_API_LEVEL": "25"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user