Stable version v13.8

This commit is contained in:
chiteroman 2023-11-27 19:07:34 +01:00
parent 4dcf53b340
commit c950e21a3d
No known key found for this signature in database
GPG Key ID: 15FF53015D426D8E
19 changed files with 29 additions and 24972 deletions

3
.idea/.gitignore vendored
View File

@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" />
</component>
</project>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="jbr-17" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

View File

@ -1,10 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -28,11 +28,6 @@ It injects a classes.dex file to modify few fields in android.os.Build class. Al
it creates a hook to modify system properties. it creates a hook to modify system properties.
The purpose of the module is to avoid a hardware attestation. The purpose of the module is to avoid a hardware attestation.
## About 'pif.json' file
You can modify this file to spoof android.os.Build fields in GMS unstable process and try to pass Device verdict.
You can't use values from recent devices due this devices must use a hardware attestation.
## Failing BASIC verdict ## Failing BASIC verdict
If you are failing basicIntegrity (SafetyNet) or MEETS_BASIC_INTEGRITY (Play Integrity) something is If you are failing basicIntegrity (SafetyNet) or MEETS_BASIC_INTEGRITY (Play Integrity) something is

View File

@ -42,33 +42,4 @@ android {
path = file("src/main/cpp/Android.mk") path = file("src/main/cpp/Android.mk")
} }
} }
}
tasks.register("copyFiles") {
doLast {
val moduleFolder = project.rootDir.resolve("module")
val dexFile = project.buildDir.resolve("intermediates/dex/release/minifyReleaseWithR8/classes.dex")
val soDir = project.buildDir.resolve("intermediates/stripped_native_libs/release/out/lib")
dexFile.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true)
soDir.walk().filter { it.isFile && it.extension == "so" }.forEach { soFile ->
val abiFolder = soFile.parentFile.name
val destination = moduleFolder.resolve("zygisk/$abiFolder.so")
soFile.copyTo(destination, overwrite = true)
}
}
}
tasks.register<Zip>("zip") {
dependsOn("copyFiles")
archiveFileName.set("PlayIntegrityFix.zip")
destinationDirectory.set(project.rootDir.resolve("out"))
from(project.rootDir.resolve("module"))
}
afterEvaluate {
tasks["assembleRelease"].finalizedBy("copyFiles", "zip")
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,17 @@
#include <android/log.h> #include <android/log.h>
#include <sys/system_properties.h> #include <sys/system_properties.h>
#include <unistd.h> #include <map>
#include <fstream> #include <string_view>
#include "zygisk.hpp" #include "zygisk.hpp"
#include "shadowhook.h" #include "shadowhook.h"
#include "json.hpp" #include "classes_dex.h"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF/Native", __VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF/Native", __VA_ARGS__)
#define DEX_FILE_PATH "/data/adb/modules/playintegrityfix/classes.dex" #define FIRST_API_LEVEL "25"
#define JSON_FILE_PATH "/data/adb/modules/playintegrityfix/pif.json" #define SECURITY_PATCH "2018-07-05"
static std::string FIRST_API_LEVEL, SECURITY_PATCH;
typedef void (*T_Callback)(void *, const char *, const char *, uint32_t); typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
@ -28,18 +26,10 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
std::string_view prop(name); std::string_view prop(name);
if (prop.ends_with("api_level")) { if (prop.ends_with("api_level")) {
if (FIRST_API_LEVEL == "nullptr") { value = FIRST_API_LEVEL;
value = nullptr;
} else {
value = FIRST_API_LEVEL.c_str();
}
LOGD("[%s] -> %s", name, value); LOGD("[%s] -> %s", name, value);
} else if (prop.ends_with("security_patch")) { } else if (prop.ends_with("security_patch")) {
if (SECURITY_PATCH == "nullptr") { value = SECURITY_PATCH;
value = nullptr;
} else {
value = SECURITY_PATCH.c_str();
}
LOGD("[%s] -> %s", name, value); LOGD("[%s] -> %s", name, value);
} }
@ -85,67 +75,23 @@ public:
std::string_view process(rawProcess); std::string_view process(rawProcess);
bool isGms = process.starts_with("com.google.android.gms"); bool isGms = process.starts_with("com.google.android.gms");
bool isGmsUnstable = process.compare("com.google.android.gms.unstable") == 0; isGmsUnstable = process.compare("com.google.android.gms.unstable") == 0;
env->ReleaseStringUTFChars(args->nice_name, rawProcess); env->ReleaseStringUTFChars(args->nice_name, rawProcess);
if (!isGms) { if (isGms) api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT); if (isGmsUnstable) return;
if (!isGmsUnstable) { api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
int dexSize = 0;
int jsonSize = 0;
int fd = api->connectCompanion();
read(fd, &dexSize, sizeof(int));
read(fd, &jsonSize, sizeof(int));
if (dexSize < 1) {
close(fd);
LOGD("Couldn't read classes.dex");
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
if (jsonSize < 1) {
close(fd);
LOGD("Couldn't read pif.json");
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
dexVector.resize(dexSize);
jsonVector.resize(jsonSize);
read(fd, dexVector.data(), dexSize);
read(fd, jsonVector.data(), jsonSize);
close(fd);
LOGD("Read from file descriptor file 'classes.dex' -> %d bytes", dexSize);
LOGD("Read from file descriptor file 'pif.json' -> %d bytes", jsonSize);
} }
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override { void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
if (dexVector.empty() || jsonVector.empty()) return; if (!isGmsUnstable) return;
readJson();
doHook(); doHook();
inject(); inject();
dexVector.clear();
jsonVector.clear();
} }
void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override { void preServerSpecialize(zygisk::ServerSpecializeArgs *args) override {
@ -155,38 +101,7 @@ public:
private: private:
zygisk::Api *api = nullptr; zygisk::Api *api = nullptr;
JNIEnv *env = nullptr; JNIEnv *env = nullptr;
std::vector<char> dexVector, jsonVector; bool isGmsUnstable = false;
void readJson() {
std::string data(jsonVector.cbegin(), jsonVector.cend());
nlohmann::json json = nlohmann::json::parse(data, nullptr, false, true);
if (json.contains("SECURITY_PATCH")) {
if (json["SECURITY_PATCH"].is_null()) {
SECURITY_PATCH = "nullptr";
} else if (json["SECURITY_PATCH"].is_string()) {
SECURITY_PATCH = json["SECURITY_PATCH"].get<std::string>();
} else {
LOGD("Error parsing SECURITY_PATCH!");
}
} else {
LOGD("Key SECURITY_PATCH doesn't exist in JSON file!");
}
if (json.contains("FIRST_API_LEVEL")) {
if (json["FIRST_API_LEVEL"].is_null()) {
FIRST_API_LEVEL = "nullptr";
} else if (json["FIRST_API_LEVEL"].is_string()) {
FIRST_API_LEVEL = json["FIRST_API_LEVEL"].get<std::string>();
} else {
LOGD("Error parsing FIRST_API_LEVEL!");
}
} else {
LOGD("Key FIRST_API_LEVEL doesn't exist in JSON file!");
}
json.clear();
}
void inject() { void inject() {
LOGD("get system classloader"); LOGD("get system classloader");
@ -199,8 +114,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(), auto buffer = env->NewDirectByteBuffer(classes_dex, classes_dex_len);
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");
@ -211,38 +125,10 @@ private:
auto entryClass = (jclass) entryClassObj; auto entryClass = (jclass) entryClassObj;
LOGD("read json");
auto readProps = env->GetStaticMethodID(entryClass, "readJson",
"(Ljava/lang/String;)V");
std::string data(jsonVector.cbegin(), jsonVector.cend());
auto javaStr = env->NewStringUTF(data.c_str());
env->CallStaticVoidMethod(entryClass, readProps, javaStr);
LOGD("call init"); LOGD("call init");
auto entryInit = env->GetStaticMethodID(entryClass, "init", "()V"); auto entryInit = env->GetStaticMethodID(entryClass, "init", "()V");
env->CallStaticVoidMethod(entryClass, entryInit); env->CallStaticVoidMethod(entryClass, entryInit);
} }
}; };
static void companion(int fd) { REGISTER_ZYGISK_MODULE(PlayIntegrityFix)
std::ifstream dex(DEX_FILE_PATH, std::ios::binary);
std::ifstream json(JSON_FILE_PATH);
std::vector<char> dexVector((std::istreambuf_iterator<char>(dex)),
std::istreambuf_iterator<char>());
std::vector<char> jsonVector((std::istreambuf_iterator<char>(json)),
std::istreambuf_iterator<char>());
int dexSize = static_cast<int>(dexVector.size());
int jsonSize = static_cast<int>(jsonVector.size());
write(fd, &dexSize, sizeof(int));
write(fd, &jsonSize, sizeof(int));
write(fd, dexVector.data(), dexSize);
write(fd, jsonVector.data(), jsonSize);
}
REGISTER_ZYGISK_MODULE(PlayIntegrityFix)
REGISTER_ZYGISK_COMPANION(companion)

View File

@ -1,40 +1,29 @@
package es.chiteroman.playintegrityfix; package es.chiteroman.playintegrityfix;
import android.os.Build; import android.os.Build;
import android.util.JsonReader;
import android.util.Log; import android.util.Log;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.KeyStoreSpi; import java.security.KeyStoreSpi;
import java.security.Provider; import java.security.Provider;
import java.security.Security; import java.security.Security;
import java.util.HashMap;
import java.util.Map;
public final class EntryPoint { public final class EntryPoint {
private static final Map<String, String> map = new HashMap<>(); private static final String PRODUCT = "sailfish";
private static final String DEVICE = "sailfish";
private static final String MANUFACTURER = "Google";
private static final String BRAND = "google";
private static final String MODEL = "Pixel";
private static final String FINGERPRINT = "google/sailfish/sailfish:8.1.0/OPM4.171019.021.P1/4820305:user/release-keys";
private static final String SECURITY_PATCH = "2018-07-05";
public static void init() { public static void init() {
spoofProvider(); spoofProvider();
spoofDevice(); spoofDevice();
} }
public static void readJson(String data) {
try (JsonReader reader = new JsonReader(new StringReader(data))) {
reader.beginObject();
while (reader.hasNext()) {
map.put(reader.nextName(), reader.nextString());
}
reader.endObject();
} catch (IOException e) {
LOG("Couldn't read JSON from Zygisk: " + e);
}
}
private static void spoofProvider() { private static void spoofProvider() {
final String KEYSTORE = "AndroidKeyStore"; final String KEYSTORE = "AndroidKeyStore";
@ -63,15 +52,13 @@ public final class EntryPoint {
} }
static void spoofDevice() { static void spoofDevice() {
if (map.isEmpty()) return; setProp("PRODUCT", PRODUCT);
setProp("DEVICE", DEVICE);
setProp("PRODUCT", map.get("PRODUCT")); setProp("MANUFACTURER", MANUFACTURER);
setProp("DEVICE", map.get("DEVICE")); setProp("BRAND", BRAND);
setProp("MANUFACTURER", map.get("MANUFACTURER")); setProp("MODEL", MODEL);
setProp("BRAND", map.get("BRAND")); setProp("FINGERPRINT", FINGERPRINT);
setProp("MODEL", map.get("MODEL")); setVersionProp("SECURITY_PATCH", SECURITY_PATCH);
setProp("FINGERPRINT", map.get("FINGERPRINT"));
setVersionProp("SECURITY_PATCH", map.get("SECURITY_PATCH"));
} }
private static void setProp(String name, String value) { private static void setProp(String name, String value) {

View File

@ -1,33 +0,0 @@
#!/sbin/sh
#################
# Initialization
#################
umask 022
# echo before loading util_functions
ui_print() { echo "$1"; }
require_new_magisk() {
ui_print "*******************************"
ui_print " Please install Magisk v20.4+! "
ui_print "*******************************"
exit 1
}
#########################
# Load util_functions.sh
#########################
OUTFD=$2
ZIPFILE=$3
mount /data 2>/dev/null
[ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk
. /data/adb/magisk/util_functions.sh
[ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk
install_module
exit 0

View File

@ -1 +0,0 @@
#MAGISK

View File

@ -1,10 +0,0 @@
# Error on < Android 8
if [ "$API" -lt 26 ]; then
abort "!!! You can't use this module on Android < 8.0."
fi
# safetynet-fix module is incompatible
if [ -d "/data/adb/modules/safetynet-fix" ]; then
touch "/data/adb/modules/safetynet-fix/remove"
ui_print "- 'safetynet-fix' module will be removed in next reboot."
fi

View File

@ -1,7 +0,0 @@
id=playintegrityfix
name=Play Integrity Fix
version=PROPS-v2.0
versionCode=2000
author=chiteroman
description=Fix CTS profile (SafetyNet) and DEVICE verdict (Play Integrity).
updateJson=https://raw.githubusercontent.com/chiteroman/PlayIntegrityFix/main/update.json

View File

@ -1,10 +0,0 @@
{
"PRODUCT": "taimen",
"DEVICE": "taimen",
"MANUFACTURER": "Google",
"BRAND": "google",
"MODEL": "Pixel 2 XL",
"FINGERPRINT": "google/taimen/taimen:8.1.0/OPM4.171019.021.R1/4833808:user/release-keys",
"SECURITY_PATCH": "2018-07-05",
"FIRST_API_LEVEL": "25"
}

View File

@ -1,9 +0,0 @@
# Remove Play Services from the Magisk Denylist when set to enforcing
if magisk --denylist status; then
magisk --denylist rm com.google.android.gms
fi
# Check if safetynet-fix is installed
if [ -d "/data/adb/modules/safetynet-fix" ]; then
touch "/data/adb/modules/safetynet-fix/remove"
fi

View File

@ -1,46 +0,0 @@
# Sensitive properties
maybe_set_prop() {
local prop="$1"
local contains="$2"
local value="$3"
if [[ "$(getprop "$prop")" == *"$contains"* ]]; then
resetprop "$prop" "$value"
fi
}
# Magisk recovery mode
maybe_set_prop ro.bootmode recovery unknown
maybe_set_prop ro.boot.mode recovery unknown
maybe_set_prop vendor.boot.mode recovery unknown
# Hiding SELinux | Permissive status
resetprop --delete ro.build.selinux
# Hiding SELinux | Use toybox to protect *stat* access time reading
if [[ "$(toybox cat /sys/fs/selinux/enforce)" == "0" ]]; then
chmod 640 /sys/fs/selinux/enforce
chmod 440 /sys/fs/selinux/policy
fi
# Late props which must be set after boot_completed
{
until [[ "$(getprop sys.boot_completed)" == "1" ]]; do
sleep 1
done
# SafetyNet/Play Integrity | Avoid breaking Realme fingerprint scanners
resetprop ro.boot.flash.locked 1
# SafetyNet/Play Integrity | Avoid breaking Oppo fingerprint scanners
resetprop ro.boot.vbmeta.device_state locked
# SafetyNet/Play Integrity | Avoid breaking OnePlus display modes/fingerprint scanners
resetprop vendor.boot.verifiedbootstate green
# SafetyNet/Play Integrity | Avoid breaking OnePlus display modes/fingerprint scanners on OOS 12
resetprop ro.boot.verifiedbootstate green
resetprop ro.boot.veritymode enforcing
resetprop vendor.boot.vbmeta.device_state locked
}&

View File

@ -1,16 +0,0 @@
# RootBeer, Microsoft
ro.build.tags=release-keys
# Samsung
ro.boot.warranty_bit=0
ro.vendor.boot.warranty_bit=0
ro.vendor.warranty_bit=0
ro.warranty_bit=0
# OnePlus
ro.is_ever_orange=0
# Other
ro.build.type=user
ro.debuggable=0
ro.secure=1