mirror of
https://github.com/chiteroman/PlayIntegrityFix.git
synced 2025-01-19 03:22:39 +02:00
v16.3
This commit is contained in:
parent
ecd3b82869
commit
3649341939
@ -16,8 +16,8 @@ android {
|
||||
applicationId = "es.chiteroman.playintegrityfix"
|
||||
minSdk = 26
|
||||
targetSdk = 34
|
||||
versionCode = 16000
|
||||
versionName = "v16.0"
|
||||
versionCode = 16300
|
||||
versionName = "v16.3"
|
||||
multiDexEnabled = false
|
||||
|
||||
packaging {
|
||||
@ -94,7 +94,7 @@ tasks.register("copyFiles") {
|
||||
val dexFile = project.layout.buildDirectory.get().asFile.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex")
|
||||
val soDir = project.layout.buildDirectory.get().asFile.resolve("intermediates/stripped_native_libs/release/stripReleaseDebugSymbols/out/lib")
|
||||
|
||||
// dexFile.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true)
|
||||
dexFile.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true)
|
||||
|
||||
soDir.walk().filter { it.isFile && it.extension == "so" }.forEach { soFile ->
|
||||
val abiFolder = soFile.parentFile.name
|
||||
|
3
app/proguard-rules.pro
vendored
3
app/proguard-rules.pro
vendored
@ -1,3 +1,4 @@
|
||||
-keep class es.chiteroman.playintegrityfix.EntryPoint {public <methods>;}
|
||||
-keep class es.chiteroman.playintegrityfix.CustomProvider
|
||||
-keep class es.chiteroman.playintegrityfix.CustomKeyStoreSpi
|
||||
-keep class es.chiteroman.playintegrityfix.CustomKeyStoreSpi
|
||||
-keep class es.chiteroman.playintegrityfix.KeyboxUtils
|
@ -1,20 +1,24 @@
|
||||
#include <android/log.h>
|
||||
#include <sys/system_properties.h>
|
||||
#include <unistd.h>
|
||||
#include <fstream>
|
||||
#include "dobby.h"
|
||||
#include "json.hpp"
|
||||
#include "zygisk.hpp"
|
||||
#include "dex.h"
|
||||
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF", __VA_ARGS__)
|
||||
|
||||
#define DEX_PATH "/data/adb/modules/playintegrityfix/classes.dex"
|
||||
|
||||
#define PIF_JSON "/data/adb/pif.json"
|
||||
|
||||
#define PIF_JSON_DEFAULT "/data/adb/modules/playintegrityfix/pif.json"
|
||||
|
||||
static std::string DEVICE_INITIAL_SDK_INT, SECURITY_PATCH, ID;
|
||||
#define KEYBOX_JSON "/data/adb/keybox.xml"
|
||||
|
||||
static inline ssize_t xread(int fd, void *buffer, size_t count) {
|
||||
#define KEYBOX_JSON_DEFAULT "/data/adb/modules/playintegrityfix/keybox.xml"
|
||||
|
||||
static ssize_t xread(int fd, void *buffer, size_t count) {
|
||||
ssize_t total = 0;
|
||||
char *buf = (char *) buffer;
|
||||
while (count > 0) {
|
||||
@ -27,7 +31,7 @@ static inline ssize_t xread(int fd, void *buffer, size_t count) {
|
||||
return total;
|
||||
}
|
||||
|
||||
static inline ssize_t xwrite(int fd, void *buffer, size_t count) {
|
||||
static ssize_t xwrite(int fd, void *buffer, size_t count) {
|
||||
ssize_t total = 0;
|
||||
char *buf = (char *) buffer;
|
||||
while (count > 0) {
|
||||
@ -40,6 +44,8 @@ static inline ssize_t xwrite(int fd, void *buffer, size_t count) {
|
||||
return total;
|
||||
}
|
||||
|
||||
static std::string DEVICE_INITIAL_SDK_INT;
|
||||
|
||||
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
|
||||
|
||||
static T_Callback o_callback = nullptr;
|
||||
@ -50,17 +56,8 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
|
||||
|
||||
std::string_view prop(name);
|
||||
|
||||
if (prop.ends_with("api_level") && !DEVICE_INITIAL_SDK_INT.empty()) {
|
||||
if (prop.ends_with("first_api_level") && !DEVICE_INITIAL_SDK_INT.empty()) {
|
||||
value = DEVICE_INITIAL_SDK_INT.c_str();
|
||||
} else if (prop.ends_with(".security_patch") && !SECURITY_PATCH.empty()) {
|
||||
value = SECURITY_PATCH.c_str();
|
||||
} else if (prop.ends_with(".id") && !ID.empty()) {
|
||||
value = ID.c_str();
|
||||
} else if (prop == "sys.usb.state") {
|
||||
value = "none";
|
||||
}
|
||||
|
||||
if (!prop.starts_with("persist") && !prop.starts_with("cache") && !prop.starts_with("debug")) {
|
||||
LOGD("[%s]: %s", name, value);
|
||||
}
|
||||
|
||||
@ -98,71 +95,81 @@ public:
|
||||
|
||||
void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
|
||||
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
|
||||
if (!args) {
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *dir = env->GetStringUTFChars(args->app_data_dir, nullptr);
|
||||
auto dir = env->GetStringUTFChars(args->app_data_dir, nullptr);
|
||||
|
||||
if (!dir) {
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!std::string_view(dir).ends_with("/com.google.android.gms")) {
|
||||
env->ReleaseStringUTFChars(args->app_data_dir, dir);
|
||||
bool isGms = std::string_view(dir).ends_with("/com.google.android.gms");
|
||||
|
||||
env->ReleaseStringUTFChars(args->app_data_dir, dir);
|
||||
|
||||
if (!isGms) {
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
return;
|
||||
}
|
||||
|
||||
env->ReleaseStringUTFChars(args->app_data_dir, dir);
|
||||
|
||||
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
|
||||
|
||||
const char *name = env->GetStringUTFChars(args->nice_name, nullptr);
|
||||
auto name = env->GetStringUTFChars(args->nice_name, nullptr);
|
||||
|
||||
if (!name) {
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(name, "com.google.android.gms.unstable", 31) != 0) {
|
||||
env->ReleaseStringUTFChars(args->nice_name, name);
|
||||
bool isGmsUnstable = std::string_view(name) == "com.google.android.gms.unstable";
|
||||
|
||||
env->ReleaseStringUTFChars(args->nice_name, name);
|
||||
|
||||
if (!isGmsUnstable) {
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
return;
|
||||
}
|
||||
|
||||
env->ReleaseStringUTFChars(args->nice_name, name);
|
||||
|
||||
long size = 0;
|
||||
std::vector<char> vector;
|
||||
|
||||
int fd = api->connectCompanion();
|
||||
|
||||
xread(fd, &size, sizeof(long));
|
||||
int dexSize = 0, jsonSize = 0, keyboxSize = 0;
|
||||
std::vector<char> jsonVector, keyboxVector;
|
||||
|
||||
if (size > 0) {
|
||||
vector.resize(size);
|
||||
xread(fd, vector.data(), size);
|
||||
json = nlohmann::json::parse(vector, nullptr, false, true);
|
||||
} else {
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
}
|
||||
xread(fd, &dexSize, sizeof(int));
|
||||
xread(fd, &jsonSize, sizeof(int));
|
||||
xread(fd, &keyboxSize, sizeof(int));
|
||||
|
||||
dexVector.resize(dexSize);
|
||||
xread(fd, dexVector.data(), dexSize);
|
||||
|
||||
jsonVector.resize(jsonSize);
|
||||
xread(fd, jsonVector.data(), jsonSize);
|
||||
|
||||
keyboxVector.resize(keyboxSize);
|
||||
xread(fd, keyboxVector.data(), keyboxSize);
|
||||
|
||||
close(fd);
|
||||
|
||||
json = nlohmann::json::parse(jsonVector, nullptr, false, true);
|
||||
|
||||
keyboxString = std::string(keyboxVector.cbegin(), keyboxVector.cend());
|
||||
}
|
||||
|
||||
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
||||
if (json.empty()) return;
|
||||
if (dexVector.empty() || json.empty()) return;
|
||||
|
||||
parseJson();
|
||||
if (json.contains("DEVICE_INITIAL_SDK_INT")) {
|
||||
DEVICE_INITIAL_SDK_INT = json["DEVICE_INITIAL_SDK_INT"].get<std::string>();
|
||||
json.erase("DEVICE_INITIAL_SDK_INT"); // You can't modify field value
|
||||
}
|
||||
|
||||
doHook();
|
||||
|
||||
injectDex();
|
||||
|
||||
// doHook();
|
||||
}
|
||||
|
||||
void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override {
|
||||
@ -172,20 +179,9 @@ public:
|
||||
private:
|
||||
zygisk::Api *api = nullptr;
|
||||
JNIEnv *env = nullptr;
|
||||
std::vector<char> dexVector;
|
||||
nlohmann::json json;
|
||||
|
||||
void parseJson() {
|
||||
if (json.contains("DEVICE_INITIAL_SDK_INT")) {
|
||||
DEVICE_INITIAL_SDK_INT = json["DEVICE_INITIAL_SDK_INT"].get<std::string>();
|
||||
json.erase("DEVICE_INITIAL_SDK_INT"); // You can't modify field value
|
||||
}
|
||||
if (json.contains("SECURITY_PATCH")) {
|
||||
SECURITY_PATCH = json["SECURITY_PATCH"].get<std::string>();
|
||||
}
|
||||
if (json.contains("ID")) {
|
||||
ID = json["ID"].get<std::string>();
|
||||
}
|
||||
}
|
||||
std::string keyboxString;
|
||||
|
||||
void injectDex() {
|
||||
LOGD("get system classloader");
|
||||
@ -198,7 +194,7 @@ private:
|
||||
auto dexClClass = env->FindClass("dalvik/system/InMemoryDexClassLoader");
|
||||
auto dexClInit = env->GetMethodID(dexClClass, "<init>",
|
||||
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
||||
auto buffer = env->NewDirectByteBuffer(classes_dex, classes_dex_len);
|
||||
auto buffer = env->NewDirectByteBuffer(dexVector.data(), dexVector.size());
|
||||
auto dexCl = env->NewObject(dexClClass, dexClInit, buffer, systemClassLoader);
|
||||
|
||||
LOGD("load class");
|
||||
@ -210,45 +206,47 @@ private:
|
||||
auto entryPointClass = (jclass) entryClassObj;
|
||||
|
||||
LOGD("call init");
|
||||
auto entryInit = env->GetStaticMethodID(entryPointClass, "init", "(Ljava/lang/String;)V");
|
||||
auto str = env->NewStringUTF(json.dump().c_str());
|
||||
env->CallStaticVoidMethod(entryPointClass, entryInit, str);
|
||||
auto entryInit = env->GetStaticMethodID(entryPointClass, "init",
|
||||
"(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
auto jsonStr = env->NewStringUTF(json.dump().c_str());
|
||||
auto keyboxStr = env->NewStringUTF(keyboxString.c_str());
|
||||
env->CallStaticVoidMethod(entryPointClass, entryInit, jsonStr, keyboxStr);
|
||||
}
|
||||
};
|
||||
|
||||
static std::vector<char> readFile(const char *path) {
|
||||
static std::vector<char> readFile(const std::string &path) {
|
||||
|
||||
std::vector<char> vector;
|
||||
std::ifstream ifs(path);
|
||||
|
||||
FILE *file = fopen(path, "rb");
|
||||
|
||||
if (file) {
|
||||
fseek(file, 0, SEEK_END);
|
||||
long size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
vector.resize(size);
|
||||
fread(vector.data(), 1, size, file);
|
||||
fclose(file);
|
||||
} else {
|
||||
LOGD("Couldn't read %s file!", path);
|
||||
if (!ifs || ifs.bad()) {
|
||||
return std::vector<char>();
|
||||
}
|
||||
|
||||
return vector;
|
||||
return std::vector<char>((std::istreambuf_iterator<char>(ifs)),
|
||||
std::istreambuf_iterator<char>());
|
||||
}
|
||||
|
||||
static void companion(int fd) {
|
||||
long size = 0;
|
||||
std::vector<char> vector;
|
||||
|
||||
vector = readFile(PIF_JSON);
|
||||
auto dex = readFile(DEX_PATH);
|
||||
|
||||
if (vector.empty()) vector = readFile(PIF_JSON_DEFAULT);
|
||||
auto json = readFile(PIF_JSON);
|
||||
if (json.empty()) json = readFile(PIF_JSON_DEFAULT);
|
||||
|
||||
size = vector.size();
|
||||
auto keybox = readFile(KEYBOX_JSON);
|
||||
if (keybox.empty()) keybox = readFile(KEYBOX_JSON_DEFAULT);
|
||||
|
||||
xwrite(fd, &size, sizeof(long));
|
||||
xwrite(fd, vector.data(), size);
|
||||
int dexSize = dex.size();
|
||||
int jsonSize = json.size();
|
||||
int keyboxSize = keybox.size();
|
||||
|
||||
xwrite(fd, &dexSize, sizeof(int));
|
||||
xwrite(fd, &jsonSize, sizeof(int));
|
||||
xwrite(fd, &keyboxSize, sizeof(int));
|
||||
|
||||
xwrite(fd, dex.data(), dexSize * sizeof(char));
|
||||
xwrite(fd, json.data(), jsonSize * sizeof(char));
|
||||
xwrite(fd, keybox.data(), keyboxSize * sizeof(char));
|
||||
}
|
||||
|
||||
REGISTER_ZYGISK_MODULE(PlayIntegrityFix)
|
||||
|
@ -26,7 +26,7 @@ public final class CustomKeyStoreSpi extends KeyStoreSpi {
|
||||
@Override
|
||||
public Certificate[] engineGetCertificateChain(String alias) {
|
||||
if (Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch(e -> e.getClassName().toLowerCase(Locale.US).contains("droidguard"))) {
|
||||
return Android.engineGetCertificateChain(keyStoreSpi.engineGetCertificateChain(alias));
|
||||
return KeyboxUtils.engineGetCertificateChain(keyStoreSpi.engineGetCertificateChain(alias));
|
||||
}
|
||||
return keyStoreSpi.engineGetCertificateChain(alias);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ public final class EntryPoint {
|
||||
Security.insertProviderAt(customProvider, 1);
|
||||
}
|
||||
|
||||
public static void init(String json) {
|
||||
public static void init(String json, String kbox) {
|
||||
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(json);
|
||||
@ -65,6 +65,12 @@ public final class EntryPoint {
|
||||
} catch (Throwable t) {
|
||||
LOG("Error loading json file: " + t);
|
||||
}
|
||||
|
||||
try {
|
||||
KeyboxUtils.parseXml(kbox);
|
||||
} catch (Throwable t) {
|
||||
LOG("Error parsing keybox file: " + t);
|
||||
}
|
||||
}
|
||||
|
||||
static void spoofFields() {
|
||||
|
@ -1,107 +0,0 @@
|
||||
package es.chiteroman.playintegrityfix;
|
||||
|
||||
public final class Keybox {
|
||||
public static final class EC {
|
||||
public static final String PRIVATE_KEY = """
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEICHghkMqFRmEWc82OlD8FMnarfk19SfC39ceTW28QuVEoAoGCCqGSM49
|
||||
AwEHoUQDQgAE6555+EJjWazLKpFMiYbMcK2QZpOCqXMmE/6sy/ghJ0whdJdKKv6l
|
||||
uU1/ZtTgZRBmNbxTt6CjpnFYPts+Ea4QFA==
|
||||
-----END EC PRIVATE KEY-----
|
||||
""";
|
||||
public static final String CERTIFICATE_1 = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICeDCCAh6gAwIBAgICEAEwCgYIKoZIzj0EAwIwgZgxCzAJBgNVBAYTAlVTMRMw
|
||||
EQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYD
|
||||
VQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJvaWQxMzAxBgNVBAMMKkFu
|
||||
ZHJvaWQgS2V5c3RvcmUgU29mdHdhcmUgQXR0ZXN0YXRpb24gUm9vdDAeFw0xNjAx
|
||||
MTEwMDQ2MDlaFw0yNjAxMDgwMDQ2MDlaMIGIMQswCQYDVQQGEwJVUzETMBEGA1UE
|
||||
CAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdB
|
||||
bmRyb2lkMTswOQYDVQQDDDJBbmRyb2lkIEtleXN0b3JlIFNvZnR3YXJlIEF0dGVz
|
||||
dGF0aW9uIEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOue
|
||||
efhCY1msyyqRTImGzHCtkGaTgqlzJhP+rMv4ISdMIXSXSir+pblNf2bU4GUQZjW8
|
||||
U7ego6ZxWD7bPhGuEBSjZjBkMB0GA1UdDgQWBBQ//KzWGrE6noEguNUlHMVlux6R
|
||||
qTAfBgNVHSMEGDAWgBTIrel3TEXDo88NFhDkeUM6IVowzzASBgNVHRMBAf8ECDAG
|
||||
AQH/AgEAMA4GA1UdDwEB/wQEAwIChDAKBggqhkjOPQQDAgNIADBFAiBLipt77oK8
|
||||
wDOHri/AiZi03cONqycqRZ9pDMfDktQPjgIhAO7aAV229DLp1IQ7YkyUBO86fMy9
|
||||
Xvsiu+f+uXc/WT/7
|
||||
-----END CERTIFICATE-----
|
||||
""";
|
||||
public static final String CERTIFICATE_2 = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICizCCAjKgAwIBAgIJAKIFntEOQ1tXMAoGCCqGSM49BAMCMIGYMQswCQYDVQQG
|
||||
EwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmll
|
||||
dzEVMBMGA1UECgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdBbmRyb2lkMTMwMQYD
|
||||
VQQDDCpBbmRyb2lkIEtleXN0b3JlIFNvZnR3YXJlIEF0dGVzdGF0aW9uIFJvb3Qw
|
||||
HhcNMTYwMTExMDA0MzUwWhcNMzYwMTA2MDA0MzUwWjCBmDELMAkGA1UEBhMCVVMx
|
||||
EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT
|
||||
BgNVBAoMDEdvb2dsZSwgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDEzMDEGA1UEAwwq
|
||||
QW5kcm9pZCBLZXlzdG9yZSBTb2Z0d2FyZSBBdHRlc3RhdGlvbiBSb290MFkwEwYH
|
||||
KoZIzj0CAQYIKoZIzj0DAQcDQgAE7l1ex+HA220Dpn7mthvsTWpdamguD/9/SQ59
|
||||
dx9EIm29sa/6FsvHrcV30lacqrewLVQBXT5DKyqO107sSHVBpKNjMGEwHQYDVR0O
|
||||
BBYEFMit6XdMRcOjzw0WEOR5QzohWjDPMB8GA1UdIwQYMBaAFMit6XdMRcOjzw0W
|
||||
EOR5QzohWjDPMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgKEMAoGCCqG
|
||||
SM49BAMCA0cAMEQCIDUho++LNEYenNVg8x1YiSBq3KNlQfYNns6KGYxmSGB7AiBN
|
||||
C/NR2TB8fVvaNTQdqEcbY6WFZTytTySn502vQX3xvw==
|
||||
-----END CERTIFICATE-----
|
||||
""";
|
||||
}
|
||||
|
||||
public static final class RSA {
|
||||
public static final String PRIVATE_KEY = """
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQDAgyPcVogbuDAgafWwhWHG7r5/BeL1qEIEir6LR752/q7yXPKb
|
||||
KvoyABQWAUKZiaFfz8aBXrNjWDwv0vIL5Jgyg92BSxbX4YVBeuVKvClqOm21wAQI
|
||||
O2jFVsHwIzmRZBmGTVC3TUCuykhMdzVsiVoMJ1q/rEmdXX0jYvKcXgLocQIDAQAB
|
||||
AoGBAL6GCwuZqAKm+xpZQ4p7txUGWwmjbcbpysxr88AsNNfXnpTGYGQo2Ix7f2V3
|
||||
wc3qZAdKvo5yht8fCBHclygmCGjeldMu/Ja20IT/JxpfYN78xwPno45uKbqaPF/C
|
||||
woB2tqiWrx0014gozpvdsfNPnJQEQweBKY4gExZyW728mTpBAkEA4cbZJ2RsCRbs
|
||||
NoJtWUmDdAwh8bB0xKGlmGfGaXlchdPcRkxbkp6Uv7NODcxQFLEPEzQat/3V9gQU
|
||||
0qMmytQcxQJBANpIWZd4XNVjD7D9jFJU+Y5TjhiYOq6ea35qWntdNDdVuSGOvUAy
|
||||
DSg4fXifdvohi8wti2il9kGPu+ylF5qzr70CQFD+/DJklVlhbtZTThVFCTKdk6PY
|
||||
ENvlvbmCKSz3i9i624Agro1X9LcdBThv/p6dsnHKNHejSZnbdvjl7OnA1J0CQBW3
|
||||
TPJ8zv+Ls2vwTZ2DRrCaL3DS9EObDyasfgP36dH3fUuRX9KbKCPwOstdUgDghX/y
|
||||
qAPpPu6W1iNc6VRCvCECQQCQp0XaiXCyzWSWYDJCKMX4KFb/1mW6moXI1g8bi+5x
|
||||
fs0scurgHa2GunZU1M9FrbXx8rMdn4Eiz6XxpVcPmy0l
|
||||
-----END RSA PRIVATE KEY-----
|
||||
""";
|
||||
public static final String CERTIFICATE_1 = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICtjCCAh+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMx
|
||||
EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT
|
||||
BgNVBAoMDEdvb2dsZSwgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDAeFw0xNjAxMDQx
|
||||
MjQwNTNaFw0zNTEyMzAxMjQwNTNaMHYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD
|
||||
YWxpZm9ybmlhMRUwEwYDVQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJv
|
||||
aWQxKTAnBgNVBAMMIEFuZHJvaWQgU29mdHdhcmUgQXR0ZXN0YXRpb24gS2V5MIGf
|
||||
MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAgyPcVogbuDAgafWwhWHG7r5/BeL1
|
||||
qEIEir6LR752/q7yXPKbKvoyABQWAUKZiaFfz8aBXrNjWDwv0vIL5Jgyg92BSxbX
|
||||
4YVBeuVKvClqOm21wAQIO2jFVsHwIzmRZBmGTVC3TUCuykhMdzVsiVoMJ1q/rEmd
|
||||
XX0jYvKcXgLocQIDAQABo2YwZDAdBgNVHQ4EFgQU1AwQG/jNY7n3OVK1DhNcpteZ
|
||||
k4YwHwYDVR0jBBgwFoAUKfrxrMxN0kyWQCd1trDpMuUH/i4wEgYDVR0TAQH/BAgw
|
||||
BgEB/wIBADAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADgYEAni1IX4xn
|
||||
M9waha2Z11Aj6hTsQ7DhnerCI0YecrUZ3GAi5KVoMWwLVcTmnKItnzpPk2sxixZ4
|
||||
Fg2Iy9mLzICdhPDCJ+NrOPH90ecXcjFZNX2W88V/q52PlmEmT7K+gbsNSQQiis6f
|
||||
9/VCLiVE+iEHElqDtVWtGIL4QBSbnCBjBH8=
|
||||
-----END CERTIFICATE-----
|
||||
""";
|
||||
public static final String CERTIFICATE_2 = """
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICpzCCAhCgAwIBAgIJAP+U2d2fB8gMMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV
|
||||
BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
|
||||
aWV3MRUwEwYDVQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJvaWQwHhcN
|
||||
MTYwMTA0MTIzMTA4WhcNMzUxMjMwMTIzMTA4WjBjMQswCQYDVQQGEwJVUzETMBEG
|
||||
A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMGA1UE
|
||||
CgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdBbmRyb2lkMIGfMA0GCSqGSIb3DQEB
|
||||
AQUAA4GNADCBiQKBgQCia63rbi5EYe/VDoLmt5TRdSMfd5tjkWP/96r/C3JHTsAs
|
||||
Q+wzfNes7UA+jCigZtX3hwszl94OuE4TQKuvpSe/lWmgMdsGUmX4RFlXYfC78hdL
|
||||
t0GAZMAoDo9Sd47b0ke2RekZyOmLw9vCkT/X11DEHTVm+Vfkl5YLCazOkjWFmwID
|
||||
AQABo2MwYTAdBgNVHQ4EFgQUKfrxrMxN0kyWQCd1trDpMuUH/i4wHwYDVR0jBBgw
|
||||
FoAUKfrxrMxN0kyWQCd1trDpMuUH/i4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
|
||||
Af8EBAMCAoQwDQYJKoZIhvcNAQELBQADgYEAT3LzNlmNDsG5dFsxWfbwjSVJMJ6j
|
||||
HBwp0kUtILlNX2S06IDHeHqcOd6os/W/L3BfRxBcxebrTQaZYdKumgf/93y4q+uc
|
||||
DyQHXrF/unlx/U1bnt8Uqf7f7XzAiF343ZtkMlbVNZriE/mPzsF83O+kqrJVw4Op
|
||||
Lvtc9mL1J1IXvmM=
|
||||
-----END CERTIFICATE-----
|
||||
""";
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package es.chiteroman.playintegrityfix;
|
||||
|
||||
import android.security.keystore.KeyProperties;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.spongycastle.asn1.ASN1Boolean;
|
||||
import org.spongycastle.asn1.ASN1Encodable;
|
||||
@ -23,39 +24,84 @@ import org.spongycastle.openssl.jcajce.JcaPEMKeyConverter;
|
||||
import org.spongycastle.operator.ContentSigner;
|
||||
import org.spongycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||
import org.spongycastle.util.io.pem.PemReader;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.StringReader;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
public final class Android {
|
||||
private static final PEMKeyPair EC, RSA;
|
||||
public final class KeyboxUtils {
|
||||
private static final ASN1ObjectIdentifier OID = new ASN1ObjectIdentifier("1.3.6.1.4.1.11129.2.1.17");
|
||||
private static final List<Certificate> EC_CERTS = new ArrayList<>();
|
||||
private static final List<Certificate> RSA_CERTS = new ArrayList<>();
|
||||
private static final LinkedList<Certificate> EC_CERTS = new LinkedList<>();
|
||||
private static final LinkedList<Certificate> RSA_CERTS = new LinkedList<>();
|
||||
private static final CertificateFactory certificateFactory;
|
||||
private static PEMKeyPair EC, RSA;
|
||||
|
||||
static {
|
||||
try {
|
||||
certificateFactory = CertificateFactory.getInstance("X.509");
|
||||
} catch (CertificateException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
EC = parseKeyPair(Keybox.EC.PRIVATE_KEY);
|
||||
EC_CERTS.add(parseCert(Keybox.EC.CERTIFICATE_1));
|
||||
EC_CERTS.add(parseCert(Keybox.EC.CERTIFICATE_2));
|
||||
public static void parseXml(String kbox) throws Throwable {
|
||||
if (TextUtils.isEmpty(kbox)) return;
|
||||
|
||||
RSA = parseKeyPair(Keybox.RSA.PRIVATE_KEY);
|
||||
RSA_CERTS.add(parseCert(Keybox.RSA.CERTIFICATE_1));
|
||||
RSA_CERTS.add(parseCert(Keybox.RSA.CERTIFICATE_2));
|
||||
} catch (Throwable t) {
|
||||
EntryPoint.LOG(t.toString());
|
||||
throw new RuntimeException(t);
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document doc = builder.parse(new ByteArrayInputStream(kbox.getBytes()));
|
||||
|
||||
doc.getDocumentElement().normalize();
|
||||
|
||||
NodeList keyboxList = doc.getElementsByTagName("Keybox");
|
||||
Node keyboxNode = keyboxList.item(0);
|
||||
if (keyboxNode.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element keyboxElement = (Element) keyboxNode;
|
||||
|
||||
NodeList keyList = keyboxElement.getElementsByTagName("Key");
|
||||
for (int j = 0; j < keyList.getLength(); j++) {
|
||||
Element keyElement = (Element) keyList.item(j);
|
||||
String algorithm = keyElement.getAttribute("algorithm");
|
||||
|
||||
NodeList privateKeyList = keyElement.getElementsByTagName("PrivateKey");
|
||||
if (privateKeyList.getLength() > 0) {
|
||||
Element privateKeyElement = (Element) privateKeyList.item(0);
|
||||
String privateKeyContent = privateKeyElement.getTextContent().trim();
|
||||
if ("ecdsa".equals(algorithm)) {
|
||||
EC = parseKeyPair(privateKeyContent);
|
||||
} else if ("rsa".equals(algorithm)) {
|
||||
RSA = parseKeyPair(privateKeyContent);
|
||||
}
|
||||
}
|
||||
|
||||
NodeList certificateChainList = keyElement.getElementsByTagName("CertificateChain");
|
||||
if (certificateChainList.getLength() > 0) {
|
||||
Element certificateChainElement = (Element) certificateChainList.item(0);
|
||||
|
||||
NodeList certificateList = certificateChainElement.getElementsByTagName("Certificate");
|
||||
for (int k = 0; k < certificateList.getLength(); k++) {
|
||||
Element certificateElement = (Element) certificateList.item(k);
|
||||
String certificateContent = certificateElement.getTextContent().trim();
|
||||
if ("ecdsa".equals(algorithm)) {
|
||||
EC_CERTS.add(parseCert(certificateContent));
|
||||
} else if ("rsa".equals(algorithm)) {
|
||||
RSA_CERTS.add(parseCert(certificateContent));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +118,18 @@ public final class Android {
|
||||
}
|
||||
|
||||
public static Certificate[] engineGetCertificateChain(Certificate[] caList) {
|
||||
if (caList == null) throw new UnsupportedOperationException();
|
||||
if (caList == null) {
|
||||
EntryPoint.LOG("Certificate chain is null!");
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
if (EC == null && RSA == null) {
|
||||
EntryPoint.LOG("EC and RSA private keys are null!");
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
if (EC_CERTS.isEmpty() && RSA_CERTS.isEmpty()) {
|
||||
EntryPoint.LOG("EC and RSA certs are empty!");
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
try {
|
||||
X509Certificate leaf = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(caList[0].getEncoded()));
|
||||
|
||||
@ -103,14 +160,17 @@ public final class Android {
|
||||
X509v3CertificateBuilder builder;
|
||||
ContentSigner signer;
|
||||
|
||||
if (KeyProperties.KEY_ALGORITHM_EC.equals(leaf.getPublicKey().getAlgorithm())) {
|
||||
// Not all keyboxes have EC keys :)
|
||||
if (EC != null && !EC_CERTS.isEmpty() && KeyProperties.KEY_ALGORITHM_EC.equals(leaf.getPublicKey().getAlgorithm())) {
|
||||
EntryPoint.LOG("Using EC");
|
||||
certificates = new LinkedList<>(EC_CERTS);
|
||||
builder = new X509v3CertificateBuilder(new X509CertificateHolder(EC_CERTS.get(0).getEncoded()).getSubject(), holder.getSerialNumber(), holder.getNotBefore(), holder.getNotAfter(), holder.getSubject(), EC.getPublicKeyInfo());
|
||||
signer = new JcaContentSignerBuilder(leaf.getSigAlgName()).build(new JcaPEMKeyConverter().getPrivateKey(EC.getPrivateKeyInfo()));
|
||||
} else {
|
||||
EntryPoint.LOG("Using RSA");
|
||||
certificates = new LinkedList<>(RSA_CERTS);
|
||||
builder = new X509v3CertificateBuilder(new X509CertificateHolder(RSA_CERTS.get(0).getEncoded()).getSubject(), holder.getSerialNumber(), holder.getNotBefore(), holder.getNotAfter(), holder.getSubject(), RSA.getPublicKeyInfo());
|
||||
signer = new JcaContentSignerBuilder(leaf.getSigAlgName()).build(new JcaPEMKeyConverter().getPrivateKey(RSA.getPrivateKeyInfo()));
|
||||
signer = new JcaContentSignerBuilder("SHA256withRSA").build(new JcaPEMKeyConverter().getPrivateKey(RSA.getPrivateKeyInfo()));
|
||||
}
|
||||
|
||||
byte[] verifiedBootKey = new byte[32];
|
||||
@ -151,6 +211,6 @@ public final class Android {
|
||||
} catch (Throwable t) {
|
||||
EntryPoint.LOG(t.toString());
|
||||
}
|
||||
return caList;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
14
changelog.md
14
changelog.md
@ -7,6 +7,16 @@ If not, try removing /data/adb/pif.json file.
|
||||
Donations:
|
||||
https://www.paypal.com/paypalme/chiteroman
|
||||
|
||||
# v16.0
|
||||
# v16.3
|
||||
|
||||
- WORKING TEE = STRONG PASS
|
||||
Google fixed the bug, no more Strong pass with SW keybox 😢
|
||||
|
||||
- Improve C++ and Java code
|
||||
- Downgrade first_api_level to 24, so all devices (should) be able to pass Device
|
||||
- Included keybox.xml parsing! You can create /data/adb/keybox.xml to define your own keybox (Strong passing with my private one :D)
|
||||
|
||||
By default, inside module folder, it exits pif.json and keybox.xml, do NOT delete these files
|
||||
|
||||
keybox.xml included in the module is SW one
|
||||
|
||||
Keybox "hack" does NOT work on broken TEE devices, like OnePlus
|
||||
|
114
module/keybox.xml
Normal file
114
module/keybox.xml
Normal file
@ -0,0 +1,114 @@
|
||||
<?xml version="1.0"?>
|
||||
<AndroidAttestation>
|
||||
<NumberOfKeyboxes>1</NumberOfKeyboxes>
|
||||
<Keybox DeviceID="sw">
|
||||
<Key algorithm="ecdsa">
|
||||
<PrivateKey format="pem">
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEICHghkMqFRmEWc82OlD8FMnarfk19SfC39ceTW28QuVEoAoGCCqGSM49
|
||||
AwEHoUQDQgAE6555+EJjWazLKpFMiYbMcK2QZpOCqXMmE/6sy/ghJ0whdJdKKv6l
|
||||
uU1/ZtTgZRBmNbxTt6CjpnFYPts+Ea4QFA==
|
||||
-----END EC PRIVATE KEY-----
|
||||
</PrivateKey>
|
||||
<CertificateChain>
|
||||
<NumberOfCertificates>2</NumberOfCertificates>
|
||||
<Certificate format="pem">
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICeDCCAh6gAwIBAgICEAEwCgYIKoZIzj0EAwIwgZgxCzAJBgNVBAYTAlVTMRMw
|
||||
EQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRUwEwYD
|
||||
VQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJvaWQxMzAxBgNVBAMMKkFu
|
||||
ZHJvaWQgS2V5c3RvcmUgU29mdHdhcmUgQXR0ZXN0YXRpb24gUm9vdDAeFw0xNjAx
|
||||
MTEwMDQ2MDlaFw0yNjAxMDgwMDQ2MDlaMIGIMQswCQYDVQQGEwJVUzETMBEGA1UE
|
||||
CAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdB
|
||||
bmRyb2lkMTswOQYDVQQDDDJBbmRyb2lkIEtleXN0b3JlIFNvZnR3YXJlIEF0dGVz
|
||||
dGF0aW9uIEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOue
|
||||
efhCY1msyyqRTImGzHCtkGaTgqlzJhP+rMv4ISdMIXSXSir+pblNf2bU4GUQZjW8
|
||||
U7ego6ZxWD7bPhGuEBSjZjBkMB0GA1UdDgQWBBQ//KzWGrE6noEguNUlHMVlux6R
|
||||
qTAfBgNVHSMEGDAWgBTIrel3TEXDo88NFhDkeUM6IVowzzASBgNVHRMBAf8ECDAG
|
||||
AQH/AgEAMA4GA1UdDwEB/wQEAwIChDAKBggqhkjOPQQDAgNIADBFAiBLipt77oK8
|
||||
wDOHri/AiZi03cONqycqRZ9pDMfDktQPjgIhAO7aAV229DLp1IQ7YkyUBO86fMy9
|
||||
Xvsiu+f+uXc/WT/7
|
||||
-----END CERTIFICATE-----
|
||||
</Certificate>
|
||||
<Certificate format="pem">
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICizCCAjKgAwIBAgIJAKIFntEOQ1tXMAoGCCqGSM49BAMCMIGYMQswCQYDVQQG
|
||||
EwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmll
|
||||
dzEVMBMGA1UECgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdBbmRyb2lkMTMwMQYD
|
||||
VQQDDCpBbmRyb2lkIEtleXN0b3JlIFNvZnR3YXJlIEF0dGVzdGF0aW9uIFJvb3Qw
|
||||
HhcNMTYwMTExMDA0MzUwWhcNMzYwMTA2MDA0MzUwWjCBmDELMAkGA1UEBhMCVVMx
|
||||
EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT
|
||||
BgNVBAoMDEdvb2dsZSwgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDEzMDEGA1UEAwwq
|
||||
QW5kcm9pZCBLZXlzdG9yZSBTb2Z0d2FyZSBBdHRlc3RhdGlvbiBSb290MFkwEwYH
|
||||
KoZIzj0CAQYIKoZIzj0DAQcDQgAE7l1ex+HA220Dpn7mthvsTWpdamguD/9/SQ59
|
||||
dx9EIm29sa/6FsvHrcV30lacqrewLVQBXT5DKyqO107sSHVBpKNjMGEwHQYDVR0O
|
||||
BBYEFMit6XdMRcOjzw0WEOR5QzohWjDPMB8GA1UdIwQYMBaAFMit6XdMRcOjzw0W
|
||||
EOR5QzohWjDPMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgKEMAoGCCqG
|
||||
SM49BAMCA0cAMEQCIDUho++LNEYenNVg8x1YiSBq3KNlQfYNns6KGYxmSGB7AiBN
|
||||
C/NR2TB8fVvaNTQdqEcbY6WFZTytTySn502vQX3xvw==
|
||||
-----END CERTIFICATE-----
|
||||
</Certificate>
|
||||
</CertificateChain>
|
||||
</Key>
|
||||
<Key algorithm="rsa">
|
||||
<PrivateKey format="pem">
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQDAgyPcVogbuDAgafWwhWHG7r5/BeL1qEIEir6LR752/q7yXPKb
|
||||
KvoyABQWAUKZiaFfz8aBXrNjWDwv0vIL5Jgyg92BSxbX4YVBeuVKvClqOm21wAQI
|
||||
O2jFVsHwIzmRZBmGTVC3TUCuykhMdzVsiVoMJ1q/rEmdXX0jYvKcXgLocQIDAQAB
|
||||
AoGBAL6GCwuZqAKm+xpZQ4p7txUGWwmjbcbpysxr88AsNNfXnpTGYGQo2Ix7f2V3
|
||||
wc3qZAdKvo5yht8fCBHclygmCGjeldMu/Ja20IT/JxpfYN78xwPno45uKbqaPF/C
|
||||
woB2tqiWrx0014gozpvdsfNPnJQEQweBKY4gExZyW728mTpBAkEA4cbZJ2RsCRbs
|
||||
NoJtWUmDdAwh8bB0xKGlmGfGaXlchdPcRkxbkp6Uv7NODcxQFLEPEzQat/3V9gQU
|
||||
0qMmytQcxQJBANpIWZd4XNVjD7D9jFJU+Y5TjhiYOq6ea35qWntdNDdVuSGOvUAy
|
||||
DSg4fXifdvohi8wti2il9kGPu+ylF5qzr70CQFD+/DJklVlhbtZTThVFCTKdk6PY
|
||||
ENvlvbmCKSz3i9i624Agro1X9LcdBThv/p6dsnHKNHejSZnbdvjl7OnA1J0CQBW3
|
||||
TPJ8zv+Ls2vwTZ2DRrCaL3DS9EObDyasfgP36dH3fUuRX9KbKCPwOstdUgDghX/y
|
||||
qAPpPu6W1iNc6VRCvCECQQCQp0XaiXCyzWSWYDJCKMX4KFb/1mW6moXI1g8bi+5x
|
||||
fs0scurgHa2GunZU1M9FrbXx8rMdn4Eiz6XxpVcPmy0l
|
||||
-----END RSA PRIVATE KEY-----
|
||||
</PrivateKey>
|
||||
<CertificateChain>
|
||||
<NumberOfCertificates>2</NumberOfCertificates>
|
||||
<Certificate format="pem">
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICtjCCAh+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMx
|
||||
EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFTAT
|
||||
BgNVBAoMDEdvb2dsZSwgSW5jLjEQMA4GA1UECwwHQW5kcm9pZDAeFw0xNjAxMDQx
|
||||
MjQwNTNaFw0zNTEyMzAxMjQwNTNaMHYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD
|
||||
YWxpZm9ybmlhMRUwEwYDVQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJv
|
||||
aWQxKTAnBgNVBAMMIEFuZHJvaWQgU29mdHdhcmUgQXR0ZXN0YXRpb24gS2V5MIGf
|
||||
MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAgyPcVogbuDAgafWwhWHG7r5/BeL1
|
||||
qEIEir6LR752/q7yXPKbKvoyABQWAUKZiaFfz8aBXrNjWDwv0vIL5Jgyg92BSxbX
|
||||
4YVBeuVKvClqOm21wAQIO2jFVsHwIzmRZBmGTVC3TUCuykhMdzVsiVoMJ1q/rEmd
|
||||
XX0jYvKcXgLocQIDAQABo2YwZDAdBgNVHQ4EFgQU1AwQG/jNY7n3OVK1DhNcpteZ
|
||||
k4YwHwYDVR0jBBgwFoAUKfrxrMxN0kyWQCd1trDpMuUH/i4wEgYDVR0TAQH/BAgw
|
||||
BgEB/wIBADAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADgYEAni1IX4xn
|
||||
M9waha2Z11Aj6hTsQ7DhnerCI0YecrUZ3GAi5KVoMWwLVcTmnKItnzpPk2sxixZ4
|
||||
Fg2Iy9mLzICdhPDCJ+NrOPH90ecXcjFZNX2W88V/q52PlmEmT7K+gbsNSQQiis6f
|
||||
9/VCLiVE+iEHElqDtVWtGIL4QBSbnCBjBH8=
|
||||
-----END CERTIFICATE-----
|
||||
</Certificate>
|
||||
<Certificate format="pem">
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICpzCCAhCgAwIBAgIJAP+U2d2fB8gMMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNV
|
||||
BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW
|
||||
aWV3MRUwEwYDVQQKDAxHb29nbGUsIEluYy4xEDAOBgNVBAsMB0FuZHJvaWQwHhcN
|
||||
MTYwMTA0MTIzMTA4WhcNMzUxMjMwMTIzMTA4WjBjMQswCQYDVQQGEwJVUzETMBEG
|
||||
A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEVMBMGA1UE
|
||||
CgwMR29vZ2xlLCBJbmMuMRAwDgYDVQQLDAdBbmRyb2lkMIGfMA0GCSqGSIb3DQEB
|
||||
AQUAA4GNADCBiQKBgQCia63rbi5EYe/VDoLmt5TRdSMfd5tjkWP/96r/C3JHTsAs
|
||||
Q+wzfNes7UA+jCigZtX3hwszl94OuE4TQKuvpSe/lWmgMdsGUmX4RFlXYfC78hdL
|
||||
t0GAZMAoDo9Sd47b0ke2RekZyOmLw9vCkT/X11DEHTVm+Vfkl5YLCazOkjWFmwID
|
||||
AQABo2MwYTAdBgNVHQ4EFgQUKfrxrMxN0kyWQCd1trDpMuUH/i4wHwYDVR0jBBgw
|
||||
FoAUKfrxrMxN0kyWQCd1trDpMuUH/i4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
|
||||
Af8EBAMCAoQwDQYJKoZIhvcNAQELBQADgYEAT3LzNlmNDsG5dFsxWfbwjSVJMJ6j
|
||||
HBwp0kUtILlNX2S06IDHeHqcOd6os/W/L3BfRxBcxebrTQaZYdKumgf/93y4q+uc
|
||||
DyQHXrF/unlx/U1bnt8Uqf7f7XzAiF343ZtkMlbVNZriE/mPzsF83O+kqrJVw4Op
|
||||
Lvtc9mL1J1IXvmM=
|
||||
-----END CERTIFICATE-----
|
||||
</Certificate>
|
||||
</CertificateChain>
|
||||
</Key>
|
||||
</Keybox>
|
||||
</AndroidAttestation>
|
@ -1,7 +1,7 @@
|
||||
id=playintegrityfix
|
||||
name=Play Integrity Fix (STRONG)
|
||||
version=v16.0
|
||||
versionCode=16000
|
||||
name=Play Integrity Fix
|
||||
version=v16.3
|
||||
versionCode=16300
|
||||
author=chiteroman
|
||||
description=WORKING TEE = STRONG PASS | THANKS GOOGLE
|
||||
description=Universal modular fix for Play Integrity (and SafetyNet) on devices running Android 8-15
|
||||
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json
|
||||
|
@ -11,5 +11,5 @@
|
||||
"TYPE": "user",
|
||||
"TAGS": "release-keys",
|
||||
"SECURITY_PATCH": "2017-12-05",
|
||||
"DEVICE_INITIAL_SDK_INT": "25"
|
||||
}
|
||||
"DEVICE_INITIAL_SDK_INT": "24"
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "v16.0",
|
||||
"versionCode": 16000,
|
||||
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v16.0/PlayIntegrityFix_v16.0.zip",
|
||||
"version": "v16.3",
|
||||
"versionCode": 16300,
|
||||
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v16.3/PlayIntegrityFix_v16.3.zip",
|
||||
"changelog": "https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/changelog.md"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user