mirror of
https://github.com/chiteroman/PlayIntegrityFix.git
synced 2025-01-19 03:22:39 +02:00
v16.0
This commit is contained in:
parent
b2b60f781e
commit
ecd3b82869
1
.idea/.name
Normal file
1
.idea/.name
Normal file
@ -0,0 +1 @@
|
|||||||
|
PlayIntegrityFix
|
@ -1,4 +1,3 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="corretto-21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="corretto-21" project-jdk-type="JavaSDK">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -16,8 +16,8 @@ android {
|
|||||||
applicationId = "es.chiteroman.playintegrityfix"
|
applicationId = "es.chiteroman.playintegrityfix"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 15990
|
versionCode = 16000
|
||||||
versionName = "v15.9.9"
|
versionName = "v16.0"
|
||||||
multiDexEnabled = false
|
multiDexEnabled = false
|
||||||
|
|
||||||
packaging {
|
packaging {
|
||||||
@ -66,6 +66,7 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("dev.rikka.ndk.thirdparty:cxx:1.2.0")
|
implementation("dev.rikka.ndk.thirdparty:cxx:1.2.0")
|
||||||
|
implementation("com.madgag.spongycastle:bcpkix-jdk15on:1.58.0.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("updateModuleProp") {
|
tasks.register("updateModuleProp") {
|
||||||
@ -93,7 +94,7 @@ tasks.register("copyFiles") {
|
|||||||
val dexFile = project.layout.buildDirectory.get().asFile.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex")
|
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")
|
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 ->
|
soDir.walk().filter { it.isFile && it.extension == "so" }.forEach { soFile ->
|
||||||
val abiFolder = soFile.parentFile.name
|
val abiFolder = soFile.parentFile.name
|
||||||
|
12962
app/src/main/cpp/dex.h
Normal file
12962
app/src/main/cpp/dex.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,22 +4,17 @@
|
|||||||
#include "dobby.h"
|
#include "dobby.h"
|
||||||
#include "json.hpp"
|
#include "json.hpp"
|
||||||
#include "zygisk.hpp"
|
#include "zygisk.hpp"
|
||||||
|
#include "dex.h"
|
||||||
|
|
||||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF", __VA_ARGS__)
|
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF", __VA_ARGS__)
|
||||||
|
|
||||||
#define CLASSES_DEX "/data/adb/modules/playintegrityfix/classes.dex"
|
|
||||||
|
|
||||||
#define PIF_JSON "/data/adb/pif.json"
|
#define PIF_JSON "/data/adb/pif.json"
|
||||||
|
|
||||||
#define PIF_JSON_DEFAULT "/data/adb/modules/playintegrityfix/pif.json"
|
#define PIF_JSON_DEFAULT "/data/adb/modules/playintegrityfix/pif.json"
|
||||||
|
|
||||||
static std::string DEVICE_INITIAL_SDK_INT, SECURITY_PATCH, ID;
|
static std::string DEVICE_INITIAL_SDK_INT, SECURITY_PATCH, ID;
|
||||||
|
|
||||||
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
|
static inline ssize_t xread(int fd, void *buffer, size_t count) {
|
||||||
|
|
||||||
static T_Callback o_callback = nullptr;
|
|
||||||
|
|
||||||
ssize_t xread(int fd, void *buffer, size_t count) {
|
|
||||||
ssize_t total = 0;
|
ssize_t total = 0;
|
||||||
char *buf = (char *) buffer;
|
char *buf = (char *) buffer;
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
@ -32,7 +27,7 @@ ssize_t xread(int fd, void *buffer, size_t count) {
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t xwrite(int fd, void *buffer, size_t count) {
|
static inline ssize_t xwrite(int fd, void *buffer, size_t count) {
|
||||||
ssize_t total = 0;
|
ssize_t total = 0;
|
||||||
char *buf = (char *) buffer;
|
char *buf = (char *) buffer;
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
@ -45,6 +40,10 @@ ssize_t xwrite(int fd, void *buffer, size_t count) {
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
|
||||||
|
|
||||||
|
static T_Callback o_callback = nullptr;
|
||||||
|
|
||||||
static void modify_callback(void *cookie, const char *name, const char *value, uint32_t serial) {
|
static void modify_callback(void *cookie, const char *name, const char *value, uint32_t serial) {
|
||||||
|
|
||||||
if (cookie == nullptr || name == nullptr || value == nullptr || o_callback == nullptr) return;
|
if (cookie == nullptr || name == nullptr || value == nullptr || o_callback == nullptr) return;
|
||||||
@ -99,81 +98,71 @@ public:
|
|||||||
|
|
||||||
void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
|
void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
|
||||||
|
|
||||||
|
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
|
|
||||||
if (!args) {
|
if (!args) {
|
||||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *rawDir = env->GetStringUTFChars(args->app_data_dir, nullptr);
|
const char *dir = env->GetStringUTFChars(args->app_data_dir, nullptr);
|
||||||
|
|
||||||
if (!rawDir) {
|
if (!dir) {
|
||||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *rawName = env->GetStringUTFChars(args->nice_name, nullptr);
|
if (!std::string_view(dir).ends_with("/com.google.android.gms")) {
|
||||||
|
env->ReleaseStringUTFChars(args->app_data_dir, dir);
|
||||||
if (!rawName) {
|
|
||||||
env->ReleaseStringUTFChars(args->app_data_dir, rawDir);
|
|
||||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string dir(rawDir);
|
env->ReleaseStringUTFChars(args->app_data_dir, dir);
|
||||||
std::string name(rawName);
|
|
||||||
|
|
||||||
env->ReleaseStringUTFChars(args->app_data_dir, rawDir);
|
|
||||||
env->ReleaseStringUTFChars(args->nice_name, rawName);
|
|
||||||
|
|
||||||
if (!dir.ends_with("/com.google.android.gms")) {
|
|
||||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
|
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
|
||||||
|
|
||||||
if (name != "com.google.android.gms.unstable") {
|
const char *name = env->GetStringUTFChars(args->nice_name, nullptr);
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
long dexSize = 0, jsonSize = 0;
|
if (strncmp(name, "com.google.android.gms.unstable", 31) != 0) {
|
||||||
|
env->ReleaseStringUTFChars(args->nice_name, name);
|
||||||
|
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
env->ReleaseStringUTFChars(args->nice_name, name);
|
||||||
|
|
||||||
|
long size = 0;
|
||||||
|
std::vector<char> vector;
|
||||||
|
|
||||||
int fd = api->connectCompanion();
|
int fd = api->connectCompanion();
|
||||||
|
|
||||||
xread(fd, &dexSize, sizeof(long));
|
xread(fd, &size, sizeof(long));
|
||||||
xread(fd, &jsonSize, sizeof(long));
|
|
||||||
|
|
||||||
LOGD("Dex file size: %ld", dexSize);
|
if (size > 0) {
|
||||||
LOGD("Json file size: %ld", jsonSize);
|
vector.resize(size);
|
||||||
|
xread(fd, vector.data(), size);
|
||||||
if (dexSize < 1 || jsonSize < 1) {
|
json = nlohmann::json::parse(vector, nullptr, false, true);
|
||||||
close(fd);
|
} else {
|
||||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dexVector.resize(dexSize);
|
|
||||||
xread(fd, dexVector.data(), dexSize);
|
|
||||||
|
|
||||||
std::vector<uint8_t> jsonVector;
|
|
||||||
|
|
||||||
jsonVector.resize(jsonSize);
|
|
||||||
xread(fd, jsonVector.data(), jsonSize);
|
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
json = nlohmann::json::parse(jsonVector, nullptr, false, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
||||||
if (dexVector.empty() || json.empty()) return;
|
if (json.empty()) return;
|
||||||
|
|
||||||
parseJson();
|
parseJson();
|
||||||
|
|
||||||
injectDex();
|
injectDex();
|
||||||
|
|
||||||
doHook();
|
// doHook();
|
||||||
}
|
}
|
||||||
|
|
||||||
void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override {
|
void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override {
|
||||||
@ -183,7 +172,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
zygisk::Api *api = nullptr;
|
zygisk::Api *api = nullptr;
|
||||||
JNIEnv *env = nullptr;
|
JNIEnv *env = nullptr;
|
||||||
std::vector<uint8_t> dexVector;
|
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
|
|
||||||
void parseJson() {
|
void parseJson() {
|
||||||
@ -210,7 +198,7 @@ private:
|
|||||||
auto dexClClass = env->FindClass("dalvik/system/InMemoryDexClassLoader");
|
auto dexClClass = env->FindClass("dalvik/system/InMemoryDexClassLoader");
|
||||||
auto dexClInit = env->GetMethodID(dexClClass, "<init>",
|
auto dexClInit = env->GetMethodID(dexClClass, "<init>",
|
||||||
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
"(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
||||||
auto buffer = env->NewDirectByteBuffer(dexVector.data(), dexVector.size());
|
auto buffer = env->NewDirectByteBuffer(classes_dex, classes_dex_len);
|
||||||
auto dexCl = env->NewObject(dexClClass, dexClInit, buffer, systemClassLoader);
|
auto dexCl = env->NewObject(dexClClass, dexClInit, buffer, systemClassLoader);
|
||||||
|
|
||||||
LOGD("load class");
|
LOGD("load class");
|
||||||
@ -228,9 +216,9 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<uint8_t> readFile(const char *path) {
|
static std::vector<char> readFile(const char *path) {
|
||||||
|
|
||||||
std::vector<uint8_t> vector;
|
std::vector<char> vector;
|
||||||
|
|
||||||
FILE *file = fopen(path, "rb");
|
FILE *file = fopen(path, "rb");
|
||||||
|
|
||||||
@ -250,23 +238,17 @@ static std::vector<uint8_t> readFile(const char *path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void companion(int fd) {
|
static void companion(int fd) {
|
||||||
|
long size = 0;
|
||||||
|
std::vector<char> vector;
|
||||||
|
|
||||||
std::vector<uint8_t> dexVector, jsonVector;
|
vector = readFile(PIF_JSON);
|
||||||
|
|
||||||
dexVector = readFile(CLASSES_DEX);
|
if (vector.empty()) vector = readFile(PIF_JSON_DEFAULT);
|
||||||
|
|
||||||
jsonVector = readFile(PIF_JSON);
|
size = vector.size();
|
||||||
|
|
||||||
if (jsonVector.empty()) jsonVector = readFile(PIF_JSON_DEFAULT);
|
xwrite(fd, &size, sizeof(long));
|
||||||
|
xwrite(fd, vector.data(), size);
|
||||||
long dexSize = dexVector.size();
|
|
||||||
long jsonSize = jsonVector.size();
|
|
||||||
|
|
||||||
xwrite(fd, &dexSize, sizeof(long));
|
|
||||||
xwrite(fd, &jsonSize, sizeof(long));
|
|
||||||
|
|
||||||
xwrite(fd, dexVector.data(), dexSize);
|
|
||||||
xwrite(fd, jsonVector.data(), jsonSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_ZYGISK_MODULE(PlayIntegrityFix)
|
REGISTER_ZYGISK_MODULE(PlayIntegrityFix)
|
||||||
|
156
app/src/main/java/es/chiteroman/playintegrityfix/Android.java
Normal file
156
app/src/main/java/es/chiteroman/playintegrityfix/Android.java
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
package es.chiteroman.playintegrityfix;
|
||||||
|
|
||||||
|
import android.security.keystore.KeyProperties;
|
||||||
|
|
||||||
|
import org.spongycastle.asn1.ASN1Boolean;
|
||||||
|
import org.spongycastle.asn1.ASN1Encodable;
|
||||||
|
import org.spongycastle.asn1.ASN1EncodableVector;
|
||||||
|
import org.spongycastle.asn1.ASN1Enumerated;
|
||||||
|
import org.spongycastle.asn1.ASN1ObjectIdentifier;
|
||||||
|
import org.spongycastle.asn1.ASN1OctetString;
|
||||||
|
import org.spongycastle.asn1.ASN1Sequence;
|
||||||
|
import org.spongycastle.asn1.ASN1TaggedObject;
|
||||||
|
import org.spongycastle.asn1.DEROctetString;
|
||||||
|
import org.spongycastle.asn1.DERSequence;
|
||||||
|
import org.spongycastle.asn1.DERTaggedObject;
|
||||||
|
import org.spongycastle.asn1.x509.Extension;
|
||||||
|
import org.spongycastle.cert.X509CertificateHolder;
|
||||||
|
import org.spongycastle.cert.X509v3CertificateBuilder;
|
||||||
|
import org.spongycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||||
|
import org.spongycastle.openssl.PEMKeyPair;
|
||||||
|
import org.spongycastle.openssl.PEMParser;
|
||||||
|
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 java.io.ByteArrayInputStream;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
public final class Android {
|
||||||
|
private static final PEMKeyPair EC, RSA;
|
||||||
|
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 CertificateFactory certificateFactory;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
certificateFactory = CertificateFactory.getInstance("X.509");
|
||||||
|
|
||||||
|
EC = parseKeyPair(Keybox.EC.PRIVATE_KEY);
|
||||||
|
EC_CERTS.add(parseCert(Keybox.EC.CERTIFICATE_1));
|
||||||
|
EC_CERTS.add(parseCert(Keybox.EC.CERTIFICATE_2));
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PEMKeyPair parseKeyPair(String key) throws Throwable {
|
||||||
|
try (PEMParser parser = new PEMParser(new StringReader(key))) {
|
||||||
|
return (PEMKeyPair) parser.readObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Certificate parseCert(String cert) throws Throwable {
|
||||||
|
try (PemReader reader = new PemReader(new StringReader(cert))) {
|
||||||
|
return certificateFactory.generateCertificate(new ByteArrayInputStream(reader.readPemObject().getContent()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Certificate[] engineGetCertificateChain(Certificate[] caList) {
|
||||||
|
if (caList == null) throw new UnsupportedOperationException();
|
||||||
|
try {
|
||||||
|
X509Certificate leaf = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(caList[0].getEncoded()));
|
||||||
|
|
||||||
|
byte[] bytes = leaf.getExtensionValue(OID.getId());
|
||||||
|
|
||||||
|
if (bytes == null) return caList;
|
||||||
|
|
||||||
|
X509CertificateHolder holder = new X509CertificateHolder(leaf.getEncoded());
|
||||||
|
|
||||||
|
Extension ext = holder.getExtension(OID);
|
||||||
|
|
||||||
|
ASN1Sequence sequence = ASN1Sequence.getInstance(ext.getExtnValue().getOctets());
|
||||||
|
|
||||||
|
ASN1Encodable[] encodables = sequence.toArray();
|
||||||
|
|
||||||
|
ASN1Sequence teeEnforced = (ASN1Sequence) encodables[7];
|
||||||
|
|
||||||
|
ASN1EncodableVector vector = new ASN1EncodableVector();
|
||||||
|
|
||||||
|
for (ASN1Encodable asn1Encodable : teeEnforced) {
|
||||||
|
ASN1TaggedObject taggedObject = (ASN1TaggedObject) asn1Encodable;
|
||||||
|
if (taggedObject.getTagNo() == 704) continue;
|
||||||
|
vector.add(taggedObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkedList<Certificate> certificates;
|
||||||
|
|
||||||
|
X509v3CertificateBuilder builder;
|
||||||
|
ContentSigner signer;
|
||||||
|
|
||||||
|
if (KeyProperties.KEY_ALGORITHM_EC.equals(leaf.getPublicKey().getAlgorithm())) {
|
||||||
|
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 {
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] verifiedBootKey = new byte[32];
|
||||||
|
byte[] verifiedBootHash = new byte[32];
|
||||||
|
|
||||||
|
ThreadLocalRandom.current().nextBytes(verifiedBootKey);
|
||||||
|
ThreadLocalRandom.current().nextBytes(verifiedBootHash);
|
||||||
|
|
||||||
|
ASN1Encodable[] rootOfTrustEnc = {new DEROctetString(verifiedBootKey), ASN1Boolean.TRUE, new ASN1Enumerated(0), new DEROctetString(verifiedBootHash)};
|
||||||
|
|
||||||
|
ASN1Sequence rootOfTrustSeq = new DERSequence(rootOfTrustEnc);
|
||||||
|
|
||||||
|
ASN1TaggedObject rootOfTrustTagObj = new DERTaggedObject(704, rootOfTrustSeq);
|
||||||
|
|
||||||
|
vector.add(rootOfTrustTagObj);
|
||||||
|
|
||||||
|
ASN1Sequence hackEnforced = new DERSequence(vector);
|
||||||
|
|
||||||
|
encodables[7] = hackEnforced;
|
||||||
|
|
||||||
|
ASN1Sequence hackedSeq = new DERSequence(encodables);
|
||||||
|
|
||||||
|
ASN1OctetString hackedSeqOctets = new DEROctetString(hackedSeq);
|
||||||
|
|
||||||
|
Extension hackedExt = new Extension(OID, false, hackedSeqOctets);
|
||||||
|
|
||||||
|
builder.addExtension(hackedExt);
|
||||||
|
|
||||||
|
for (ASN1ObjectIdentifier extensionOID : holder.getExtensions().getExtensionOIDs()) {
|
||||||
|
if (OID.getId().equals(extensionOID.getId())) continue;
|
||||||
|
builder.addExtension(holder.getExtension(extensionOID));
|
||||||
|
}
|
||||||
|
|
||||||
|
certificates.addFirst(new JcaX509CertificateConverter().getCertificate(builder.build(signer)));
|
||||||
|
|
||||||
|
return certificates.toArray(new Certificate[0]);
|
||||||
|
|
||||||
|
} catch (Throwable t) {
|
||||||
|
EntryPoint.LOG(t.toString());
|
||||||
|
}
|
||||||
|
return caList;
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
import java.security.UnrecoverableKeyException;
|
import java.security.UnrecoverableKeyException;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -24,13 +25,9 @@ public final class CustomKeyStoreSpi extends KeyStoreSpi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Certificate[] engineGetCertificateChain(String alias) {
|
public Certificate[] engineGetCertificateChain(String alias) {
|
||||||
|
if (Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch(e -> e.getClassName().toLowerCase(Locale.US).contains("droidguard"))) {
|
||||||
for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {
|
return Android.engineGetCertificateChain(keyStoreSpi.engineGetCertificateChain(alias));
|
||||||
if (stackTraceElement.getClassName().toLowerCase(Locale.US).contains("droidguard")) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return keyStoreSpi.engineGetCertificateChain(alias);
|
return keyStoreSpi.engineGetCertificateChain(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
107
app/src/main/java/es/chiteroman/playintegrityfix/Keybox.java
Normal file
107
app/src/main/java/es/chiteroman/playintegrityfix/Keybox.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
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-----
|
||||||
|
""";
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,6 @@ If not, try removing /data/adb/pif.json file.
|
|||||||
Donations:
|
Donations:
|
||||||
https://www.paypal.com/paypalme/chiteroman
|
https://www.paypal.com/paypalme/chiteroman
|
||||||
|
|
||||||
# v15.9.9
|
# v16.0
|
||||||
|
|
||||||
- MEETS_DEVICE_INTEGRITY is green again ✅
|
- WORKING TEE = STRONG PASS
|
||||||
- Refine code logic
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
id=playintegrityfix
|
id=playintegrityfix
|
||||||
name=Play Integrity Fix
|
name=Play Integrity Fix (STRONG)
|
||||||
version=v15.9.9
|
version=v16.0
|
||||||
versionCode=15990
|
versionCode=16000
|
||||||
author=chiteroman
|
author=chiteroman
|
||||||
description=Universal modular fix for Play Integrity (and SafetyNet) on devices running Android 8-14.
|
description=WORKING TEE = STRONG PASS | THANKS GOOGLE
|
||||||
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json
|
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "v15.9.9",
|
"version": "v16.0",
|
||||||
"versionCode": 15990,
|
"versionCode": 16000,
|
||||||
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v15.9.9/PlayIntegrityFix_v15.9.9.zip",
|
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v16.0/PlayIntegrityFix_v16.0.zip",
|
||||||
"changelog": "https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/changelog.md"
|
"changelog": "https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/changelog.md"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user