mirror of
https://github.com/chiteroman/PlayIntegrityFix.git
synced 2025-01-19 03:22:39 +02:00
v16.4
This commit is contained in:
parent
fdfa3ee793
commit
8850f447a1
263
.idea/other.xml
Normal file
263
.idea/other.xml
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="direct_access_persist.xml">
|
||||||
|
<option name="deviceSelectionList">
|
||||||
|
<list>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="27" />
|
||||||
|
<option name="brand" value="DOCOMO" />
|
||||||
|
<option name="codename" value="F01L" />
|
||||||
|
<option name="id" value="F01L" />
|
||||||
|
<option name="manufacturer" value="FUJITSU" />
|
||||||
|
<option name="name" value="F-01L" />
|
||||||
|
<option name="screenDensity" value="360" />
|
||||||
|
<option name="screenX" value="720" />
|
||||||
|
<option name="screenY" value="1280" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="28" />
|
||||||
|
<option name="brand" value="DOCOMO" />
|
||||||
|
<option name="codename" value="SH-01L" />
|
||||||
|
<option name="id" value="SH-01L" />
|
||||||
|
<option name="manufacturer" value="SHARP" />
|
||||||
|
<option name="name" value="AQUOS sense2 SH-01L" />
|
||||||
|
<option name="screenDensity" value="480" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2160" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="31" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="a51" />
|
||||||
|
<option name="id" value="a51" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy A51" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="akita" />
|
||||||
|
<option name="id" value="akita" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 8a" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="b0q" />
|
||||||
|
<option name="id" value="b0q" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy S22 Ultra" />
|
||||||
|
<option name="screenDensity" value="600" />
|
||||||
|
<option name="screenX" value="1440" />
|
||||||
|
<option name="screenY" value="3088" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="32" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="bluejay" />
|
||||||
|
<option name="id" value="bluejay" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 6a" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="29" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="crownqlteue" />
|
||||||
|
<option name="id" value="crownqlteue" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy Note9" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="2220" />
|
||||||
|
<option name="screenY" value="1080" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="dm3q" />
|
||||||
|
<option name="id" value="dm3q" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy S23 Ultra" />
|
||||||
|
<option name="screenDensity" value="600" />
|
||||||
|
<option name="screenX" value="1440" />
|
||||||
|
<option name="screenY" value="3088" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="felix" />
|
||||||
|
<option name="id" value="felix" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel Fold" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="2208" />
|
||||||
|
<option name="screenY" value="1840" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="felix_camera" />
|
||||||
|
<option name="id" value="felix_camera" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel Fold (Camera-enabled)" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="2208" />
|
||||||
|
<option name="screenY" value="1840" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="gts8uwifi" />
|
||||||
|
<option name="id" value="gts8uwifi" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy Tab S8 Ultra" />
|
||||||
|
<option name="screenDensity" value="320" />
|
||||||
|
<option name="screenX" value="1848" />
|
||||||
|
<option name="screenY" value="2960" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="husky" />
|
||||||
|
<option name="id" value="husky" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 8 Pro" />
|
||||||
|
<option name="screenDensity" value="390" />
|
||||||
|
<option name="screenX" value="1008" />
|
||||||
|
<option name="screenY" value="2244" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="30" />
|
||||||
|
<option name="brand" value="motorola" />
|
||||||
|
<option name="codename" value="java" />
|
||||||
|
<option name="id" value="java" />
|
||||||
|
<option name="manufacturer" value="Motorola" />
|
||||||
|
<option name="name" value="G20" />
|
||||||
|
<option name="screenDensity" value="280" />
|
||||||
|
<option name="screenX" value="720" />
|
||||||
|
<option name="screenY" value="1600" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="lynx" />
|
||||||
|
<option name="id" value="lynx" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 7a" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="31" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="oriole" />
|
||||||
|
<option name="id" value="oriole" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 6" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="panther" />
|
||||||
|
<option name="id" value="panther" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 7" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="31" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="q2q" />
|
||||||
|
<option name="id" value="q2q" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy Z Fold3" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1768" />
|
||||||
|
<option name="screenY" value="2208" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="q5q" />
|
||||||
|
<option name="id" value="q5q" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy Z Fold5" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1812" />
|
||||||
|
<option name="screenY" value="2176" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="30" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="r11" />
|
||||||
|
<option name="id" value="r11" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel Watch" />
|
||||||
|
<option name="screenDensity" value="320" />
|
||||||
|
<option name="screenX" value="384" />
|
||||||
|
<option name="screenY" value="384" />
|
||||||
|
<option name="type" value="WEAR_OS" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="30" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="redfin" />
|
||||||
|
<option name="id" value="redfin" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 5" />
|
||||||
|
<option name="screenDensity" value="440" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2340" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="34" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="shiba" />
|
||||||
|
<option name="id" value="shiba" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel 8" />
|
||||||
|
<option name="screenDensity" value="420" />
|
||||||
|
<option name="screenX" value="1080" />
|
||||||
|
<option name="screenY" value="2400" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="33" />
|
||||||
|
<option name="brand" value="google" />
|
||||||
|
<option name="codename" value="tangorpro" />
|
||||||
|
<option name="id" value="tangorpro" />
|
||||||
|
<option name="manufacturer" value="Google" />
|
||||||
|
<option name="name" value="Pixel Tablet" />
|
||||||
|
<option name="screenDensity" value="320" />
|
||||||
|
<option name="screenX" value="1600" />
|
||||||
|
<option name="screenY" value="2560" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
<PersistentDeviceSelectionData>
|
||||||
|
<option name="api" value="29" />
|
||||||
|
<option name="brand" value="samsung" />
|
||||||
|
<option name="codename" value="x1q" />
|
||||||
|
<option name="id" value="x1q" />
|
||||||
|
<option name="manufacturer" value="Samsung" />
|
||||||
|
<option name="name" value="Galaxy S20" />
|
||||||
|
<option name="screenDensity" value="480" />
|
||||||
|
<option name="screenX" value="1440" />
|
||||||
|
<option name="screenY" value="3200" />
|
||||||
|
</PersistentDeviceSelectionData>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -16,11 +16,14 @@ android {
|
|||||||
applicationId = "es.chiteroman.playintegrityfix"
|
applicationId = "es.chiteroman.playintegrityfix"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 16300
|
versionCode = 16400
|
||||||
versionName = "v16.3"
|
versionName = "v16.4"
|
||||||
multiDexEnabled = false
|
multiDexEnabled = false
|
||||||
|
|
||||||
packaging {
|
packaging {
|
||||||
|
resources {
|
||||||
|
excludes += "META-INF/**"
|
||||||
|
}
|
||||||
jniLibs {
|
jniLibs {
|
||||||
excludes += "**/liblog.so"
|
excludes += "**/liblog.so"
|
||||||
excludes += "**/libdobby.so"
|
excludes += "**/libdobby.so"
|
||||||
@ -33,7 +36,7 @@ android {
|
|||||||
arguments += "-DCMAKE_BUILD_TYPE=MinSizeRel"
|
arguments += "-DCMAKE_BUILD_TYPE=MinSizeRel"
|
||||||
arguments += "-DPlugin.Android.BionicLinkerUtil=ON"
|
arguments += "-DPlugin.Android.BionicLinkerUtil=ON"
|
||||||
|
|
||||||
cppFlags += "-std=c++20"
|
cppFlags += "-std=c++2b"
|
||||||
cppFlags += "-fno-exceptions"
|
cppFlags += "-fno-exceptions"
|
||||||
cppFlags += "-fno-rtti"
|
cppFlags += "-fno-rtti"
|
||||||
cppFlags += "-fvisibility=hidden"
|
cppFlags += "-fvisibility=hidden"
|
||||||
@ -47,7 +50,9 @@ android {
|
|||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
isShrinkResources = true
|
isShrinkResources = true
|
||||||
multiDexEnabled = false
|
multiDexEnabled = false
|
||||||
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,8 +96,10 @@ tasks.register("copyFiles") {
|
|||||||
|
|
||||||
doLast {
|
doLast {
|
||||||
val moduleFolder = project.rootDir.resolve("module")
|
val moduleFolder = project.rootDir.resolve("module")
|
||||||
val dexFile = project.layout.buildDirectory.get().asFile.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex")
|
val dexFile =
|
||||||
val soDir = project.layout.buildDirectory.get().asFile.resolve("intermediates/stripped_native_libs/release/stripReleaseDebugSymbols/out/lib")
|
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)
|
||||||
|
|
||||||
|
7
app/proguard-rules.pro
vendored
7
app/proguard-rules.pro
vendored
@ -1,4 +1,3 @@
|
|||||||
-keep class es.chiteroman.playintegrityfix.EntryPoint {public <methods>;}
|
-keep class es.chiteroman.playintegrityfix.EntryPoint {*;}
|
||||||
-keep class es.chiteroman.playintegrityfix.CustomProvider
|
-keep class es.chiteroman.playintegrityfix.CustomKeyStoreSpi {*;}
|
||||||
-keep class es.chiteroman.playintegrityfix.CustomKeyStoreSpi
|
-keep class es.chiteroman.playintegrityfix.CustomProvider {*;}
|
||||||
-keep class es.chiteroman.playintegrityfix.KeyboxUtils
|
|
12962
app/src/main/cpp/dex.h
12962
app/src/main/cpp/dex.h
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,7 @@
|
|||||||
#include "zygisk.hpp"
|
#include "zygisk.hpp"
|
||||||
|
|
||||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF", __VA_ARGS__)
|
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF", __VA_ARGS__)
|
||||||
|
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "PIF", __VA_ARGS__)
|
||||||
|
|
||||||
#define DEX_PATH "/data/adb/modules/playintegrityfix/classes.dex"
|
#define DEX_PATH "/data/adb/modules/playintegrityfix/classes.dex"
|
||||||
|
|
||||||
@ -14,10 +15,6 @@
|
|||||||
|
|
||||||
#define PIF_JSON_DEFAULT "/data/adb/modules/playintegrityfix/pif.json"
|
#define PIF_JSON_DEFAULT "/data/adb/modules/playintegrityfix/pif.json"
|
||||||
|
|
||||||
#define KEYBOX_JSON "/data/adb/keybox.xml"
|
|
||||||
|
|
||||||
#define KEYBOX_JSON_DEFAULT "/data/adb/modules/playintegrityfix/keybox.xml"
|
|
||||||
|
|
||||||
static ssize_t xread(int fd, void *buffer, size_t count) {
|
static 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;
|
||||||
@ -56,7 +53,7 @@ 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("first_api_level") && !DEVICE_INITIAL_SDK_INT.empty()) {
|
if (prop.ends_with("first_api_level")) {
|
||||||
value = DEVICE_INITIAL_SDK_INT.c_str();
|
value = DEVICE_INITIAL_SDK_INT.c_str();
|
||||||
LOGD("[%s]: %s", name, value);
|
LOGD("[%s]: %s", name, value);
|
||||||
}
|
}
|
||||||
@ -76,6 +73,7 @@ my_system_property_read_callback(const prop_info *pi, T_Callback callback, void
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void doHook() {
|
static void doHook() {
|
||||||
|
|
||||||
void *handle = DobbySymbolResolver(nullptr, "__system_property_read_callback");
|
void *handle = DobbySymbolResolver(nullptr, "__system_property_read_callback");
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
LOGD("Couldn't hook __system_property_read_callback");
|
LOGD("Couldn't hook __system_property_read_callback");
|
||||||
@ -136,38 +134,32 @@ public:
|
|||||||
|
|
||||||
int fd = api->connectCompanion();
|
int fd = api->connectCompanion();
|
||||||
|
|
||||||
int dexSize = 0, jsonSize = 0, keyboxSize = 0;
|
int dexSize = 0, jsonSize = 0;
|
||||||
std::vector<char> jsonVector, keyboxVector;
|
std::vector<char> jsonVector;
|
||||||
|
|
||||||
xread(fd, &dexSize, sizeof(int));
|
xread(fd, &dexSize, sizeof(int));
|
||||||
xread(fd, &jsonSize, sizeof(int));
|
xread(fd, &jsonSize, sizeof(int));
|
||||||
xread(fd, &keyboxSize, sizeof(int));
|
|
||||||
|
|
||||||
dexVector.resize(dexSize);
|
dexVector.resize(dexSize);
|
||||||
xread(fd, dexVector.data(), dexSize);
|
xread(fd, dexVector.data(), dexSize);
|
||||||
|
|
||||||
|
if (jsonSize > 0) {
|
||||||
jsonVector.resize(jsonSize);
|
jsonVector.resize(jsonSize);
|
||||||
xread(fd, jsonVector.data(), jsonSize);
|
xread(fd, jsonVector.data(), jsonSize);
|
||||||
|
json = nlohmann::json::parse(jsonVector, nullptr, false, true);
|
||||||
keyboxVector.resize(keyboxSize);
|
}
|
||||||
xread(fd, keyboxVector.data(), keyboxSize);
|
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
json = nlohmann::json::parse(jsonVector, nullptr, false, true);
|
LOGD("Dex file size: %d", dexSize);
|
||||||
|
LOGD("Json file size: %d", jsonSize);
|
||||||
keyboxString = std::string(keyboxVector.cbegin(), keyboxVector.cend());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
||||||
if (dexVector.empty() || json.empty()) return;
|
if (dexVector.empty()) return;
|
||||||
|
|
||||||
if (json.contains("DEVICE_INITIAL_SDK_INT")) {
|
if (needHook()) doHook();
|
||||||
DEVICE_INITIAL_SDK_INT = json["DEVICE_INITIAL_SDK_INT"].get<std::string>();
|
else api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
json.erase("DEVICE_INITIAL_SDK_INT"); // You can't modify field value
|
|
||||||
}
|
|
||||||
|
|
||||||
doHook();
|
|
||||||
|
|
||||||
injectDex();
|
injectDex();
|
||||||
}
|
}
|
||||||
@ -181,7 +173,25 @@ private:
|
|||||||
JNIEnv *env = nullptr;
|
JNIEnv *env = nullptr;
|
||||||
std::vector<char> dexVector;
|
std::vector<char> dexVector;
|
||||||
nlohmann::json json;
|
nlohmann::json json;
|
||||||
std::string keyboxString;
|
|
||||||
|
bool needHook() {
|
||||||
|
if (json.contains("DEVICE_INITIAL_SDK_INT")) {
|
||||||
|
if (json["DEVICE_INITIAL_SDK_INT"].is_string()) {
|
||||||
|
DEVICE_INITIAL_SDK_INT = json["DEVICE_INITIAL_SDK_INT"].get<std::string>();
|
||||||
|
} else if (json["DEVICE_INITIAL_SDK_INT"].is_number_integer()) {
|
||||||
|
DEVICE_INITIAL_SDK_INT = std::to_string(json["DEVICE_INITIAL_SDK_INT"].get<int>());
|
||||||
|
} else {
|
||||||
|
LOGE("Couldn't parse DEVICE_INITIAL_SDK_INT from JSON file!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value can't be modified, it's marked as SystemApi field
|
||||||
|
json.erase("DEVICE_INITIAL_SDK_INT");
|
||||||
|
|
||||||
|
return !DEVICE_INITIAL_SDK_INT.empty();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void injectDex() {
|
void injectDex() {
|
||||||
LOGD("get system classloader");
|
LOGD("get system classloader");
|
||||||
@ -194,7 +204,8 @@ 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(dexVector.data(),
|
||||||
|
static_cast<jlong>(dexVector.size()));
|
||||||
auto dexCl = env->NewObject(dexClClass, dexClInit, buffer, systemClassLoader);
|
auto dexCl = env->NewObject(dexClClass, dexClInit, buffer, systemClassLoader);
|
||||||
|
|
||||||
LOGD("load class");
|
LOGD("load class");
|
||||||
@ -206,11 +217,9 @@ private:
|
|||||||
auto entryPointClass = (jclass) entryClassObj;
|
auto entryPointClass = (jclass) entryClassObj;
|
||||||
|
|
||||||
LOGD("call init");
|
LOGD("call init");
|
||||||
auto entryInit = env->GetStaticMethodID(entryPointClass, "init",
|
auto entryInit = env->GetStaticMethodID(entryPointClass, "init", "(Ljava/lang/String;)V");
|
||||||
"(Ljava/lang/String;Ljava/lang/String;)V");
|
|
||||||
auto jsonStr = env->NewStringUTF(json.dump().c_str());
|
auto jsonStr = env->NewStringUTF(json.dump().c_str());
|
||||||
auto keyboxStr = env->NewStringUTF(keyboxString.c_str());
|
env->CallStaticVoidMethod(entryPointClass, entryInit, jsonStr);
|
||||||
env->CallStaticVoidMethod(entryPointClass, entryInit, jsonStr, keyboxStr);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -218,12 +227,9 @@ static std::vector<char> readFile(const std::string &path) {
|
|||||||
|
|
||||||
std::ifstream ifs(path);
|
std::ifstream ifs(path);
|
||||||
|
|
||||||
if (!ifs || ifs.bad()) {
|
if (!ifs || ifs.bad()) return {};
|
||||||
return std::vector<char>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::vector<char>((std::istreambuf_iterator<char>(ifs)),
|
return {(std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()};
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void companion(int fd) {
|
static void companion(int fd) {
|
||||||
@ -233,20 +239,17 @@ static void companion(int fd) {
|
|||||||
auto json = readFile(PIF_JSON);
|
auto json = readFile(PIF_JSON);
|
||||||
if (json.empty()) json = readFile(PIF_JSON_DEFAULT);
|
if (json.empty()) json = readFile(PIF_JSON_DEFAULT);
|
||||||
|
|
||||||
auto keybox = readFile(KEYBOX_JSON);
|
int dexSize = static_cast<int>(dex.size());
|
||||||
if (keybox.empty()) keybox = readFile(KEYBOX_JSON_DEFAULT);
|
int jsonSize = static_cast<int>(json.size());
|
||||||
|
|
||||||
int dexSize = dex.size();
|
|
||||||
int jsonSize = json.size();
|
|
||||||
int keyboxSize = keybox.size();
|
|
||||||
|
|
||||||
xwrite(fd, &dexSize, sizeof(int));
|
xwrite(fd, &dexSize, sizeof(int));
|
||||||
xwrite(fd, &jsonSize, sizeof(int));
|
xwrite(fd, &jsonSize, sizeof(int));
|
||||||
xwrite(fd, &keyboxSize, sizeof(int));
|
|
||||||
|
|
||||||
xwrite(fd, dex.data(), dexSize * sizeof(char));
|
xwrite(fd, dex.data(), dexSize * sizeof(char));
|
||||||
|
|
||||||
|
if (jsonSize > 0) {
|
||||||
xwrite(fd, json.data(), jsonSize * sizeof(char));
|
xwrite(fd, json.data(), jsonSize * sizeof(char));
|
||||||
xwrite(fd, keybox.data(), keyboxSize * sizeof(char));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_ZYGISK_MODULE(PlayIntegrityFix)
|
REGISTER_ZYGISK_MODULE(PlayIntegrityFix)
|
||||||
|
@ -26,13 +26,16 @@ 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"))) {
|
if (Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch(e -> e.getClassName().toLowerCase(Locale.US).contains("droidguard"))) {
|
||||||
return KeyboxUtils.engineGetCertificateChain(keyStoreSpi.engineGetCertificateChain(alias));
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
return keyStoreSpi.engineGetCertificateChain(alias);
|
return keyStoreSpi.engineGetCertificateChain(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Certificate engineGetCertificate(String alias) {
|
public Certificate engineGetCertificate(String alias) {
|
||||||
|
if (Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch(e -> e.getClassName().toLowerCase(Locale.US).contains("droidguard"))) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
return keyStoreSpi.engineGetCertificate(alias);
|
return keyStoreSpi.engineGetCertificate(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,12 +12,11 @@ public final class CustomProvider extends Provider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Service getService(String type, String algorithm) {
|
public synchronized Service getService(String type, String algorithm) {
|
||||||
EntryPoint.LOG(String.format("Service: '%s' | Algorithm: '%s'", type, algorithm));
|
if ("KeyStore".equals(type)) {
|
||||||
|
|
||||||
Thread t = new Thread(EntryPoint::spoofFields);
|
Thread t = new Thread(EntryPoint::spoofFields);
|
||||||
t.setDaemon(true);
|
t.setDaemon(true);
|
||||||
t.start();
|
t.start();
|
||||||
|
}
|
||||||
return super.getService(type, algorithm);
|
return super.getService(type, algorithm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package es.chiteroman.playintegrityfix;
|
package es.chiteroman.playintegrityfix;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -14,6 +15,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public final class EntryPoint {
|
public final class EntryPoint {
|
||||||
|
public static final String TAG = "PIF";
|
||||||
private static final Map<Field, String> map = new HashMap<>();
|
private static final Map<Field, String> map = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -26,7 +28,7 @@ public final class EntryPoint {
|
|||||||
CustomKeyStoreSpi.keyStoreSpi = (KeyStoreSpi) keyStoreSpi.get(keyStore);
|
CustomKeyStoreSpi.keyStoreSpi = (KeyStoreSpi) keyStoreSpi.get(keyStore);
|
||||||
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
LOG("Couldn't get keyStoreSpi: " + t);
|
Log.e(TAG, "Couldn't get keyStoreSpi field!", t);
|
||||||
}
|
}
|
||||||
|
|
||||||
Provider provider = Security.getProvider("AndroidKeyStore");
|
Provider provider = Security.getProvider("AndroidKeyStore");
|
||||||
@ -37,7 +39,7 @@ public final class EntryPoint {
|
|||||||
Security.insertProviderAt(customProvider, 1);
|
Security.insertProviderAt(customProvider, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void init(String json, String kbox) {
|
public static void init(String json) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JSONObject jsonObject = new JSONObject(json);
|
JSONObject jsonObject = new JSONObject(json);
|
||||||
@ -45,32 +47,26 @@ public final class EntryPoint {
|
|||||||
jsonObject.keys().forEachRemaining(s -> {
|
jsonObject.keys().forEachRemaining(s -> {
|
||||||
try {
|
try {
|
||||||
String value = jsonObject.getString(s);
|
String value = jsonObject.getString(s);
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(value)) return;
|
||||||
|
|
||||||
Field field = getFieldByName(s);
|
Field field = getFieldByName(s);
|
||||||
|
|
||||||
if (field == null) {
|
if (field == null) return;
|
||||||
LOG("Field " + s + " not found!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
map.put(field, value);
|
map.put(field, value);
|
||||||
LOG("Save " + field.getName() + " with value: " + value);
|
|
||||||
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
LOG("Couldn't parse " + s + " key!");
|
Log.e(TAG, "Error parsing JSON", t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.e(TAG, "Error parsing JSON", t);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i(TAG, "Fields ready to spoof: " + map.size());
|
||||||
|
|
||||||
spoofFields();
|
spoofFields();
|
||||||
|
|
||||||
} 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() {
|
static void spoofFields() {
|
||||||
@ -78,16 +74,22 @@ public final class EntryPoint {
|
|||||||
try {
|
try {
|
||||||
if (s.equals(field.get(null))) return;
|
if (s.equals(field.get(null))) return;
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
|
String oldValue = String.valueOf(field.get(null));
|
||||||
field.set(null, s);
|
field.set(null, s);
|
||||||
LOG("Set " + field.getName() + " field value: " + s);
|
Log.d(TAG, String.format("""
|
||||||
|
---------------------------------------
|
||||||
|
[%s]
|
||||||
|
OLD: '%s'
|
||||||
|
NEW: '%s'
|
||||||
|
---------------------------------------
|
||||||
|
""", field.getName(), oldValue, field.get(null)));
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
LOG(t.toString());
|
Log.e(TAG, "Error modifying field", t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Field getFieldByName(String name) {
|
private static Field getFieldByName(String name) {
|
||||||
|
|
||||||
Field field;
|
Field field;
|
||||||
try {
|
try {
|
||||||
field = Build.class.getDeclaredField(name);
|
field = Build.class.getDeclaredField(name);
|
||||||
@ -98,13 +100,7 @@ public final class EntryPoint {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
|
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LOG(String msg) {
|
|
||||||
Log.d("PIF", msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,216 +0,0 @@
|
|||||||
package es.chiteroman.playintegrityfix;
|
|
||||||
|
|
||||||
import android.security.keystore.KeyProperties;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
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 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.LinkedList;
|
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
|
|
||||||
public final class KeyboxUtils {
|
|
||||||
private static final ASN1ObjectIdentifier OID = new ASN1ObjectIdentifier("1.3.6.1.4.1.11129.2.1.17");
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void parseXml(String kbox) throws Throwable {
|
|
||||||
if (TextUtils.isEmpty(kbox)) return;
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
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()));
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
// 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("SHA256withRSA").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());
|
|
||||||
}
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,3 @@
|
|||||||
buildscript {
|
|
||||||
val agp_version by extra("8.3.2")
|
|
||||||
}
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application") version "8.3.2" apply false
|
id("com.android.application") version "8.5.0" apply false
|
||||||
}
|
}
|
16
changelog.md
16
changelog.md
@ -7,16 +7,8 @@ If not, try removing /data/adb/pif.json file.
|
|||||||
Donations:
|
Donations:
|
||||||
https://www.paypal.com/paypalme/chiteroman
|
https://www.paypal.com/paypalme/chiteroman
|
||||||
|
|
||||||
# v16.3
|
# v16.4
|
||||||
|
|
||||||
Google fixed the bug, no more Strong pass with SW keybox 😢
|
- Misc improvements in code
|
||||||
|
- Remove keybox.xml parsing due DroidGuard detections (better use [FrameworkPatch](https://github.com/chiteroman/FrameworkPatch))
|
||||||
- Improve C++ and Java code
|
- Add BOARD and HARDWARE fields in json
|
||||||
- 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 exists 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
|
|
||||||
|
@ -1,114 +0,0 @@
|
|||||||
<?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
|
id=playintegrityfix
|
||||||
name=Play Integrity Fix
|
name=Play Integrity Fix
|
||||||
version=v16.3
|
version=v16.4
|
||||||
versionCode=16300
|
versionCode=16400
|
||||||
author=chiteroman
|
author=chiteroman
|
||||||
description=Universal modular fix for Play Integrity (and SafetyNet) on devices running Android 8-15
|
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
|
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"MANUFACTURER": "Google",
|
"ID": "OPM1.171019.011",
|
||||||
"MODEL": "Pixel",
|
|
||||||
"FINGERPRINT": "google/sailfish/sailfish:8.1.0/OPM1.171019.011/4448085:user/release-keys",
|
|
||||||
"BRAND": "google",
|
|
||||||
"PRODUCT": "sailfish",
|
"PRODUCT": "sailfish",
|
||||||
"DEVICE": "sailfish",
|
"DEVICE": "sailfish",
|
||||||
"RELEASE": "8.1.0",
|
"BOARD": "",
|
||||||
"ID": "OPM1.171019.011",
|
"MANUFACTURER": "Google",
|
||||||
|
"BRAND": "google",
|
||||||
|
"MODEL": "Pixel",
|
||||||
|
"HARDWARE": "",
|
||||||
"INCREMENTAL": "4448085",
|
"INCREMENTAL": "4448085",
|
||||||
"TYPE": "user",
|
"RELEASE": "8.1.0",
|
||||||
"TAGS": "release-keys",
|
|
||||||
"SECURITY_PATCH": "2017-12-05",
|
"SECURITY_PATCH": "2017-12-05",
|
||||||
"DEVICE_INITIAL_SDK_INT": "24"
|
"DEVICE_INITIAL_SDK_INT": "24",
|
||||||
|
"FINGERPRINT": "google/sailfish/sailfish:8.1.0/OPM1.171019.011/4448085:user/release-keys"
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "v16.3",
|
"version": "v16.4",
|
||||||
"versionCode": 16300,
|
"versionCode": 16400,
|
||||||
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v16.3/PlayIntegrityFix_v16.3.zip",
|
"zipUrl": "https://github.com/chiteroman/PlayIntegrityFix/releases/download/v16.4/PlayIntegrityFix_v16.4.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