Add SECURITY_PATCH and fix null props

This commit is contained in:
chiteroman 2023-11-21 14:04:33 +01:00
parent bf9ce4eb73
commit abc57e0a46
No known key found for this signature in database
GPG Key ID: 15FF53015D426D8E
11 changed files with 73 additions and 117 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,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<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,20 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="FieldCanBeLocal" enabled="true" level="WARNING" enabled_by_default="true">
<option name="EXCLUDE_ANNOS">
<value>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="android.annotation.TargetApi" />
</list>
</value>
</option>
<option name="IGNORE_FIELDS_USED_IN_MULTIPLE_METHODS" value="true" />
</inspection_tool>
<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,9 +0,0 @@
<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,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/src/main/cpp/libcxx" vcs="Git" />
</component>
</project>

View File

@ -1,31 +1,47 @@
# Play Integrity Fix
A Zygisk module which fix "ctsProfileMatch" (SafetyNet) and "MEETS_DEVICE_INTEGRITY" (Play Integrity).
A Zygisk module which fix "ctsProfileMatch" (SafetyNet) and "MEETS_DEVICE_INTEGRITY" (Play
Integrity).
To use this module you must have one of this:
- Magisk with Zygisk enabled.
- KernelSU with [ZygiskNext](https://github.com/Dr-TSNG/ZygiskNext) module installed.
[**Download the latest here**](https://github.com/chiteroman/PlayIntegrityFix/releases/latest).
## Telegram group
https://t.me/playintegrityfix
## Donations
- [PayPal](https://paypal.me/chiteroman)
## Official posts
- [XDA](https://xdaforums.com/t/module-play-integrity-fix-safetynet-fix.4607985/)
## About module
It injects a classes.dex file to modify few fields in android.os.Build class. Also, in native code it creates a hook to modify system properties.
It injects a classes.dex file to modify few fields in android.os.Build class. Also, in native code
it creates a hook to modify system properties.
The purpose of the module is to avoid a hardware attestation.
## Failing BASIC verdict
If you are failing basicIntegrity (SafetyNet) or MEETS_BASIC_INTEGRITY (Play Integrity) something is wrong in your setup. My recommended steps in order to find the problem:
If you are failing basicIntegrity (SafetyNet) or MEETS_BASIC_INTEGRITY (Play Integrity) something is
wrong in your setup. My recommended steps in order to find the problem:
- Disable all modules except mine.
- Check your SELinux (must be enforced).
Some modules which modify system can trigger DroidGuard detection, never hook GMS processes.
## Certify Play Store and fix Google Wallet
Follow this steps:
- Flash my module in Magisk/KernelSU (if you already have my module, just ignore this step).
- Clear Google Wallet cache.
- Clear Google Play Store cache.
@ -35,44 +51,18 @@ Follow this steps:
Reboot and done!
## Read module logs
You can read module logs using this command:
```
adb shell "logcat | grep 'PIF'"
```
## Can this module pass MEETS_STRONG_INTEGRITY?
**No**
## Play Integrity is now our problem, SafetyNet is deprecated
You can read more info here: [click me](https://xdaforums.com/t/info-play-integrity-api-replacement-for-safetynet.4479337/)
No.
## Make FCM Push back to work after cleared GSF data
Once you cleared GSF (Google Service Framework, com.google.android.gsf) data, a new DeviceID of Google Service Framework will be generated. So all the FCM tokens that have registered in the server of Apps will no longer work (it will point to your old DeviceID). You can follow these steps to make the Apps to generate a new FCM token.
## About Play Integrity, SafetyNet is deprecated
The idea is to delete a file called `xxx.gms.appid-no-backup` (xxx usually is the package name) in the app's files folder. Once the file does not exist, the app will generate a new FCM token when it starts up next time.
Run the following commands to do that, you can use `adb shell`, Termux, some terminal apps, or whatever.
1. Get the root user
```
su
```
2. cd to `/data/data`
```
cd /data/data
```
3. Search for the files ending with `gms.appid-no-backup` firstly (without really deleting it), so you can review the list of the files that will be deleted, and make sure it will not delete something wrong (usually it should not. I don't think any other useful files named like this). If you don't really care, you can skip this step.
```
find . -type f -name '*gms.appid-no-backup'
```
4. Delete all the files end with `gms.appid-no-backup`
```
find . -type f -name '*gms.appid-no-backup' -delete
```
5. Reboot your device.
6. It is better to launch the apps that receive FCM push one time, to make sure it generates a new FCM token and registers with the server.
You can read more info
here: [click me](https://xdaforums.com/t/info-play-integrity-api-replacement-for-safetynet.4479337/)

View File

@ -19,7 +19,7 @@ android {
ndk {
//noinspection ChromeOsAbiSupport
abiFilters += setOf("armeabi-v7a", "arm64-v8a")
jobs = 4
jobs = Runtime.getRuntime().availableProcessors()
}
}
}

View File

@ -19,7 +19,7 @@
#include <jni.h>
#define ZYGISK_API_VERSION 2
#define ZYGISK_API_VERSION 4
/*
@ -142,6 +142,7 @@ struct AppSpecializeArgs {
jint &gid;
jintArray &gids;
jint &runtime_flags;
jobjectArray &rlimits;
jint &mount_external;
jstring &se_info;
jstring &nice_name;
@ -149,6 +150,7 @@ struct AppSpecializeArgs {
jstring &app_data_dir;
// Optional arguments. Please check whether the pointer is null before de-referencing
jintArray *const fds_to_ignore;
jboolean *const is_child_zygote;
jboolean *const is_top_app;
jobjectArray *const pkg_data_info_list;
@ -241,6 +243,14 @@ struct Api {
// Returns bitwise-or'd zygisk::StateFlag values.
uint32_t getFlags();
// Exempt the provided file descriptor from being automatically closed.
//
// This API only make sense in preAppSpecialize; calling this method in any other situation
// is either a no-op (returns true) or an error (returns false).
//
// When false is returned, the provided file descriptor will eventually be closed by zygote.
bool exemptFd(int fd);
// Hook JNI native methods for a class
//
// Lookup all registered JNI native methods and replace it with your own methods.
@ -257,13 +267,10 @@ struct Api {
// 56b4346000-56b4347000 r-xp 00002000 fe:00 235 /system/bin/app_process64
// (More details: https://man7.org/linux/man-pages/man5/proc.5.html)
//
// For ELFs loaded in memory with pathname matching `regex`, replace function `symbol` with `newFunc`.
// The `dev` and `inode` pair uniquely identifies a file being mapped into memory.
// For matching ELFs loaded in memory, replace function `symbol` with `newFunc`.
// If `oldFunc` is not nullptr, the original function pointer will be saved to `oldFunc`.
void pltHookRegister(const char *regex, const char *symbol, void *newFunc, void **oldFunc);
// For ELFs loaded in memory with pathname matching `regex`, exclude hooks registered for `symbol`.
// If `symbol` is nullptr, then all symbols will be excluded.
void pltHookExclude(const char *regex, const char *symbol);
void pltHookRegister(dev_t dev, ino_t inode, const char *symbol, void *newFunc, void **oldFunc);
// Commit all the hooks that was previously registered.
// Returns false if an error occurred.
@ -324,8 +331,8 @@ struct api_table {
bool (*registerModule)(api_table *, module_abi *);
void (*hookJniNativeMethods)(JNIEnv *, const char *, JNINativeMethod *, int);
void (*pltHookRegister)(const char *, const char *, void *, void **);
void (*pltHookExclude)(const char *, const char *);
void (*pltHookRegister)(dev_t, ino_t, const char *, void *, void **);
bool (*exemptFd)(int);
bool (*pltHookCommit)();
int (*connectCompanion)(void * /* impl */);
void (*setOption)(void * /* impl */, Option);
@ -358,14 +365,14 @@ inline void Api::setOption(Option opt) {
inline uint32_t Api::getFlags() {
return tbl->getFlags ? tbl->getFlags(tbl->impl) : 0;
}
inline bool Api::exemptFd(int fd) {
return tbl->exemptFd != nullptr && tbl->exemptFd(fd);
}
inline void Api::hookJniNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int numMethods) {
if (tbl->hookJniNativeMethods) tbl->hookJniNativeMethods(env, className, methods, numMethods);
}
inline void Api::pltHookRegister(const char *regex, const char *symbol, void *newFunc, void **oldFunc) {
if (tbl->pltHookRegister) tbl->pltHookRegister(regex, symbol, newFunc, oldFunc);
}
inline void Api::pltHookExclude(const char *regex, const char *symbol) {
if (tbl->pltHookExclude) tbl->pltHookExclude(regex, symbol);
inline void Api::pltHookRegister(dev_t dev, ino_t inode, const char *symbol, void *newFunc, void **oldFunc) {
if (tbl->pltHookRegister) tbl->pltHookRegister(dev, inode, symbol, newFunc, oldFunc);
}
inline bool Api::pltHookCommit() {
return tbl->pltHookCommit != nullptr && tbl->pltHookCommit();

View File

@ -60,10 +60,17 @@ public final class EntryPoint {
}
public static void spoofDevice() {
props.forEach((field, value) -> setProp((String) field, (String) value));
setProp("PRODUCT", props.getProperty("PRODUCT"));
setProp("DEVICE", props.getProperty("DEVICE"));
setProp("MANUFACTURER", props.getProperty("MANUFACTURER"));
setProp("BRAND", props.getProperty("BRAND"));
setProp("MODEL", props.getProperty("MODEL"));
setProp("FINGERPRINT", props.getProperty("FINGERPRINT"));
setVersionProp("SECURITY_PATCH", props.getProperty("SECURITY_PATCH"));
}
private static void setProp(String name, String value) {
if (name == null || value == null || name.isEmpty() || value.isEmpty()) return;
try {
Field field = Build.class.getDeclaredField(name);
field.setAccessible(true);
@ -79,6 +86,23 @@ public final class EntryPoint {
}
}
private static void setVersionProp(String name, String value) {
if (name == null || value == null || name.isEmpty() || value.isEmpty()) return;
try {
Field field = Build.VERSION.class.getDeclaredField(name);
field.setAccessible(true);
String oldValue = (String) field.get(null);
field.set(null, value);
field.setAccessible(false);
if (value.equals(oldValue)) return;
LOG(String.format("[%s]: %s -> %s", name, oldValue, value));
} catch (NoSuchFieldException e) {
LOG(String.format("Couldn't find '%s' field name.", name));
} catch (IllegalAccessException e) {
LOG(String.format("Couldn't modify '%s' field value.", name));
}
}
public static void LOG(String msg) {
Log.d("PIF/Java", msg);
}

View File

@ -1,3 +1,3 @@
plugins {
id("com.android.application") version "8.1.3" apply false
id("com.android.application") version "8.1.4" apply false
}