You've already forked PlayIntegrityFork
mirror of
https://github.com/osm0sis/PlayIntegrityFork.git
synced 2025-09-06 06:37:06 +00:00
Compare commits
177 Commits
v9
...
1afd4278be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1afd4278be | ||
|
|
77d5ccdc99 | ||
|
|
a2f726b633 | ||
|
|
38631f685a | ||
|
|
39d2610579 | ||
|
|
0132ebb272 | ||
|
|
a82914221e | ||
|
|
4755f88180 | ||
|
|
62150ce6d4 | ||
|
|
88573ca743 | ||
|
|
89de098a83 | ||
|
|
c6739dfa42 | ||
|
|
a7dd416873 | ||
|
|
539ff7351a | ||
|
|
0cd56584df | ||
|
|
2cdee60781 | ||
|
|
7e376e5627 | ||
|
|
ec34417cd9 | ||
|
|
0b957b13b9 | ||
|
|
ec374a7d9b | ||
|
|
17db1e7177 | ||
|
|
451769c341 | ||
|
|
77f91e3a85 | ||
|
|
b4eae8a6b6 | ||
|
|
05520f7881 | ||
|
|
1745060524 | ||
|
|
512ed8a1f1 | ||
|
|
0d8d090014 | ||
|
|
0d03f99499 | ||
|
|
85dd219ea3 | ||
|
|
36cc9573ba | ||
|
|
d72fc9ee04 | ||
|
|
84adafc3ac | ||
|
|
cb49481c45 | ||
|
|
b5a9b26b70 | ||
|
|
39922653db | ||
|
|
58f2c2de57 | ||
|
|
e858134828 | ||
|
|
fafaf418e4 | ||
|
|
da758bc33c | ||
|
|
d66260c3f6 | ||
|
|
1a01e35862 | ||
|
|
028e94e71b | ||
|
|
9e04c5cc5b | ||
|
|
46e5e0a6d2 | ||
|
|
d2db871892 | ||
|
|
7e7812bede | ||
|
|
c2af0fcad5 | ||
|
|
1493650b65 | ||
|
|
3f62cb6a3a | ||
|
|
5daf1b933e | ||
|
|
e8375a02d1 | ||
|
|
fa937983e8 | ||
|
|
83b9d96ce4 | ||
|
|
4bcf51ccfd | ||
|
|
e653659895 | ||
|
|
11e2629a26 | ||
|
|
8805c3736d | ||
|
|
a52cc16b43 | ||
|
|
4740d2048d | ||
|
|
e2b8a3c4b0 | ||
|
|
4dbe12ae58 | ||
|
|
996981a8e7 | ||
|
|
d278b77ced | ||
|
|
a3f68d392e | ||
|
|
9b3801a117 | ||
|
|
df5d5b7ce9 | ||
|
|
b644573e52 | ||
|
|
3e30d553c9 | ||
|
|
8a64752923 | ||
|
|
264a218a79 | ||
|
|
59781b1682 | ||
|
|
a4c8aab031 | ||
|
|
abe69d201b | ||
|
|
da0fad725a | ||
|
|
d9794b2017 | ||
|
|
d08ca33633 | ||
|
|
a7ba40a36c | ||
|
|
140c32befd | ||
|
|
6fc3200df2 | ||
|
|
c3ee7e5c0a | ||
|
|
c635a9e3ba | ||
|
|
8ddab06840 | ||
|
|
16002e28c6 | ||
|
|
148dea0344 | ||
|
|
e01b3b5ada | ||
|
|
4666737242 | ||
|
|
cd32f0cb0a | ||
|
|
4e96fdef9d | ||
|
|
19d31cffea | ||
|
|
1edc85dec4 | ||
|
|
f351c97b2b | ||
|
|
0de5574d53 | ||
|
|
3f346f3735 | ||
|
|
b83de28f0b | ||
|
|
bc591c5732 | ||
|
|
7233c66f8a | ||
|
|
78dd16ae09 | ||
|
|
240a52b558 | ||
|
|
785622321e | ||
|
|
565d895a96 | ||
|
|
7dd9ed8f1d | ||
|
|
2e74733319 | ||
|
|
153aefbe57 | ||
|
|
91231e12f2 | ||
|
|
787936d94f | ||
|
|
fe57017255 | ||
|
|
0d05112f38 | ||
|
|
d8ff58d9ca | ||
|
|
ea65aef097 | ||
|
|
ebdbccdad2 | ||
|
|
08e3fb4d29 | ||
|
|
a671c3b0d3 | ||
|
|
c13a7b1299 | ||
|
|
629de14990 | ||
|
|
bd4fdcf0c3 | ||
|
|
8c216e2d40 | ||
|
|
27fc24337b | ||
|
|
796f776534 | ||
|
|
c972637347 | ||
|
|
b10828f199 | ||
|
|
726aecb2be | ||
|
|
a790f2c0db | ||
|
|
165d370bc8 | ||
|
|
915b87e6be | ||
|
|
1255a49274 | ||
|
|
6cc82e3e7b | ||
|
|
87fde1f4ca | ||
|
|
d535747c91 | ||
|
|
98bb23460e | ||
|
|
027e5855a0 | ||
|
|
8d2d1ecbd2 | ||
|
|
3775b5448e | ||
|
|
00023fb111 | ||
|
|
481491758c | ||
|
|
b42773671a | ||
|
|
3d55dc59c1 | ||
|
|
33f4fa2ce0 | ||
|
|
2857e3d2f8 | ||
|
|
4b8d6497d0 | ||
|
|
f3a7f3d5e9 | ||
|
|
bee755d8f3 | ||
|
|
dd4db53ca2 | ||
|
|
c30b3ab8a8 | ||
|
|
9d0a67d119 | ||
|
|
667efdd6a6 | ||
|
|
6e7377b3de | ||
|
|
98ab70a0b6 | ||
|
|
418e7306e3 | ||
|
|
44420c89ab | ||
|
|
adcdd80d65 | ||
|
|
096c8941b9 | ||
|
|
a926c520f2 | ||
|
|
9ef7a7f04e | ||
|
|
e9c1ec1d5d | ||
|
|
a7c2f348ea | ||
|
|
a5d9980ea7 | ||
|
|
58db03d596 | ||
|
|
64e412c351 | ||
|
|
914750104f | ||
|
|
1db82e2ccb | ||
|
|
f20c2dff1e | ||
|
|
620581b4de | ||
|
|
ebfd0c292a | ||
|
|
3e58be1e24 | ||
|
|
662b9c59c7 | ||
|
|
0bc9a4543a | ||
|
|
e3e4bbb95f | ||
|
|
7c3d0bd8dd | ||
|
|
b26b043a02 | ||
|
|
5aabd4b6b5 | ||
|
|
6d173fb3a1 | ||
|
|
efa3e98a94 | ||
|
|
8756c3963a | ||
|
|
6109918511 | ||
|
|
0386e085b5 | ||
|
|
b24d538e82 |
5
.github/workflows/android.yml
vendored
5
.github/workflows/android.yml
vendored
@@ -1,6 +1,7 @@
|
||||
name: Android CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: main
|
||||
paths-ignore: '**.md'
|
||||
@@ -11,7 +12,7 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: macos-14
|
||||
runs-on: macos-15
|
||||
|
||||
steps:
|
||||
- name: Check out
|
||||
@@ -30,7 +31,7 @@ jobs:
|
||||
run: chmod +x gradlew
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew assembleRelease
|
||||
run: ./gradlew --warning-mode all assembleRelease
|
||||
|
||||
- name: Upload CI module zip as artifact zip
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
5
.gitmodules
vendored
5
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
||||
[submodule "Dobby"]
|
||||
path = app/src/main/cpp/Dobby
|
||||
url = https://github.com/jmpews/Dobby
|
||||
url = https://github.com/JingMatrix/Dobby
|
||||
[submodule "json"]
|
||||
path = app/src/main/cpp/json
|
||||
url = https://github.com/nlohmann/json
|
||||
|
||||
33
CHANGELOG.md
33
CHANGELOG.md
@@ -1,16 +1,23 @@
|
||||
## Custom Fork v9
|
||||
- Improve migrate script handling of some formatting edge cases
|
||||
- Add migrate script manual option to override all values using the fingerprint values
|
||||
- Add an opt-in scripts-only-mode for Android <10 ROMs
|
||||
- Add autopif script to allow extracting the latest Xiaomi.eu custom.pif.json values
|
||||
- Add killgms script to allow manual DroidGuard process killing
|
||||
## Custom Fork v13
|
||||
|
||||
## Custom Fork v8
|
||||
- Rename VERBOSE_LOGS to verboseLogs to better differentiate Advanced Settings from Build Fields or System Properties
|
||||
- Improve replace list to also allow file paths replacing/hiding systemlessly
|
||||
- Improve migration script and add optional verboseLogs entry to output
|
||||
- Improve replace list to automatically comment out any overlay APK config.xml entries systemlessly
|
||||
- Update default/example app replace list for more ROM spoof injection methods
|
||||
- Fix retaining disabled ROM apps through module updates in some scenarios
|
||||
- Improve Action on KSU/APatch, KSU-Next, MMRL
|
||||
- Improve autopif2 to ignore Preview builds by default
|
||||
- Remove unnecessary adb props spoof
|
||||
- Add all known opt-out props for PPU/PIH variants/hybrids
|
||||
- Add new verified boot error props deletion
|
||||
- Update killgms to killpi by adding vending
|
||||
- Improve autopif2 to populate TS's optional security_patch.txt
|
||||
- Improve ROM overlay xml disabling support
|
||||
- Improve autopif2 for wget2 on arm
|
||||
- Improve Action to use Platform Preview builds
|
||||
|
||||
## Custom Fork v12
|
||||
- Improve autopif2 to generate from Pixel Beta point releases
|
||||
- Improve autopif2 to catch more broken environments
|
||||
- Improve migrate parsing lines with comments
|
||||
- Update default app replace list for helluvaOS
|
||||
- Fix retaining replaced non-system ROM apps on KSU/APatch
|
||||
- Add autopif2 --strong for initial setup with TS
|
||||
- Add skipping prop deletion to avoid app detections if skipdelprop file exists
|
||||
|
||||
_[Previous changelogs](https://github.com/osm0sis/PlayIntegrityFork/releases)_
|
||||
|
||||
76
README.md
76
README.md
@@ -6,27 +6,26 @@
|
||||
[](https://github.com/osm0sis/PlayIntegrityFork/releases/latest)
|
||||
[](https://github.com/osm0sis/PlayIntegrityFork/releases)
|
||||
|
||||
A Zygisk module which fixes "ctsProfileMatch" (SafetyNet) and "MEETS_DEVICE_INTEGRITY" (Play Integrity).
|
||||
A Zygisk module which fixes "MEETS_DEVICE_INTEGRITY" for Android <13 "deviceRecognitionVerdict" with the Play Integrity API.
|
||||
|
||||
To use this module you must have one of the following (latest versions):
|
||||
|
||||
- [Magisk](https://github.com/topjohnwu/Magisk) with Zygisk enabled (and Enforce DenyList enabled if NOT also using [Shamiko](https://github.com/LSPosed/LSPosed.github.io/releases) or [Zygisk Assistant](https://github.com/snake-4/Zygisk-Assistant), for best results)
|
||||
- [Magisk](https://github.com/topjohnwu/Magisk) with Zygisk enabled (and Enforce DenyList enabled if NOT also using [Shamiko](https://github.com/LSPosed/LSPosed.github.io/releases) or [Zygisk Assistant](https://github.com/snake-4/Zygisk-Assistant) or [NoHello](https://github.com/MhmRdd/NoHello), for best results)
|
||||
- [KernelSU](https://github.com/tiann/KernelSU) with [Zygisk Next](https://github.com/Dr-TSNG/ZygiskNext) module installed
|
||||
- [KernelSU Next](https://github.com/KernelSU-Next/KernelSU-Next) with [Zygisk Next](https://github.com/Dr-TSNG/ZygiskNext) module installed
|
||||
- [APatch](https://github.com/bmax121/APatch) with [Zygisk Next](https://github.com/Dr-TSNG/ZygiskNext) module installed
|
||||
|
||||
## About module
|
||||
|
||||
It injects a classes.dex file to modify fields in the android.os.Build class. Also, it creates a hook in the native code to modify system properties. These are spoofed only to Google Play Services' DroidGuard (SafetyNet/Play Integrity) service.
|
||||
|
||||
The purpose of the module is to avoid hardware attestation.
|
||||
It injects a classes.dex file to modify fields in the android.os.Build class. Also, it creates a hook in the native code to modify system properties. These are spoofed only to Google Play Services' DroidGuard (Play Integrity) service.
|
||||
|
||||
## About 'custom.pif.json' file
|
||||
|
||||
You can fill out the included template [example.pif.json](https://raw.githubusercontent.com/osm0sis/PlayIntegrityFork/main/module/example.pif.json) from the module directory (/data/adb/modules/playintegrityfix) then rename it to custom.pif.json to spoof custom values to the GMS unstable process. It will be used instead of any included pif.json (none included currently).
|
||||
|
||||
Note this is just a template with the current suggested defaults, but with this fork you can include as few or as many android.os.Build class fields and Android system properties as needed to pass DEVICE verdict now and in the future if the enforced checks by Play Integrity change.
|
||||
Note this is just a template with the current suggested default entries, but with this fork you can include as few or as many android.os.Build class fields and Android system properties as needed to pass DEVICE verdict now and in the future if the enforced checks by Play Integrity change.
|
||||
|
||||
As a general rule you can't use values from recent devices due to them only being allowed with full hardware backed attestation. A script to extract the latest Xiaomi.eu public fingerprint is included with the module; see the autopif section below for usage and caveats, and see the Resources below for information and scripts to help find a working private fingerprint.
|
||||
As a general rule you can't use values from recent devices due to them only being allowed with full hardware backed attestation. A script to extract the latest Pixel Beta fingerprint is included with the module; see the autopif2 section below for usage and caveats, and see the Resources below for information and scripts to help find a working private fingerprint.
|
||||
|
||||
Older formatted custom.pif.json files from cross-forks and previous releases will be automatically migrated to the latest format. Simply ensure the filename is custom.pif.json and place it in the module directory before upgrading.
|
||||
|
||||
@@ -46,37 +45,44 @@ A migration may also be performed manually with `sh migrate.sh` and custom.pif.j
|
||||
|
||||
- Scripts:
|
||||
- [gen_pif_custom.sh](https://xdaforums.com/t/tools-zips-scripts-osm0sis-odds-and-ends-multiple-devices-platforms.2239421/post-89173470) - Script to generate a custom.pif.json from device dump build.prop files
|
||||
- [pif-test-json-file.sh](https://xdaforums.com/t/tools-zips-scripts-osm0sis-odds-and-ends-multiple-devices-platforms.2239421/post-89482876) - Script to automate generating and testing json files to attempt to find working fingerprints
|
||||
- [autopif.sh](https://xdaforums.com/t/module-play-integrity-fix-safetynet-fix.4607985/post-89233630) - Script to extract the latest working Xiaomi.eu public fingerprint (though frequently banned and may be banned for RCS use while otherwise passing) to test an initial setup
|
||||
- [pif-test-json-file.sh](https://xdaforums.com/t/module-play-integrity-fix-safetynet-fix.4607985/post-89561228) - Script to automate generating and testing json files to attempt to find working fingerprints
|
||||
- [install-random-fp.sh](https://xdaforums.com/t/script-for-randomly-installing-custom-device-fingerprints.4647408/) - Script to randomly switch between multiple working fingerprints found by the user
|
||||
|
||||
- Apps:
|
||||
- [FP BETA Checker](https://xdaforums.com/t/tricky-store-bootloader-keybox-spoofing.4683446/post-89754890) - Tasker App to check the estimated expiry of the Pixel Beta fingerprint and trigger autopif2.sh to update
|
||||
- [FP XEU Checker](https://xdaforums.com/t/module-play-integrity-fix-safetynet-fix.4607985/post-89390931) - Tasker App to check for a new Xiaomi.eu public fingerprint and trigger autopif.sh to update
|
||||
|
||||
</details>
|
||||
|
||||
## About 'custom.app_replace.list' file
|
||||
|
||||
You can customize the included default [example.app_replace.list](https://raw.githubusercontent.com/osm0sis/PlayIntegrityFork/main/module/example.app_replace.list) from the module directory (/data/adb/modules/playintegrityfix) then rename it to custom.app_replace.list to systemlessly replace any additional conflicting custom ROM spoof injection app paths to disable them.
|
||||
|
||||
## About 'autopif.sh' and 'killgms.sh' script files
|
||||
## About 'autopif2.sh' and 'killpi.sh' script files
|
||||
|
||||
There's intentionally no custom./pif.json in my fork by default, because the goal remains to be futureproof, and including something that could/will be banned and obsolete the next day would be contrary to that goal. If you don't care to have your own private fingerprint to use or don't have time to look for one currently then simply run the extraction script from a root prompt with `sh autopif.sh` in the module directory (/data/adb/playintegrityfix/), or from a file explorer app that supports script execution.
|
||||
There's intentionally no pif.json in the module because the goal remains to be futureproof, and including something that may be banned and obsolete within days would be contrary to that goal. If you don't care to have your own private fingerprint to use or don't have time to look for one currently (since very few remain) then simply run the generation script from a root manager app that supports the module Action button, a root prompt with `sh autopif2.sh --preview` in the module directory (/data/adb/modules/playintegrityfix), or from a file explorer app that supports script execution. For arm/x86 devices wget2 is required but may be installed via [addon module](https://xdaforums.com/t/tools-zips-scripts-osm0sis-odds-and-ends-multiple-devices-platforms.2239421/post-89991315).
|
||||
|
||||
The autopif script extracts the latest working Xiaomi.eu fingerprint (though frequently banned and may be banned for RCS use while otherwise passing Play Integrity and SafetyNet) to test an initial setup.
|
||||
The autopif2 script generates a random device fingerprint from the latest Pixel Beta, ideally only to test an initial setup, since they expire roughly every 6 weeks from the Pixel Beta release date (dates included in the generated fingerprint), and the public mass-used ones from other modules or ROMs may also get banned or may be banned for RCS use while otherwise passing Play Integrity in that time. Notable advanced commandline options are: `-p` or `--preview` forces not to ignore Android Platform Preview builds (Developer Previews and Betas); and `-d #` or `--depth #` chooses the depth to crawl down the QPR Betas list when there are multiple active Betas, e.g. when QPR2 is concurrent with QPR1 the default value of 1 would get the first listed (QPR2) and `-d 2` would force it to get the second listed (QPR1).
|
||||
|
||||
The killgms script forces the Google Play Services DroidGuard process (com.google.android.gms.unstable) to end, making it restart with the next attestation attempt; useful for testing out different private fingerprints without requiring a reboot in between.
|
||||
The killpi script forces the Google Play Services DroidGuard (com.google.android.gms.unstable) and Play Store (com.android.vending) processes to end, making them restart with the next attestation attempt; useful for testing out different fingerprints without requiring a reboot in between.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Make sure Google Play Services (com.google.android.gms) is NOT on the Magisk DenyList if Enforce DenyList is enabled since this interferes with the module; the module does prevent this using scripts but it only happens once during each reboot.
|
||||
|
||||
Note: The below verdicts are all referring to the Android <13 deviceRecognitionVerdict Play Integrity API, not the Android 13+ deviceRecognitionVerdict (which relies on locked bootloader checks to pass even DEVICE verdict).
|
||||
|
||||
### Failing BASIC verdict
|
||||
|
||||
If you are failing basicIntegrity (SafetyNet) or MEETS_BASIC_INTEGRITY (Play Integrity) something is wrong in your setup. Recommended steps in order to find the problem:
|
||||
If you are failing MEETS_BASIC_INTEGRITY something is wrong in your setup. Recommended steps in order to find the problem:
|
||||
|
||||
- Disable all modules except this one
|
||||
- Try a different (ideally known working) custom.pif.json
|
||||
|
||||
Note: Some modules which modify system (e.g. Xposed) can trigger DroidGuard detections, as can any which hook GMS processes (e.g. custom fonts).
|
||||
|
||||
### Failing DEVICE verdict (on KernelSU/APatch)
|
||||
### Failing DEVICE verdict (on KernelSU/KernelSU Next/APatch)
|
||||
|
||||
- Disable Zygisk Next
|
||||
- Reboot
|
||||
@@ -92,7 +98,8 @@ Note: Some modules which modify system (e.g. Xposed) can trigger DroidGuard dete
|
||||
### Failing DEVICE verdict (on custom ROM)
|
||||
|
||||
- Check the ROM signing keys with command `adb shell unzip -l /system/etc/security/otacerts.zip` or `unzip -l /system/etc/security/otacerts.zip`
|
||||
- If the output shows the ROM is signed with the AOSP testkey then inform your ROM maintainer to start signing their builds with a private key for their next build and ideally also provide a ROM signature migration build to allow you to update to it without requiring a data wipe
|
||||
- If the output shows the ROM is signed with the AOSP testkey then inform your ROM maintainer to start signing their builds with a private key for their next build and ideally also provide a ROM signature migration build to allow users to update to it without requiring a data wipe
|
||||
- There is an experimental advanced feature to attempt to work around this by spoofing the ROM signature in Package Manager, see the spoofing Advanced Settings section below
|
||||
- You may also try a different custom ROM, or go back to the stock ROM for your device, if available/possible
|
||||
|
||||
### Failing Play Protect/Store Certification and/or Google Wallet Tap To Pay Setup Security Requirements
|
||||
@@ -115,15 +122,30 @@ Add a "verboseLogs" entry with a value of "0", "1", "2", "3" or "100" to your cu
|
||||
|
||||
## Can this module pass MEETS_STRONG_INTEGRITY?
|
||||
|
||||
No.
|
||||
No...
|
||||
|
||||
## About Play Integrity (SafetyNet is deprecated)
|
||||
## About spoofing Advanced Settings
|
||||
|
||||
[Play Integrity API](https://xdaforums.com/t/info-play-integrity-api-replacement-for-safetynet.4479337/) - FAQ/information about PI (Play Integrity) replacing SN (SafetyNet)
|
||||
The advanced spoofing options add granular control over what exactly gets spoofed, allowing one to disable the parts that may conflict with other kinds of spoofing modules, and provide an option to work around the testkey ROM ban for those needing that feature. See more in the Details area below.
|
||||
|
||||
<details>
|
||||
<summary><strong>Details</strong></summary>
|
||||
|
||||
- Adding the Advanced Settings entries is best done using the migration script with the `sh migrate.sh --force --advanced` or `sh migrate.sh -f -a` command. They may also be added on initial setups using the `sh autopif2.sh --advanced --preview` or `sh autopif2.sh -a -p` command or configured directly for Tricky Store to achieve <A13 STRONG or A13+ DEVICE or STRONG integrity (see below) with the `sh autopif2.sh --strong --preview` or `sh autopif2.sh -s -p` command. Other than for the "verboseLogs" entry (see above), they are all 0 (disabled) or 1 (enabled).
|
||||
|
||||
- The "spoofBuild" entry (default 1) controls spoofing the Build Fields from the fingerprint; the "spoofProps" entry (default 1) controls spoofing the System Properties from the fingerprint; the "spoofProvider" entry (default 1) controls spoofing the Keystore Provider; the "spoofSignature" entry (default 0) controls spoofing the ROM Signature, and the "spoofVendingSdk" entry (default 0) controls spoofing ROM SDK_INT/sdkVersion 32 to the Play Store (com.android.vending) to force Play Integrity to use the <A13 verdicts.
|
||||
|
||||
- Leaving spoofVendingSdk enabled is NOT recommended, it [will break](https://github.com/osm0sis/PlayIntegrityFork/pull/30) the behavior of the Play Store to some extent (back gesture/navbar button for all, account sign-in and downloads for higher original ROM SDK_INT) and could have other unintended effects like incorrect app variants being served, crashes, etc. One possible use case is with the [spoofVendingSdk QSTile](https://xdaforums.com/t/tricky-store-bootloader-keybox-spoofing.4683446/post-90118016) Tasker App to quickly toggle it on only as needed, then toggle it off again afterward.
|
||||
|
||||
- For spoofing locked bootloader and attempting to pass Play Integrity <A13 STRONG or A13+ DEVICE or STRONG verdict I only recommend using the latest official [Tricky Store](https://github.com/5ec1cff/TrickyStore) build.
|
||||
|
||||
- Note: Using Tricky Store to achieve <A13 STRONG or A13+ DEVICE or STRONG integrity (with an unrevoked hardware keybox.xml) requires the Advanced Settings "spoofProvider" disabled and the "*.security_patch" entry commented out (unless spoofing a matching OS Patch Level with system= or all= in Tricky Store's security_patch.txt; autopif2 will do this automatically if security_patch.txt exists in the Tricky Store directory), but to achieve <A13 DEVICE integrity (with Tricky Store default AOSP software keybox.xml) requires at least "spoofProps" enabled, and some fingerprints may also require "spoofProvider". More known working private fingerprints can achieve <A13 DEVICE/STRONG integrity on more devices using these Advanced Settings in conjunction with Tricky Store than was possible with Tricky Store alone since they require fingerprint props spoofing.
|
||||
|
||||
</details>
|
||||
|
||||
## About Scripts-only mode
|
||||
|
||||
An advanced mode intended for older Android <10 stock ROMs or those with stock-like values, (and some other rare special cases,) since they generally only need a few prop changes to pass Play Integrity DEVICE verdict. Due to this the majority of the previous information does not apply to or contradicts that of Scripts-only mode, so to avoid confusion it's contained in the Details area below.
|
||||
An advanced feature intended for older Android <10 ROMs, mostly stock ROMs or those with stock-like values, (and some other rare special cases), since they generally only need a few prop changes to pass Play Integrity <A13 DEVICE verdict. Due to this the majority of the previous information does not apply to or contradicts that of Scripts-only mode, so to avoid confusion it's contained in the Details area below.
|
||||
|
||||
<details>
|
||||
<summary><strong>Details</strong></summary>
|
||||
@@ -136,6 +158,20 @@ An advanced mode intended for older Android <10 stock ROMs or those with stock-l
|
||||
|
||||
</details>
|
||||
|
||||
## About skipping property deletion
|
||||
|
||||
An advanced feature (unrelated to Play Integrity) intended for those who also need to use apps which detect prop tampering. To avoid triggering these detections by skipping any `resetprop --delete` commands in the module scripts, manually opt-in by creating a file named skipdelprop in the module directory after installation, either from a root prompt with `touch /data/adb/modules/playintegrityfix/skipdelprop` or from a file explorer app, then reboot.
|
||||
|
||||
## About Play Integrity (SafetyNet has been shut down)
|
||||
|
||||
[Play Integrity API](https://xdaforums.com/t/info-play-integrity-api-replacement-for-safetynet.4479337/) - FAQ/information about PI (Play Integrity) replacing SN (SafetyNet)
|
||||
|
||||
[Play Integrity Improved Verdicts](https://developer.android.com/google/play/integrity/improvements) - Information about the more secure verdicts for Android 13+ ROMs (also see the spoofing Advanced Settings section above)
|
||||
|
||||
## Credits
|
||||
|
||||
Module scripts were adapted from those of kdrag0n/Displax's Universal SafetyNet Fix (USNF) module, please see the commit history of [Displax's USNF Fork](https://github.com/Displax/safetynet-fix/tree/dev/magisk) for proper attribution.
|
||||
Forked from chiteroman's [Play Integrity Fix (PIF)](https://github.com/chiteroman/PlayIntegrityFix) (no longer online).
|
||||
|
||||
Original concept and general mechanism of PIF from kdrag0n's [ProtonAOSP](https://protonaosp.org/) and [Universal SafetyNet Fix (USNF)](https://github.com/kdrag0n/safetynet-fix) projects.
|
||||
|
||||
Module scripts adapted from those of Displax's forked Universal SafetyNet Fix (USNF MOD) module; please see the commit history of [Displax's USNF MOD](https://github.com/Displax/safetynet-fix/tree/dev/magisk) for proper attribution.
|
||||
|
||||
@@ -4,9 +4,9 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "es.chiteroman.playintegrityfix"
|
||||
compileSdk = 34
|
||||
ndkVersion = "26.3.11579264"
|
||||
buildToolsVersion = "34.0.0"
|
||||
compileSdk = 36
|
||||
ndkVersion = "28.1.13356709"
|
||||
buildToolsVersion = "36.0.0"
|
||||
|
||||
buildFeatures {
|
||||
prefab = true
|
||||
@@ -22,7 +22,7 @@ android {
|
||||
defaultConfig {
|
||||
applicationId = "es.chiteroman.playintegrityfix"
|
||||
minSdk = 26
|
||||
targetSdk = 34
|
||||
targetSdk = 36
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
|
||||
@@ -62,15 +62,16 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("dev.rikka.ndk.thirdparty:cxx:1.2.0")
|
||||
implementation("org.lsposed.libcxx:libcxx:28.1.13356709")
|
||||
implementation("org.lsposed.hiddenapibypass:hiddenapibypass:6.1")
|
||||
}
|
||||
|
||||
tasks.register("copyFiles") {
|
||||
doLast {
|
||||
val moduleFolder = project.rootDir.resolve("module")
|
||||
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 moduleFolder = project.rootDir.resolve("module")
|
||||
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")
|
||||
|
||||
doLast {
|
||||
dexFile.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true)
|
||||
|
||||
soDir.walk().filter { it.isFile && it.extension == "so" }.forEach { soFile ->
|
||||
|
||||
8
app/proguard-rules.pro
vendored
8
app/proguard-rules.pro
vendored
@@ -1,3 +1,5 @@
|
||||
-keep class es.chiteroman.playintegrityfix.EntryPoint {public <methods>;}
|
||||
-keep class es.chiteroman.playintegrityfix.CustomProvider
|
||||
-keep class es.chiteroman.playintegrityfix.CustomKeyStoreSpi
|
||||
-keep class es.chiteroman.playintegrityfix.EntryPoint { public <methods>; }
|
||||
-keep class es.chiteroman.playintegrityfix.EntryPointVending { public <methods>; }
|
||||
-keepclassmembers class es.chiteroman.playintegrityfix.CustomKeyStoreSpi
|
||||
-keepclassmembers class es.chiteroman.playintegrityfix.CustomPackageInfoCreator { public <init>(...); }
|
||||
-keepclassmembers class es.chiteroman.playintegrityfix.CustomProvider
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.22.1)
|
||||
|
||||
project(zygisk)
|
||||
project(playintegrityfix)
|
||||
|
||||
find_package(cxx REQUIRED CONFIG)
|
||||
|
||||
|
||||
Submodule app/src/main/cpp/Dobby updated: b0176de574...05a09ac680
1
app/src/main/cpp/json
Submodule
1
app/src/main/cpp/json
Submodule
Submodule app/src/main/cpp/json added at 55f93686c0
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "zygisk.hpp"
|
||||
#include "json.hpp"
|
||||
#include "json/single_include/nlohmann/json.hpp"
|
||||
#include "dobby.h"
|
||||
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "PIF/Native", __VA_ARGS__)
|
||||
@@ -12,8 +12,15 @@
|
||||
|
||||
#define JSON_FILE_PATH "/data/adb/modules/playintegrityfix/pif.json"
|
||||
#define CUSTOM_JSON_FILE_PATH "/data/adb/modules/playintegrityfix/custom.pif.json"
|
||||
#define VENDING_PACKAGE "com.android.vending"
|
||||
#define DROIDGUARD_PACKAGE "com.google.android.gms.unstable"
|
||||
|
||||
static int verboseLogs = 0;
|
||||
static int spoofBuild = 1;
|
||||
static int spoofProps = 1;
|
||||
static int spoofProvider = 1;
|
||||
static int spoofSignature = 0;
|
||||
static int spoofVendingSdk = 0;
|
||||
|
||||
static std::map<std::string, std::string> jsonProps;
|
||||
|
||||
@@ -28,13 +35,6 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
|
||||
|
||||
std::string prop(name);
|
||||
|
||||
// Spoof specific property values
|
||||
if (prop == "init.svc.adbd") {
|
||||
value = "stopped";
|
||||
} else if (prop == "sys.usb.state") {
|
||||
value = "mtp";
|
||||
}
|
||||
|
||||
if (jsonProps.count(prop)) {
|
||||
// Exact property match
|
||||
value = jsonProps[prop].c_str();
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
}
|
||||
|
||||
void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
|
||||
bool isGms = false, isGmsUnstable = false;
|
||||
bool isGms = false, isDroidGuardOrVending = false;
|
||||
|
||||
auto rawProcess = env->GetStringUTFChars(args->nice_name, nullptr);
|
||||
auto rawDir = env->GetStringUTFChars(args->app_data_dir, nullptr);
|
||||
@@ -98,11 +98,11 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
std::string_view process(rawProcess);
|
||||
pkgName = rawProcess;
|
||||
std::string_view dir(rawDir);
|
||||
|
||||
isGms = dir.ends_with("/com.google.android.gms");
|
||||
isGmsUnstable = process == "com.google.android.gms.unstable";
|
||||
isGms = dir.ends_with("/com.google.android.gms") || dir.ends_with("/com.android.vending");
|
||||
isDroidGuardOrVending = pkgName == DROIDGUARD_PACKAGE || pkgName == VENDING_PACKAGE;
|
||||
|
||||
env->ReleaseStringUTFChars(args->nice_name, rawProcess);
|
||||
env->ReleaseStringUTFChars(args->app_data_dir, rawDir);
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
// We are in GMS now, force unmount
|
||||
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
|
||||
|
||||
if (!isGmsUnstable) {
|
||||
if (!isDroidGuardOrVending) {
|
||||
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||
return;
|
||||
}
|
||||
@@ -164,8 +164,12 @@ public:
|
||||
if (dexVector.empty() || json.empty()) return;
|
||||
|
||||
readJson();
|
||||
doHook();
|
||||
inject();
|
||||
|
||||
if (pkgName == VENDING_PACKAGE) spoofProps = spoofBuild = spoofProvider = spoofSignature = 0;
|
||||
else spoofVendingSdk = 0;
|
||||
|
||||
if (spoofProps > 0) doHook();
|
||||
if (spoofBuild + spoofProvider + spoofSignature + spoofVendingSdk > 0) inject();
|
||||
|
||||
dexVector.clear();
|
||||
json.clear();
|
||||
@@ -180,11 +184,12 @@ private:
|
||||
JNIEnv *env = nullptr;
|
||||
std::vector<char> dexVector;
|
||||
nlohmann::json json;
|
||||
std::string pkgName;
|
||||
|
||||
void readJson() {
|
||||
LOGD("JSON contains %d keys!", static_cast<int>(json.size()));
|
||||
|
||||
// Verbose logging if verboseLogs with level number is present
|
||||
// Verbose logging level
|
||||
if (json.contains("verboseLogs")) {
|
||||
if (!json["verboseLogs"].is_null() && json["verboseLogs"].is_string() && json["verboseLogs"] != "") {
|
||||
verboseLogs = stoi(json["verboseLogs"].get<std::string>());
|
||||
@@ -195,6 +200,57 @@ private:
|
||||
json.erase("verboseLogs");
|
||||
}
|
||||
|
||||
// Advanced spoofing settings
|
||||
if (json.contains("spoofVendingSdk")) {
|
||||
if (!json["spoofVendingSdk"].is_null() && json["spoofVendingSdk"].is_string() && json["spoofVendingSdk"] != "") {
|
||||
spoofVendingSdk = stoi(json["spoofVendingSdk"].get<std::string>());
|
||||
if (verboseLogs > 0) LOGD("Spoofing SDK Level in Play Store %s!", (spoofVendingSdk > 0) ? "enabled" : "disabled");
|
||||
} else {
|
||||
LOGD("Error parsing spoofVendingSdk!");
|
||||
}
|
||||
json.erase("spoofVendingSdk");
|
||||
}
|
||||
if (pkgName == VENDING_PACKAGE) {
|
||||
json.clear();
|
||||
return;
|
||||
}
|
||||
if (json.contains("spoofBuild")) {
|
||||
if (!json["spoofBuild"].is_null() && json["spoofBuild"].is_string() && json["spoofBuild"] != "") {
|
||||
spoofBuild = stoi(json["spoofBuild"].get<std::string>());
|
||||
if (verboseLogs > 0) LOGD("Spoofing Build Fields %s!", (spoofBuild > 0) ? "enabled" : "disabled");
|
||||
} else {
|
||||
LOGD("Error parsing spoofBuild!");
|
||||
}
|
||||
json.erase("spoofBuild");
|
||||
}
|
||||
if (json.contains("spoofProps")) {
|
||||
if (!json["spoofProps"].is_null() && json["spoofProps"].is_string() && json["spoofProps"] != "") {
|
||||
spoofProps = stoi(json["spoofProps"].get<std::string>());
|
||||
if (verboseLogs > 0) LOGD("Spoofing System Properties %s!", (spoofProps > 0) ? "enabled" : "disabled");
|
||||
} else {
|
||||
LOGD("Error parsing spoofProps!");
|
||||
}
|
||||
json.erase("spoofProps");
|
||||
}
|
||||
if (json.contains("spoofProvider")) {
|
||||
if (!json["spoofProvider"].is_null() && json["spoofProvider"].is_string() && json["spoofProvider"] != "") {
|
||||
spoofProvider = stoi(json["spoofProvider"].get<std::string>());
|
||||
if (verboseLogs > 0) LOGD("Spoofing Keystore Provider %s!", (spoofProvider > 0) ? "enabled" : "disabled");
|
||||
} else {
|
||||
LOGD("Error parsing spoofProvider!");
|
||||
}
|
||||
json.erase("spoofProvider");
|
||||
}
|
||||
if (json.contains("spoofSignature")) {
|
||||
if (!json["spoofSignature"].is_null() && json["spoofSignature"].is_string() && json["spoofSignature"] != "") {
|
||||
spoofSignature = stoi(json["spoofSignature"].get<std::string>());
|
||||
if (verboseLogs > 0) LOGD("Spoofing ROM Signature %s!", (spoofSignature > 0) ? "enabled" : "disabled");
|
||||
} else {
|
||||
LOGD("Error parsing spoofSignature!");
|
||||
}
|
||||
json.erase("spoofSignature");
|
||||
}
|
||||
|
||||
std::vector<std::string> eraseKeys;
|
||||
for (auto &jsonList: json.items()) {
|
||||
if (verboseLogs > 1) LOGD("Parsing %s", jsonList.key().c_str());
|
||||
@@ -220,32 +276,41 @@ private:
|
||||
}
|
||||
|
||||
void inject() {
|
||||
LOGD("JNI: Getting system classloader");
|
||||
const char* niceName = pkgName == VENDING_PACKAGE ? "PS" : "DG";
|
||||
|
||||
LOGD("JNI %s: Getting system classloader", niceName);
|
||||
auto clClass = env->FindClass("java/lang/ClassLoader");
|
||||
auto getSystemClassLoader = env->GetStaticMethodID(clClass, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
|
||||
auto systemClassLoader = env->CallStaticObjectMethod(clClass, getSystemClassLoader);
|
||||
|
||||
LOGD("JNI: Creating module classloader");
|
||||
LOGD("JNI %s: Creating module classloader", niceName);
|
||||
auto dexClClass = env->FindClass("dalvik/system/InMemoryDexClassLoader");
|
||||
auto dexClInit = env->GetMethodID(dexClClass, "<init>", "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V");
|
||||
auto buffer = env->NewDirectByteBuffer(dexVector.data(), static_cast<jlong>(dexVector.size()));
|
||||
auto dexCl = env->NewObject(dexClClass, dexClInit, buffer, systemClassLoader);
|
||||
|
||||
LOGD("JNI: Loading module class");
|
||||
LOGD("JNI %s: Loading module class", niceName);
|
||||
auto loadClass = env->GetMethodID(clClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
auto entryClassName = env->NewStringUTF("es.chiteroman.playintegrityfix.EntryPoint");
|
||||
const char* className = pkgName == VENDING_PACKAGE ? "es.chiteroman.playintegrityfix.EntryPointVending" : "es.chiteroman.playintegrityfix.EntryPoint";
|
||||
auto entryClassName = env->NewStringUTF(className);
|
||||
auto entryClassObj = env->CallObjectMethod(dexCl, loadClass, entryClassName);
|
||||
|
||||
auto entryClass = (jclass) entryClassObj;
|
||||
|
||||
LOGD("JNI: Sending JSON");
|
||||
auto receiveJson = env->GetStaticMethodID(entryClass, "receiveJson", "(Ljava/lang/String;)V");
|
||||
auto javaStr = env->NewStringUTF(json.dump().c_str());
|
||||
env->CallStaticVoidMethod(entryClass, receiveJson, javaStr);
|
||||
if (pkgName == VENDING_PACKAGE) {
|
||||
LOGD("JNI %s: Calling EntryPointVending.init", niceName);
|
||||
auto entryInit = env->GetStaticMethodID(entryClass, "init", "(II)V");
|
||||
env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofVendingSdk);
|
||||
} else {
|
||||
LOGD("JNI %s: Sending JSON", niceName);
|
||||
auto receiveJson = env->GetStaticMethodID(entryClass, "receiveJson", "(Ljava/lang/String;)V");
|
||||
auto javaStr = env->NewStringUTF(json.dump().c_str());
|
||||
env->CallStaticVoidMethod(entryClass, receiveJson, javaStr);
|
||||
|
||||
LOGD("JNI: Calling init");
|
||||
auto entryInit = env->GetStaticMethodID(entryClass, "init", "(I)V");
|
||||
env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs);
|
||||
LOGD("JNI %s: Calling EntryPoint.init", niceName);
|
||||
auto entryInit = env->GetStaticMethodID(entryClass, "init", "(IIII)V");
|
||||
env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofBuild, spoofProvider, spoofSignature);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package es.chiteroman.playintegrityfix;
|
||||
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.Signature;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class CustomPackageInfoCreator implements Parcelable.Creator<PackageInfo> {
|
||||
private final Parcelable.Creator<PackageInfo> originalCreator;
|
||||
private final Signature spoofedSignature;
|
||||
|
||||
public CustomPackageInfoCreator(Parcelable.Creator<PackageInfo> originalCreator, Signature spoofedSignature) {
|
||||
this.originalCreator = originalCreator;
|
||||
this.spoofedSignature = spoofedSignature;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public PackageInfo createFromParcel(Parcel source) {
|
||||
PackageInfo packageInfo = originalCreator.createFromParcel(source);
|
||||
if (packageInfo.packageName.equals("android")) {
|
||||
if (packageInfo.signatures != null && packageInfo.signatures.length > 0) {
|
||||
packageInfo.signatures[0] = spoofedSignature;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
if (packageInfo.signingInfo != null) {
|
||||
Signature[] signaturesArray = packageInfo.signingInfo.getApkContentsSigners();
|
||||
if (signaturesArray != null && signaturesArray.length > 0) {
|
||||
signaturesArray[0] = spoofedSignature;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return packageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackageInfo[] newArray(int size) {
|
||||
return originalCreator.newArray(size);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,9 @@ public final class CustomProvider extends Provider {
|
||||
@Override
|
||||
public synchronized Service getService(String type, String algorithm) {
|
||||
if (EntryPoint.getVerboseLogs() > 2) EntryPoint.LOG(String.format("Service: Caller type '%s' with algorithm '%s'", type, algorithm));
|
||||
if (type.equals("KeyStore")) EntryPoint.spoofDevice();
|
||||
if (EntryPoint.getSpoofBuildEnabled() > 0) {
|
||||
if (type.equals("KeyStore")) EntryPoint.spoofDevice();
|
||||
}
|
||||
return super.getService(type, algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
package es.chiteroman.playintegrityfix;
|
||||
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.Signature;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Base64;
|
||||
import android.util.JsonReader;
|
||||
import android.util.Log;
|
||||
|
||||
import org.lsposed.hiddenapibypass.HiddenApiBypass;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.KeyStoreSpi;
|
||||
@@ -17,6 +26,35 @@ import java.util.Map;
|
||||
|
||||
public final class EntryPoint {
|
||||
private static Integer verboseLogs = 0;
|
||||
private static Integer spoofBuildEnabled = 1;
|
||||
|
||||
private static final String signatureData = "MIIFyTCCA7GgAwIBAgIVALyxxl+zDS9SL68SzOr48309eAZyMA0GCSqGSIb3DQEBCwUAMHQxCzAJ\n" +
|
||||
"BgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQw\n" +
|
||||
"EgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAg\n" +
|
||||
"Fw0yMjExMDExODExMzVaGA8yMDUyMTEwMTE4MTEzNVowdDELMAkGA1UEBhMCVVMxEzARBgNVBAgT\n" +
|
||||
"CkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC0dvb2dsZSBJbmMu\n" +
|
||||
"MRAwDgYDVQQLEwdBbmRyb2lkMRAwDgYDVQQDEwdBbmRyb2lkMIICIjANBgkqhkiG9w0BAQEFAAOC\n" +
|
||||
"Ag8AMIICCgKCAgEAsqtalIy/nctKlrhd1UVoDffFGnDf9GLi0QQhsVoJkfF16vDDydZJOycG7/kQ\n" +
|
||||
"ziRZhFdcoMrIYZzzw0ppBjsSe1AiWMuKXwTBaEtxN99S1xsJiW4/QMI6N6kMunydWRMsbJ6aAxi1\n" +
|
||||
"lVq0bxSwr8Sg/8u9HGVivfdG8OpUM+qjuV5gey5xttNLK3BZDrAlco8RkJZryAD40flmJZrWXJmc\n" +
|
||||
"r2HhJJUnqG4Z3MSziEgW1u1JnnY3f/BFdgYsA54SgdUGdQP3aqzSjIpGK01/vjrXvifHazSANjvl\n" +
|
||||
"0AUE5i6AarMw2biEKB2ySUDp8idC5w12GpqDrhZ/QkW8yBSa87KbkMYXuRA2Gq1fYbQx3YJraw0U\n" +
|
||||
"gZ4M3fFKpt6raxxM5j0sWHlULD7dAZMERvNESVrKG3tQ7B39WAD8QLGYc45DFEGOhKv5Fv8510h5\n" +
|
||||
"sXK502IvGpI4FDwz2rbtAgJ0j+16db5wCSW5ThvNPhCheyciajc8dU1B5tJzZN/ksBpzne4Xf9gO\n" +
|
||||
"LZ9ZU0+3Z5gHVvTS/YpxBFwiFpmL7dvGxew0cXGSsG5UTBlgr7i0SX0WhY4Djjo8IfPwrvvA0QaC\n" +
|
||||
"FamdYXKqBsSHgEyXS9zgGIFPt2jWdhaS+sAa//5SXcWro0OdiKPuwEzLgj759ke1sHRnvO735dYn\n" +
|
||||
"5whVbzlGyLBh3L0CAwEAAaNQME4wDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUU1eXQ7NoYKjvOQlh\n" +
|
||||
"5V8jHQMoxA8wHwYDVR0jBBgwFoAUU1eXQ7NoYKjvOQlh5V8jHQMoxA8wDQYJKoZIhvcNAQELBQAD\n" +
|
||||
"ggIBAHFIazRLs3itnZKllPnboSd6sHbzeJURKehx8GJPvIC+xWlwWyFO5+GHmgc3yh/SVd3Xja/k\n" +
|
||||
"8Ud59WEYTjyJJWTw0Jygx37rHW7VGn2HDuy/x0D+els+S8HeLD1toPFMepjIXJn7nHLhtmzTPlDW\n" +
|
||||
"DrhiaYsls/k5Izf89xYnI4euuOY2+1gsweJqFGfbznqyqy8xLyzoZ6bvBJtgeY+G3i/9Be14HseS\n" +
|
||||
"Na4FvI1Oze/l2gUu1IXzN6DGWR/lxEyt+TncJfBGKbjafYrfSh3zsE4N3TU7BeOL5INirOMjre/j\n" +
|
||||
"VgB1YQG5qLVaPoz6mdn75AbBBm5a5ahApLiKqzy/hP+1rWgw8Ikb7vbUqov/bnY3IlIU6XcPJTCD\n" +
|
||||
"b9aRZQkStvYpQd82XTyxD/T0GgRLnUj5Uv6iZlikFx1KNj0YNS2T3gyvL++J9B0Y6gAkiG0EtNpl\n" +
|
||||
"z7Pomsv5pVdmHVdKMjqWw5/6zYzVmu5cXFtR384Ti1qwML1xkD6TC3VIv88rKIEjrkY2c+v1frh9\n" +
|
||||
"fRJ2OmzXmML9NgHTjEiJR2Ib2iNrMKxkuTIs9oxKZgrJtJKvdU9qJJKM5PnZuNuHhGs6A/9gt9Oc\n" +
|
||||
"cetYeQvVSqeEmQluWfcunQn9C9Vwi2BJIiVJh4IdWZf5/e2PlSSQ9CJjz2bKI17pzdxOmjQfE0JS\n" +
|
||||
"F7Xt\n";
|
||||
|
||||
private static final Map<String, String> map = new HashMap<>();
|
||||
|
||||
@@ -24,11 +62,17 @@ public final class EntryPoint {
|
||||
return verboseLogs;
|
||||
}
|
||||
|
||||
public static void init(int level) {
|
||||
verboseLogs = level;
|
||||
public static Integer getSpoofBuildEnabled() {
|
||||
return spoofBuildEnabled;
|
||||
}
|
||||
|
||||
public static void init(int logLevel, int spoofBuildVal, int spoofProviderVal, int spoofSignatureVal) {
|
||||
verboseLogs = logLevel;
|
||||
spoofBuildEnabled = spoofBuildVal;
|
||||
if (verboseLogs > 99) logFields();
|
||||
spoofProvider();
|
||||
spoofDevice();
|
||||
if (spoofProviderVal > 0) spoofProvider();
|
||||
if (spoofBuildVal > 0) spoofDevice();
|
||||
if (spoofSignatureVal > 0) spoofPackageManager();
|
||||
}
|
||||
|
||||
public static void receiveJson(String data) {
|
||||
@@ -78,6 +122,63 @@ public final class EntryPoint {
|
||||
}
|
||||
}
|
||||
|
||||
private static void spoofPackageManager() {
|
||||
Signature spoofedSignature = new Signature(Base64.decode(signatureData, Base64.DEFAULT));
|
||||
Parcelable.Creator<PackageInfo> originalCreator = PackageInfo.CREATOR;
|
||||
Parcelable.Creator<PackageInfo> customCreator = new CustomPackageInfoCreator(originalCreator, spoofedSignature);
|
||||
|
||||
try {
|
||||
Field creatorField = findField(PackageInfo.class, "CREATOR");
|
||||
creatorField.setAccessible(true);
|
||||
creatorField.set(null, customCreator);
|
||||
} catch (Exception e) {
|
||||
LOG("Couldn't replace PackageInfoCreator: " + e);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
HiddenApiBypass.addHiddenApiExemptions("Landroid/os/Parcel;", "Landroid/content/pm", "Landroid/app");
|
||||
}
|
||||
|
||||
try {
|
||||
Field cacheField = findField(PackageManager.class, "sPackageInfoCache");
|
||||
cacheField.setAccessible(true);
|
||||
Object cache = cacheField.get(null);
|
||||
Method clearMethod = cache.getClass().getMethod("clear");
|
||||
clearMethod.invoke(cache);
|
||||
} catch (Exception e) {
|
||||
LOG("Couldn't clear PackageInfoCache: " + e);
|
||||
}
|
||||
|
||||
try {
|
||||
Field creatorsField = findField(Parcel.class, "mCreators");
|
||||
creatorsField.setAccessible(true);
|
||||
Map<?, ?> mCreators = (Map<?, ?>) creatorsField.get(null);
|
||||
mCreators.clear();
|
||||
} catch (Exception e) {
|
||||
LOG("Couldn't clear Parcel mCreators: " + e);
|
||||
}
|
||||
|
||||
try {
|
||||
Field creatorsField = findField(Parcel.class, "sPairedCreators");
|
||||
creatorsField.setAccessible(true);
|
||||
Map<?, ?> sPairedCreators = (Map<?, ?>) creatorsField.get(null);
|
||||
sPairedCreators.clear();
|
||||
} catch (Exception e) {
|
||||
LOG("Couldn't clear Parcel sPairedCreators: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Field findField(Class<?> currentClass, String fieldName) throws NoSuchFieldException {
|
||||
while (currentClass != null && !currentClass.equals(Object.class)) {
|
||||
try {
|
||||
return currentClass.getDeclaredField(fieldName);
|
||||
} catch (NoSuchFieldException e) {
|
||||
currentClass = currentClass.getSuperclass();
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldException("Field '" + fieldName + "' not found in class hierarchy of " + currentClass.getName());
|
||||
}
|
||||
|
||||
private static boolean classContainsField(Class className, String fieldName) {
|
||||
for (Field field : className.getDeclaredFields()) {
|
||||
if (field.getName().equals(fieldName)) return true;
|
||||
@@ -164,6 +265,6 @@ public final class EntryPoint {
|
||||
}
|
||||
|
||||
static void LOG(String msg) {
|
||||
Log.d("PIF/Java", msg);
|
||||
Log.d("PIF/Java:DG", msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package es.chiteroman.playintegrityfix;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Build;
|
||||
import java.lang.reflect.Field;
|
||||
import android.util.Log;
|
||||
|
||||
public final class EntryPointVending {
|
||||
|
||||
private static void LOG(String msg) {
|
||||
Log.d("PIF/Java:PS", msg);
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
public static void init(int verboseLogs, int spoofVendingSdk) {
|
||||
if (spoofVendingSdk < 1) return;
|
||||
int requestSdk = spoofVendingSdk == 1 ? 32 : spoofVendingSdk;
|
||||
int targetSdk = Math.min(Build.VERSION.SDK_INT, requestSdk);
|
||||
int oldValue;
|
||||
try {
|
||||
Field field = Build.VERSION.class.getDeclaredField("SDK_INT");
|
||||
field.setAccessible(true);
|
||||
oldValue = field.getInt(null);
|
||||
if (oldValue == targetSdk) {
|
||||
if (verboseLogs > 2) LOG(String.format("[SDK_INT]: %d (unchanged)", oldValue));
|
||||
field.setAccessible(false);
|
||||
return;
|
||||
}
|
||||
field.set(null, targetSdk);
|
||||
field.setAccessible(false);
|
||||
LOG(String.format("[SDK_INT]: %d -> %d", oldValue, targetSdk));
|
||||
} catch (NoSuchFieldException e) {
|
||||
LOG("SDK_INT field not found: " + e);
|
||||
} catch (SecurityException | IllegalAccessException | IllegalArgumentException |
|
||||
NullPointerException | ExceptionInInitializerError e) {
|
||||
LOG("SDK_INT field not accessible: " + e);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
plugins {
|
||||
id("com.android.application") version "8.4.2" apply false
|
||||
id("com.android.application") version "8.10.1" apply false
|
||||
}
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
10
gradlew
vendored
10
gradlew
vendored
@@ -15,6 +15,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
@@ -84,7 +86,7 @@ done
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
@@ -112,7 +114,7 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -203,7 +205,7 @@ fi
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
@@ -211,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
6
gradlew.bat
vendored
6
gradlew.bat
vendored
@@ -13,6 +13,8 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@@ -68,11 +70,11 @@ goto fail
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
15
module/action.sh
Normal file
15
module/action.sh
Normal file
@@ -0,0 +1,15 @@
|
||||
MODPATH="${0%/*}"
|
||||
|
||||
# ensure not running in busybox ash standalone shell
|
||||
set +o standalone
|
||||
unset ASH_STANDALONE
|
||||
|
||||
sh $MODPATH/autopif2.sh -a -m -p || exit 1
|
||||
|
||||
echo -e "\nDone!"
|
||||
|
||||
# warn since KernelSU/APatch's implementation automatically closes if successful
|
||||
if [ "$KSU" = "true" -o "$APATCH" = "true" ] && [ "$KSU_NEXT" != "true" ] && [ "$MMRL" != "true" ]; then
|
||||
echo -e "\nClosing dialog in 20 seconds ..."
|
||||
sleep 20
|
||||
fi
|
||||
@@ -1,105 +0,0 @@
|
||||
#!/system/bin/sh
|
||||
|
||||
if [ "$USER" != "root" -o "$(whoami 2>/dev/null)" != "root" ]; then
|
||||
echo "autopif: need root permissions";
|
||||
exit 1;
|
||||
fi;
|
||||
|
||||
echo "Xiaomi.eu pif.json extractor script \
|
||||
\n by osm0sis @ xda-developers";
|
||||
|
||||
case "$0" in
|
||||
*.sh) DIR="$0";;
|
||||
*) DIR="$(lsof -p $$ 2>/dev/null | grep -o '/.*autopif.sh$')";;
|
||||
esac;
|
||||
DIR=$(dirname "$(readlink -f "$DIR")");
|
||||
|
||||
if ! which wget >/dev/null || grep -q "wget-curl" $(which wget); then
|
||||
if [ -f /data/adb/magisk/busybox ]; then
|
||||
wget() { /data/adb/magisk/busybox wget "$@"; }
|
||||
elif [ -f /data/adb/ksu/bin/busybox ]; then
|
||||
wget() { /data/adb/ksu/bin/busybox wget "$@"; }
|
||||
elif [ -f /data/adb/ap/bin/busybox ]; then
|
||||
wget() { /data/adb/ap/bin/busybox wget "$@"; }
|
||||
else
|
||||
echo "Error: wget not found, install busybox!";
|
||||
exit 1;
|
||||
fi;
|
||||
fi;
|
||||
|
||||
item() { echo "\n- $@"; }
|
||||
|
||||
if [ "$DIR" = /data/adb/modules/playintegrityfix ]; then
|
||||
DIR=$DIR/autopif;
|
||||
mkdir -p $DIR;
|
||||
fi;
|
||||
cd "$DIR";
|
||||
|
||||
if [ ! -f apktool_2.0.3-dexed.jar ]; then
|
||||
item "Downloading Apktool ...";
|
||||
wget --no-check-certificate -O apktool_2.0.3-dexed.jar https://github.com/osm0sis/APK-Patcher/raw/master/tools/apktool_2.0.3-dexed.jar 2>&1 || exit 1;
|
||||
fi;
|
||||
|
||||
item "Finding latest APK from RSS feed ...";
|
||||
APKURL=$(wget -q -O - --no-check-certificate https://sourceforge.net/projects/xiaomi-eu-multilang-miui-roms/rss?path=/xiaomi.eu/Xiaomi.eu-app | grep -o '<link>.*' | head -n 2 | tail -n 1 | sed 's;<link>\(.*\)</link>;\1;g');
|
||||
APKNAME=$(echo $APKURL | sed 's;.*/\(.*\)/download;\1;g');
|
||||
echo "$APKNAME";
|
||||
|
||||
if [ ! -f $APKNAME ]; then
|
||||
item "Downloading $APKNAME ...";
|
||||
wget --no-check-certificate -O $APKNAME $APKURL 2>&1 || exit 1;
|
||||
fi;
|
||||
|
||||
OUT=$(basename $APKNAME .apk);
|
||||
if [ ! -d $OUT ]; then
|
||||
item "Extracting APK files with Apktool ...";
|
||||
DALVIKVM=dalvikvm;
|
||||
if echo "$PREFIX" | grep -q "termux"; then
|
||||
if [ "$TERMUX_VERSION" ]; then
|
||||
if grep -q "apex" $PREFIX/bin/dalvikvm; then
|
||||
DALVIKVM=$PREFIX/bin/dalvikvm;
|
||||
else
|
||||
echo 'Error: Outdated Termux packages, run "pkg upgrade" from a user prompt!';
|
||||
exit 1;
|
||||
fi;
|
||||
else
|
||||
echo "Error: Play Store Termux not supported, use GitHub/F-Droid Termux!";
|
||||
exit 1;
|
||||
fi;
|
||||
fi;
|
||||
$DALVIKVM -Xnoimage-dex2oat -cp apktool_2.0.3-dexed.jar brut.apktool.Main d -f --no-src -p $OUT -o $OUT $APKNAME || exit 1;
|
||||
fi;
|
||||
|
||||
item "Converting inject_fields.xml to pif.json ...";
|
||||
(echo '{';
|
||||
grep -o '<field.*' $OUT/res/xml/inject_fields.xml | sed 's;.*name=\(".*"\) type.* value=\(".*"\).*; \1: \2,;g';
|
||||
echo ' "FIRST_API_LEVEL": "25",' ) | sed '$s/,/\n}/' | tee pif.json;
|
||||
|
||||
if [ -f /data/adb/modules/playintegrityfix/migrate.sh ]; then
|
||||
if [ -f /data/adb/modules/playintegrityfix/custom.pif.json ]; then
|
||||
grep -qE "verboseLogs|VERBOSE_LOGS" /data/adb/modules/playintegrityfix/custom.pif.json && ARGS="-a";
|
||||
fi;
|
||||
item "Converting pif.json to custom.pif.json with migrate.sh:";
|
||||
rm -f custom.pif.json;
|
||||
sh /data/adb/modules/playintegrityfix/migrate.sh -i $ARGS pif.json;
|
||||
cat custom.pif.json;
|
||||
fi;
|
||||
|
||||
if [ "$DIR" = /data/adb/modules/playintegrityfix/autopif ]; then
|
||||
if [ -f /data/adb/modules/playintegrityfix/migrate.sh ]; then
|
||||
NEWNAME="custom.pif.json";
|
||||
else
|
||||
NEWNAME="pif.json";
|
||||
fi;
|
||||
if [ -f "../$NEWNAME" ]; then
|
||||
item "Renaming old file to $NEWNAME.bak ...";
|
||||
mv -fv ../$NEWNAME ../$NEWNAME.bak;
|
||||
fi;
|
||||
item "Installing new json ...";
|
||||
cp -fv $NEWNAME ..;
|
||||
fi;
|
||||
|
||||
if [ -f /data/adb/modules/playintegrityfix/killgms.sh ]; then
|
||||
item "Killing any running GMS DroidGuard process ...";
|
||||
sh /data/adb/modules/playintegrityfix/killgms.sh 2>&1;
|
||||
fi;
|
||||
203
module/autopif2.sh
Normal file
203
module/autopif2.sh
Normal file
@@ -0,0 +1,203 @@
|
||||
#!/system/bin/sh
|
||||
|
||||
if [ "$USER" != "root" -a "$(whoami 2>/dev/null)" != "root" ]; then
|
||||
echo "autopif2: need root permissions"; exit 1;
|
||||
fi;
|
||||
case "$HOME" in
|
||||
*termux*) echo "autopif2: need su root environment"; exit 1;;
|
||||
esac;
|
||||
|
||||
FORCE_DEPTH=1;
|
||||
until [ -z "$1" ]; do
|
||||
case "$1" in
|
||||
-h|--help|help) echo "sh autopif2.sh [-a|-s] [-m] [-p] [-d #]"; exit 0;;
|
||||
-a|--advanced|advanced) ARGS="-a"; shift;;
|
||||
-s|--strong|strong) ARGS="-a"; PATCH_COMMENT=1; spoofProvider=0; shift;;
|
||||
-m|--match|match) FORCE_MATCH=1; shift;;
|
||||
-p|--preview|preview) FORCE_PREVIEW=1; shift;;
|
||||
-d|--depth|depth) echo "$2" | grep -q '^[1-9]$' || exit 1; FORCE_DEPTH=$2; shift 2;;
|
||||
*) break;;
|
||||
esac;
|
||||
done;
|
||||
|
||||
echo "Pixel Beta pif.json generator script \
|
||||
\n by osm0sis @ xda-developers";
|
||||
|
||||
case "$0" in
|
||||
*.sh) DIR="$0";;
|
||||
*) DIR="$(lsof -p $$ 2>/dev/null | grep -o '/.*autopif2.sh$')";;
|
||||
esac;
|
||||
DIR=$(dirname "$(readlink -f "$DIR")");
|
||||
|
||||
item() { echo "\n- $@"; }
|
||||
die() { echo "\nError: $@, install busybox!"; exit 1; }
|
||||
|
||||
find_busybox() {
|
||||
[ -n "$BUSYBOX" ] && return 0;
|
||||
local path;
|
||||
for path in /data/adb/modules/busybox-ndk/system/*/busybox /data/adb/magisk/busybox /data/adb/ksu/bin/busybox /data/adb/ap/bin/busybox; do
|
||||
if [ -f "$path" ]; then
|
||||
BUSYBOX="$path";
|
||||
return 0;
|
||||
fi;
|
||||
done;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if which wget2 >/dev/null; then
|
||||
wget() { wget2 "$@"; }
|
||||
elif ! which wget >/dev/null || grep -q "wget-curl" $(which wget); then
|
||||
if ! find_busybox; then
|
||||
die "wget not found";
|
||||
elif $BUSYBOX ping -c1 -s2 android.com 2>&1 | grep -q "bad address"; then
|
||||
die "wget broken";
|
||||
else
|
||||
wget() { $BUSYBOX wget "$@"; }
|
||||
fi;
|
||||
fi;
|
||||
|
||||
if date -D '%s' -d "$(date '+%s')" 2>&1 | grep -qE "bad date|invalid option"; then
|
||||
if ! find_busybox; then
|
||||
die "date broken";
|
||||
else
|
||||
date() { $BUSYBOX date "$@"; }
|
||||
fi;
|
||||
fi;
|
||||
|
||||
if ! echo "A\nB" | grep -m1 -A1 "A" | grep -q "B"; then
|
||||
if ! find_busybox; then
|
||||
die "grep broken";
|
||||
else
|
||||
grep() { $BUSYBOX grep "$@"; }
|
||||
fi;
|
||||
fi;
|
||||
|
||||
if [ "$DIR" = /data/adb/modules/playintegrityfix ]; then
|
||||
DIR=$DIR/autopif2;
|
||||
mkdir -p $DIR;
|
||||
fi;
|
||||
cd "$DIR";
|
||||
|
||||
item "Crawling Android Developers for latest Pixel Beta ...";
|
||||
wget -q -O PIXEL_VERSIONS_HTML --no-check-certificate https://developer.android.com/about/versions 2>&1 || exit 1;
|
||||
wget -q -O PIXEL_LATEST_HTML --no-check-certificate $(grep -o 'https://developer.android.com/about/versions/.*[0-9]"' PIXEL_VERSIONS_HTML | sort -ru | cut -d\" -f1 | head -n1) 2>&1 || exit 1;
|
||||
if grep -qE 'Developer Preview|tooltip>.*preview program' PIXEL_LATEST_HTML && [ ! "$FORCE_PREVIEW" ]; then
|
||||
wget -q -O PIXEL_BETA_HTML --no-check-certificate $(grep -o 'https://developer.android.com/about/versions/.*[0-9]"' PIXEL_VERSIONS_HTML | sort -ru | cut -d\" -f1 | head -n2 | tail -n1) 2>&1 || exit 1;
|
||||
else
|
||||
TITLE="Preview ";
|
||||
mv -f PIXEL_LATEST_HTML PIXEL_BETA_HTML;
|
||||
fi;
|
||||
wget -q -O PIXEL_OTA_HTML --no-check-certificate https://developer.android.com$(grep -o 'href=".*download-ota.*"' PIXEL_BETA_HTML | cut -d\" -f2 | head -n$FORCE_DEPTH | tail -n1) 2>&1 || exit 1;
|
||||
echo "$(grep -m1 -oE 'tooltip>Android .*[0-9]' PIXEL_OTA_HTML | cut -d\> -f2) $TITLE$(grep -oE 'tooltip>QPR.* Beta' PIXEL_OTA_HTML | cut -d\> -f2 | head -n$FORCE_DEPTH | tail -n1)";
|
||||
|
||||
BETA_REL_DATE="$(date -D '%B %e, %Y' -d "$(grep -m1 -A1 'Release date' PIXEL_OTA_HTML | tail -n1 | sed 's;.*<td>\(.*\)</td>.*;\1;')" '+%Y-%m-%d')";
|
||||
BETA_EXP_DATE="$(date -D '%s' -d "$(($(date -D '%Y-%m-%d' -d "$BETA_REL_DATE" '+%s') + 60 * 60 * 24 * 7 * 6))" '+%Y-%m-%d')";
|
||||
echo "Beta Released: $BETA_REL_DATE \
|
||||
\nEstimated Expiry: $BETA_EXP_DATE";
|
||||
|
||||
MODEL_LIST="$(grep -A1 'tr id=' PIXEL_OTA_HTML | grep 'td' | sed 's;.*<td>\(.*\)</td>;\1;')";
|
||||
PRODUCT_LIST="$(grep -o 'ota/.*_beta' PIXEL_OTA_HTML | cut -d\/ -f2)";
|
||||
OTA_LIST="$(grep 'ota/.*_beta' PIXEL_OTA_HTML | cut -d\" -f2)";
|
||||
|
||||
if [ "$FORCE_MATCH" ]; then
|
||||
DEVICE="$(getprop ro.product.device)";
|
||||
case "$PRODUCT_LIST" in
|
||||
*${DEVICE}_beta*)
|
||||
MODEL="$(getprop ro.product.model)";
|
||||
PRODUCT="${DEVICE}_beta";
|
||||
OTA="$(echo "$OTA_LIST" | grep "$PRODUCT")";
|
||||
;;
|
||||
esac;
|
||||
fi;
|
||||
item "Selecting Pixel Beta device ...";
|
||||
if [ -z "$PRODUCT" ]; then
|
||||
set_random_beta() {
|
||||
local list_count="$(echo "$MODEL_LIST" | wc -l)";
|
||||
local list_rand="$((RANDOM % $list_count + 1))";
|
||||
local IFS=$'\n';
|
||||
set -- $MODEL_LIST;
|
||||
MODEL="$(eval echo \${$list_rand})";
|
||||
set -- $PRODUCT_LIST;
|
||||
PRODUCT="$(eval echo \${$list_rand})";
|
||||
set -- $OTA_LIST;
|
||||
OTA="$(eval echo \${$list_rand})";
|
||||
DEVICE="$(echo "$PRODUCT" | sed 's/_beta//')";
|
||||
}
|
||||
set_random_beta;
|
||||
fi;
|
||||
echo "$MODEL ($PRODUCT)";
|
||||
|
||||
(ulimit -f 2; wget -q -O PIXEL_ZIP_METADATA --no-check-certificate $OTA) 2>/dev/null;
|
||||
FINGERPRINT="$(grep -am1 'post-build=' PIXEL_ZIP_METADATA 2>/dev/null | cut -d= -f2)";
|
||||
SECURITY_PATCH="$(grep -am1 'security-patch-level=' PIXEL_ZIP_METADATA 2>/dev/null | cut -d= -f2)";
|
||||
if [ -z "$FINGERPRINT" -o -z "$SECURITY_PATCH" ]; then
|
||||
echo "\nError: Failed to extract information from metadata!";
|
||||
exit 1;
|
||||
fi;
|
||||
|
||||
item "Dumping values to minimal pif.json ...";
|
||||
cat <<EOF | tee pif.json;
|
||||
{
|
||||
"MANUFACTURER": "Google",
|
||||
"MODEL": "$MODEL",
|
||||
"FINGERPRINT": "$FINGERPRINT",
|
||||
"PRODUCT": "$PRODUCT",
|
||||
"DEVICE": "$DEVICE",
|
||||
"SECURITY_PATCH": "$SECURITY_PATCH",
|
||||
"DEVICE_INITIAL_SDK_INT": "32"
|
||||
}
|
||||
EOF
|
||||
|
||||
for MIGRATE in migrate.sh /data/adb/modules/playintegrityfix/migrate.sh; do
|
||||
[ -f "$MIGRATE" ] && break;
|
||||
done;
|
||||
if [ -f "$MIGRATE" ]; then
|
||||
OLDJSON=/data/adb/modules/playintegrityfix/custom.pif.json;
|
||||
if [ -f "$OLDJSON" ]; then
|
||||
grep -q '//"\*.security_patch"' $OLDJSON && PATCH_COMMENT=1;
|
||||
grep -qE "verboseLogs|VERBOSE_LOGS" $OLDJSON && ARGS="-a";
|
||||
fi;
|
||||
[ -f /data/adb/tricky_store/security_patch.txt ] && unset PATCH_COMMENT;
|
||||
item "Converting pif.json to custom.pif.json with migrate.sh:";
|
||||
rm -f custom.pif.json;
|
||||
sh $MIGRATE -i $ARGS pif.json;
|
||||
if [ -n "$ARGS" ]; then
|
||||
grep_json() { [ -f "$2" ] && grep -m1 "$1" $2 | cut -d\" -f4; }
|
||||
verboseLogs=$(grep_json "VERBOSE_LOGS" $OLDJSON);
|
||||
ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingSdk verboseLogs";
|
||||
for SETTING in $ADVSETTINGS; do
|
||||
eval [ -z \"\$$SETTING\" ] \&\& $SETTING=$(grep_json "$SETTING" $OLDJSON);
|
||||
eval TMPVAL=\$$SETTING;
|
||||
[ -n "$TMPVAL" ] && sed -i "s;\($SETTING\": \"\).;\1$TMPVAL;" custom.pif.json;
|
||||
done;
|
||||
fi;
|
||||
[ "$PATCH_COMMENT" ] && sed -i 's;"\*.security_patch";//"\*.security_patch";' custom.pif.json;
|
||||
sed -i "s;};\n // Beta Released: $BETA_REL_DATE\n // Estimated Expiry: $BETA_EXP_DATE\n};" custom.pif.json;
|
||||
cat custom.pif.json;
|
||||
fi;
|
||||
|
||||
if [ "$DIR" = /data/adb/modules/playintegrityfix/autopif2 ]; then
|
||||
if [ -f /data/adb/modules/playintegrityfix/migrate.sh ]; then
|
||||
NEWNAME="custom.pif.json";
|
||||
else
|
||||
NEWNAME="pif.json";
|
||||
fi;
|
||||
if [ -f "../$NEWNAME" ]; then
|
||||
item "Renaming old file to $NEWNAME.bak ...";
|
||||
mv -fv ../$NEWNAME ../$NEWNAME.bak;
|
||||
fi;
|
||||
item "Installing new json ...";
|
||||
cp -fv $NEWNAME ..;
|
||||
TS_SECPAT=/data/adb/tricky_store/security_patch.txt;
|
||||
if [ -f "$TS_SECPAT" ]; then
|
||||
item "Updating Tricky Store security_patch.txt ...";
|
||||
[ -s "$TS_SECPAT" ] || echo "all=" > $TS_SECPAT;
|
||||
grep -q 'all=' $TS_SECPAT && sed -i "s/all=.*/all=$SECURITY_PATCH/" $TS_SECPAT;
|
||||
grep -q 'system=' $TS_SECPAT && sed -i "s/system=.*/system=$(echo ${SECURITY_PATCH//-} | cut -c-6)/" $TS_SECPAT;
|
||||
cat $TS_SECPAT;
|
||||
fi;
|
||||
if [ -f /data/adb/modules/playintegrityfix/killpi.sh ]; then
|
||||
item "Killing any running GMS DroidGuard/Play Store processes ...";
|
||||
sh /data/adb/modules/playintegrityfix/killpi.sh 2>&1 || true;
|
||||
fi;
|
||||
fi;
|
||||
@@ -1,3 +1,32 @@
|
||||
SKIPDELPROP=false
|
||||
[ -f "$MODPATH/skipdelprop" ] && SKIPDELPROP=true
|
||||
|
||||
# delprop_if_exist <prop name>
|
||||
delprop_if_exist() {
|
||||
local NAME="$1"
|
||||
|
||||
[ -n "$(resetprop "$NAME")" ] && resetprop --delete "$NAME"
|
||||
}
|
||||
|
||||
# persistprop <prop name> <new value>
|
||||
persistprop() {
|
||||
local NAME="$1"
|
||||
local NEWVALUE="$2"
|
||||
local CURVALUE="$(resetprop "$NAME")"
|
||||
|
||||
if ! grep -q "$NAME" $MODPATH/uninstall.sh 2>/dev/null; then
|
||||
if [ "$CURVALUE" ]; then
|
||||
[ "$NEWVALUE" = "$CURVALUE" ] || echo "resetprop -n -p \"$NAME\" \"$CURVALUE\"" >> $MODPATH/uninstall.sh
|
||||
else
|
||||
echo "resetprop -p --delete \"$NAME\"" >> $MODPATH/uninstall.sh
|
||||
fi
|
||||
fi
|
||||
resetprop -n -p "$NAME" "$NEWVALUE"
|
||||
}
|
||||
|
||||
RESETPROP="resetprop -n"
|
||||
[ -f /data/adb/magisk/util_functions.sh ] && [ "$(grep MAGISK_VER_CODE /data/adb/magisk/util_functions.sh | cut -d= -f2)" -lt 27003 ] && RESETPROP=resetprop_hexpatch
|
||||
|
||||
# resetprop_hexpatch [-f|--force] <prop name> <new value>
|
||||
resetprop_hexpatch() {
|
||||
case "$1" in
|
||||
@@ -18,7 +47,7 @@ resetprop_hexpatch() {
|
||||
local PROPFILE="/dev/__properties__/$(resetprop -Z "$NAME")"
|
||||
fi
|
||||
[ ! -f "$PROPFILE" ] && return 3
|
||||
local NAMEOFFSET=$(echo $(strings -t d "$PROPFILE" | grep "$NAME") | cut -d ' ' -f 1)
|
||||
local NAMEOFFSET=$(echo $(strings -t d "$PROPFILE" | grep "$NAME") | cut -d\ -f1)
|
||||
|
||||
#<hex 2-byte change counter><flags byte><hex length of prop value><prop value + nul padding to 92 bytes><prop name>
|
||||
local NEWHEX="$(printf '%02x' "$NEWLEN")$(printf "$NEWVALUE" | od -A n -t x1 -v | tr -d ' \n')$(printf "%$((92-NEWLEN))s" | sed 's/ /00/g')"
|
||||
@@ -37,7 +66,7 @@ resetprop_if_diff() {
|
||||
local EXPECTED="$2"
|
||||
local CURRENT="$(resetprop "$NAME")"
|
||||
|
||||
[ -z "$CURRENT" ] || [ "$CURRENT" = "$EXPECTED" ] || resetprop_hexpatch "$NAME" "$EXPECTED"
|
||||
[ -z "$CURRENT" ] || [ "$CURRENT" = "$EXPECTED" ] || $RESETPROP "$NAME" "$EXPECTED"
|
||||
}
|
||||
|
||||
# resetprop_if_match <prop name> <value match string> <new value>
|
||||
@@ -46,7 +75,7 @@ resetprop_if_match() {
|
||||
local CONTAINS="$2"
|
||||
local VALUE="$3"
|
||||
|
||||
[[ "$(resetprop "$NAME")" = *"$CONTAINS"* ]] && resetprop_hexpatch "$NAME" "$VALUE"
|
||||
[[ "$(resetprop "$NAME")" = *"$CONTAINS"* ]] && $RESETPROP "$NAME" "$VALUE"
|
||||
}
|
||||
|
||||
# stub for boot-time
|
||||
|
||||
@@ -39,7 +39,7 @@ for APP in $(grep -v '^#' $LIST); do
|
||||
APK=$(readlink -f $APP);
|
||||
fi
|
||||
if [ -s "$APK" ]; then
|
||||
PKGNAME=$(unzip -p $APK AndroidManifest.xml | tr -d '\0' | grep -oE '[[:alnum:].-_]+\*http' | cut -d\* -f1)
|
||||
PKGNAME=$(unzip -p $APK AndroidManifest.xml | tr -d '\0' | grep -oE 'android.*overlay' | strings | tr -d '\n' | sed -e 's/^android//' -e 's/application//' -e 's;*http.*res/android;;' -e 's/manifest//' -e 's/overlay$//' | grep -oE '[[:alnum:].-_].*overlay' | cut -d\ -f2)
|
||||
if [ "$PKGNAME" ] && grep -q "overlay package=\"$PKGNAME" $CFG; then
|
||||
HIDECFG=$MODPATH$PREFIX$CFG
|
||||
if [ ! -f "$HIDECFG" ]; then
|
||||
@@ -59,9 +59,21 @@ for APP in $(grep -v '^#' $LIST); do
|
||||
fi
|
||||
done
|
||||
|
||||
# Work around AOSPA PropImitationHooks conflict when their persist props don't exist
|
||||
if [ -n "$(resetprop ro.aospa.version)" ]; then
|
||||
for PROP in persist.sys.pihooks.first_api_level persist.sys.pihooks.security_patch; do
|
||||
resetprop | grep -q "\[$PROP\]" || resetprop -n -p "$PROP" "";
|
||||
done;
|
||||
fi;
|
||||
# Work around custom ROM PropImitationHooks conflict when their persist props don't exist
|
||||
if [ -n "$(resetprop ro.aospa.version)" -o -n "$(resetprop net.pixelos.version)" -o -n "$(resetprop ro.afterlife.version)" -o -f /data/system/gms_certified_props.json ]; then
|
||||
for PROP in persist.sys.pihooks.first_api_level persist.sys.pihooks.security_patch; do
|
||||
resetprop | grep -q "\[$PROP\]" || persistprop "$PROP" ""
|
||||
done
|
||||
fi
|
||||
|
||||
# Work around supported custom ROM PropImitationHooks/PixelPropsUtils (and hybrids) conflict when spoofProvider is disabled
|
||||
if resetprop | grep -qE "persist.sys.pihooks|persist.sys.entryhooks|persist.sys.spoof|persist.sys.pixelprops" || [ -f /data/system/gms_certified_props.json ]; then
|
||||
persistprop persist.sys.pihooks.disable.gms_props true
|
||||
persistprop persist.sys.pihooks.disable.gms_key_attestation_block true
|
||||
persistprop persist.sys.entryhooks_enabled false
|
||||
persistprop persist.sys.spoof.gms false
|
||||
persistprop persist.sys.pixelprops.gms false
|
||||
persistprop persist.sys.pixelprops.gapps false
|
||||
persistprop persist.sys.pixelprops.google false
|
||||
persistprop persist.sys.pixelprops.pi false
|
||||
fi
|
||||
|
||||
@@ -3,21 +3,24 @@ if [ -f /data/adb/modules/playintegrityfix/scripts-only-mode ]; then
|
||||
ui_print "! Installing global scripts only; Zygisk attestation fallback and device spoofing disabled"
|
||||
touch $MODPATH/scripts-only-mode
|
||||
sed -i 's/\(description=\)\(.*\)/\1[Scripts-only mode] \2/' $MODPATH/module.prop
|
||||
rm -rf $MODPATH/autopif.sh $MODPATH/classes.dex $MODPATH/common_setup.sh \
|
||||
[ -f /data/adb/modules/playintegrityfix/uninstall.sh ] && sh /data/adb/modules/playintegrityfix/uninstall.sh
|
||||
rm -rf $MODPATH/action.sh $MODPATH/autopif2.sh $MODPATH/classes.dex $MODPATH/common_setup.sh \
|
||||
$MODPATH/custom.pif.json $MODPATH/example.app_replace.list $MODPATH/example.pif.json \
|
||||
$MODPATH/killgms.sh $MODPATH/migrate.sh $MODPATH/zygisk \
|
||||
$MODPATH/migrate.sh $MODPATH/pif.json $MODPATH/zygisk \
|
||||
/data/adb/modules/playintegrityfix/custom.app_replace.list \
|
||||
/data/adb/modules/playintegrityfix/custom.pif.json /data/adb/modules/playintegrityfix/system
|
||||
/data/adb/modules/playintegrityfix/custom.pif.json \
|
||||
/data/adb/modules/playintegrityfix/system \
|
||||
/data/adb/modules/playintegrityfix/uninstall.sh
|
||||
fi
|
||||
|
||||
# Copy any disabled app files to updated module
|
||||
if [ -d /data/adb/modules/playintegrityfix/system ]; then
|
||||
ui_print "- Restoring disabled ROM apps configuration"
|
||||
cp -arf /data/adb/modules/playintegrityfix/system $MODPATH
|
||||
cp -afL /data/adb/modules/playintegrityfix/system $MODPATH
|
||||
fi
|
||||
|
||||
# Copy any supported custom files to updated module
|
||||
for FILE in custom.app_replace.list custom.pif.json; do
|
||||
for FILE in custom.app_replace.list custom.pif.json skipdelprop uninstall.sh; do
|
||||
if [ -f "/data/adb/modules/playintegrityfix/$FILE" ]; then
|
||||
ui_print "- Restoring $FILE"
|
||||
cp -af /data/adb/modules/playintegrityfix/$FILE $MODPATH/$FILE
|
||||
@@ -30,14 +33,17 @@ if [ -d /data/adb/modules/MagiskHidePropsConf ]; then
|
||||
fi
|
||||
|
||||
# Run common tasks for installation and boot-time
|
||||
[ -d "$MODPATH/zygisk" ] && . $MODPATH/common_setup.sh
|
||||
if [ -d "$MODPATH/zygisk" ]; then
|
||||
. $MODPATH/common_func.sh
|
||||
. $MODPATH/common_setup.sh
|
||||
fi
|
||||
|
||||
# Migrate custom.pif.json to latest defaults if needed
|
||||
if [ -f "$MODPATH/custom.pif.json" ] && ! grep -q "api_level" $MODPATH/custom.pif.json; then
|
||||
ui_print "- Running migration script on custom.pif.json:"
|
||||
ui_print " "
|
||||
chmod 755 $MODPATH/migrate.sh
|
||||
sh $MODPATH/migrate.sh install $MODPATH/custom.pif.json
|
||||
sh $MODPATH/migrate.sh --install --advanced $MODPATH/custom.pif.json
|
||||
ui_print " "
|
||||
fi
|
||||
|
||||
|
||||
@@ -11,11 +11,13 @@
|
||||
/system/app/EliteDevelopmentModule
|
||||
/system/app/XInjectModule
|
||||
|
||||
# hentaiOS
|
||||
# helluvaOS, hentaiOS
|
||||
/system_ext/app/helluvaProductDevice*
|
||||
/system_ext/app/helluvaProductSecretStub
|
||||
/system_ext/app/hentaiLewdbSVTDummy
|
||||
|
||||
# Evolution X
|
||||
/system_ext/app/PifPrebuilt
|
||||
|
||||
# PixelOS
|
||||
# PixelOS, YAAP
|
||||
/system_ext/overlay/CertifiedPropsOverlay.apk
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// These are the current suggested defaults but you may add as many other fields/properties as needed
|
||||
//
|
||||
// See android.os.Build source for all field values' corresponding properties:
|
||||
// See android.os.Build source for all fields and field values' corresponding properties:
|
||||
// https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/Build.java
|
||||
|
||||
{
|
||||
@@ -24,5 +24,13 @@
|
||||
// System Properties
|
||||
"*.build.id": "", // for ro.build.id
|
||||
"*.security_patch": "", // for ro.build.version.security_patch
|
||||
"*api_level": "" // for ro.board.api_level, ro.board.first_api_level, ro.product.first_api_level and ro.vendor.api_level
|
||||
"*api_level": "", // for ro.board.api_level, ro.board.first_api_level, ro.product.first_api_level and ro.vendor.api_level
|
||||
|
||||
// Advanced Settings
|
||||
"spoofBuild": "1",
|
||||
"spoofProps": "1",
|
||||
"spoofProvider": "1",
|
||||
"spoofSignature": "0",
|
||||
"spoofVendingSdk": "0",
|
||||
"verboseLogs": "0"
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/system/bin/sh
|
||||
# killgms.sh by osm0sis @ xda-developers
|
||||
#
|
||||
# Kill the Google Play services DroidGuard process
|
||||
# (com.google.android.gms.unstable)
|
||||
|
||||
if [ "$USER" != "root" -o "$(whoami 2>/dev/null)" != "root" ]; then
|
||||
echo "killgms: need root permissions";
|
||||
exit 1;
|
||||
fi;
|
||||
|
||||
killall -v com.google.android.gms.unstable;
|
||||
13
module/killpi.sh
Normal file
13
module/killpi.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/system/bin/sh
|
||||
# killpi.sh by osm0sis @ xda-developers
|
||||
#
|
||||
# Kill the Google Play services DroidGuard and Play Store processes
|
||||
# (com.google.android.gms.unstable and com.android.vending)
|
||||
|
||||
if [ "$USER" != "root" -a "$(whoami 2>/dev/null)" != "root" ]; then
|
||||
echo "killpi: need root permissions";
|
||||
exit 1;
|
||||
fi;
|
||||
|
||||
killall -v com.google.android.gms.unstable;
|
||||
killall -v com.android.vending;
|
||||
@@ -1,13 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
case "$1" in
|
||||
-h|--help|help) echo "sh migrate.sh [-f] [-o] [-a] [in-file] [out-file]"; exit 0;;
|
||||
esac;
|
||||
|
||||
N="
|
||||
";
|
||||
|
||||
case "$1" in
|
||||
-h|--help|help) echo "sh migrate.sh [-f] [-o] [-a] [in-file] [out-file]"; exit 0;;
|
||||
-i|--install|install) INSTALL=1; shift;;
|
||||
*) echo "custom.pif.json migration script \
|
||||
$N by osm0sis @ xda-developers $N";;
|
||||
@@ -15,18 +12,26 @@ esac;
|
||||
|
||||
item() { echo "- $@"; }
|
||||
die() { [ "$INSTALL" ] || echo "$N$N! $@"; exit 1; }
|
||||
grep_get_json() { eval set -- "$(cat "$FILE" | tr -d '\r\n' | grep -m1 -o "$1"'".*' | cut -d: -f2-)"; echo "$1" | sed -e 's|"|\\\\\\"|g' -e 's|[,}]*$||'; }
|
||||
grep_check_json() { grep -q "$1" "$FILE" && [ "$(grep_get_json $1)" ]; }
|
||||
grep_get_json() {
|
||||
local target="$FILE";
|
||||
[ -n "$2" ] && target="$2";
|
||||
eval set -- "$(cat "$target" | tr -d '\r\n' | grep -m1 -o "$1"'".*' | cut -d: -f2- | sed 's|//|#|g')";
|
||||
echo "$1" | sed -e 's|"|\\\\\\"|g' -e 's|[,}]*$||';
|
||||
}
|
||||
grep_check_json() {
|
||||
local target="$FILE";
|
||||
[ -n "$2" ] && target="$2";
|
||||
grep -q "$1" "$target" && [ "$(grep_get_json $1 "$target")" ];
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
-f|--force|force) FORCE=1; shift;;
|
||||
esac;
|
||||
case "$1" in
|
||||
-o|--override|override) OVERRIDE=1; shift;;
|
||||
esac;
|
||||
case "$1" in
|
||||
-a|--advanced|advanced) ADVANCED=1; shift;;
|
||||
esac;
|
||||
until [ -z "$1" -o -f "$1" ]; do
|
||||
case "$1" in
|
||||
-f|--force|force) FORCE=1; shift;;
|
||||
-o|--override|override) OVERRIDE=1; shift;;
|
||||
-a|--advanced|advanced) ADVANCED=1; shift;;
|
||||
*) die "Invalid argument/file not found: $1";;
|
||||
esac;
|
||||
done;
|
||||
|
||||
if [ -f "$1" ]; then
|
||||
FILE="$1";
|
||||
@@ -109,10 +114,26 @@ if [ -z "$DEVICE_INITIAL_SDK_INT" -o "$DEVICE_INITIAL_SDK_INT" = "null" ]; then
|
||||
DEVICE_INITIAL_SDK_INT=25;
|
||||
fi;
|
||||
|
||||
ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingSdk verboseLogs";
|
||||
|
||||
spoofBuild=1;
|
||||
spoofProps=1;
|
||||
spoofProvider=1;
|
||||
spoofSignature=0;
|
||||
spoofVendingSdk=0;
|
||||
verboseLogs=0;
|
||||
|
||||
if [ -f "$OUT" ]; then
|
||||
item "Renaming old file to $(basename "$OUT").bak ...";
|
||||
mv -f "$OUT" "$OUT.bak";
|
||||
grep -qE "verboseLogs|VERBOSE_LOGS" "$OUT.bak" && ADVANCED=1;
|
||||
if grep -qE "verboseLogs|VERBOSE_LOGS" "$OUT.bak"; then
|
||||
ADVANCED=1;
|
||||
grep_check_json VERBOSE_LOGS "$OUT.bak" && verboseLogs="$(grep_get_json VERBOSE_LOGS "$OUT.bak")";
|
||||
for SETTING in $ADVSETTINGS; do
|
||||
eval grep_check_json $SETTING \"$OUT.bak\" \&\& $SETTING=\"$(grep_get_json $SETTING "$OUT.bak")\";
|
||||
done;
|
||||
grep -q '//"\*.security_patch"' "$OUT.bak" && SECURITY_COMMENT='//';
|
||||
fi;
|
||||
fi;
|
||||
|
||||
[ "$INSTALL" ] || item "Writing fields and properties to updated custom.pif.json ...";
|
||||
@@ -124,12 +145,14 @@ for FIELD in $ALLFIELDS; do
|
||||
done;
|
||||
echo "$N // System Properties";
|
||||
echo ' "*.build.id": "'$ID'",';
|
||||
echo ' "*.security_patch": "'$SECURITY_PATCH'",';
|
||||
echo " $SECURITY_COMMENT"'"*.security_patch": "'$SECURITY_PATCH'",';
|
||||
[ -z "$VNDK_VERSION" ] || echo ' "*.vndk.version": "'$VNDK_VERSION'",';
|
||||
echo ' "*api_level": "'$DEVICE_INITIAL_SDK_INT'",';
|
||||
if [ "$ADVANCED" ]; then
|
||||
echo "$N // Advanced Settings";
|
||||
echo ' "verboseLogs": "0",';
|
||||
for SETTING in $ADVSETTINGS; do
|
||||
eval echo '\ \ \ \ \"$SETTING\": \"'\$$SETTING'\",';
|
||||
done;
|
||||
fi) | sed '$s/,/\n}/' > "$OUT";
|
||||
|
||||
[ "$INSTALL" ] || cat "$OUT";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
id=playintegrityfix
|
||||
name=Play Integrity Fork
|
||||
version=v9
|
||||
versionCode=90000
|
||||
version=v13
|
||||
versionCode=130001
|
||||
author=osm0sis & chiteroman @ xda-developers
|
||||
description=Fix CTS profile (SafetyNet) and DEVICE verdict (Play Integrity)
|
||||
description=Fix <A13 DEVICE (Play Integrity) verdict
|
||||
updateJson=https://raw.githubusercontent.com/osm0sis/PlayIntegrityFork/main/update.json
|
||||
|
||||
@@ -2,15 +2,17 @@ MODPATH="${0%/*}"
|
||||
. $MODPATH/common_func.sh
|
||||
|
||||
if [ -d "$MODPATH/zygisk" ]; then
|
||||
# Remove Play Services from Magisk DenyList when set to Enforce in normal mode
|
||||
# Remove Play Services and Play Store from Magisk DenyList when set to Enforce in normal mode
|
||||
if magisk --denylist status; then
|
||||
magisk --denylist rm com.google.android.gms
|
||||
magisk --denylist rm com.android.vending
|
||||
fi
|
||||
# Run common tasks for installation and boot-time
|
||||
. $MODPATH/common_setup.sh
|
||||
else
|
||||
# Add Play Services DroidGuard process to Magisk DenyList for better results in scripts-only mode
|
||||
# Add Play Services DroidGuard and Play Store processes to Magisk DenyList for better results in scripts-only mode
|
||||
magisk --denylist add com.google.android.gms com.google.android.gms.unstable
|
||||
magisk --denylist add com.android.vending
|
||||
fi
|
||||
|
||||
# Conditional early sensitive properties
|
||||
@@ -21,9 +23,6 @@ resetprop_if_diff ro.vendor.boot.warranty_bit 0
|
||||
resetprop_if_diff ro.vendor.warranty_bit 0
|
||||
resetprop_if_diff ro.warranty_bit 0
|
||||
|
||||
# Xiaomi
|
||||
resetprop_if_diff ro.secureboot.lockstate locked
|
||||
|
||||
# Realme
|
||||
resetprop_if_diff ro.boot.realmebootstate green
|
||||
|
||||
@@ -31,9 +30,20 @@ resetprop_if_diff ro.boot.realmebootstate green
|
||||
resetprop_if_diff ro.is_ever_orange 0
|
||||
|
||||
# Microsoft
|
||||
resetprop_if_diff ro.build.tags release-keys
|
||||
for PROP in $(resetprop | grep -oE 'ro.*.build.tags'); do
|
||||
resetprop_if_diff $PROP release-keys
|
||||
done
|
||||
|
||||
# Other
|
||||
resetprop_if_diff ro.build.type user
|
||||
for PROP in $(resetprop | grep -oE 'ro.*.build.type'); do
|
||||
resetprop_if_diff $PROP user
|
||||
done
|
||||
resetprop_if_diff ro.adb.secure 1
|
||||
if ! $SKIPDELPROP; then
|
||||
delprop_if_exist ro.boot.verifiedbooterror
|
||||
delprop_if_exist ro.boot.verifyerrorpart
|
||||
fi
|
||||
resetprop_if_diff ro.boot.veritymode.managed yes
|
||||
resetprop_if_diff ro.debuggable 0
|
||||
resetprop_if_diff ro.force.debuggable 0
|
||||
resetprop_if_diff ro.secure 1
|
||||
|
||||
@@ -3,18 +3,18 @@ MODPATH="${0%/*}"
|
||||
|
||||
# Conditional sensitive properties
|
||||
|
||||
# Magisk recovery mode
|
||||
resetprop_if_match ro.bootmode recovery unknown
|
||||
# Magisk Recovery Mode
|
||||
resetprop_if_match ro.boot.mode recovery unknown
|
||||
resetprop_if_match ro.bootmode recovery unknown
|
||||
resetprop_if_match vendor.boot.mode recovery unknown
|
||||
|
||||
# SELinux
|
||||
resetprop_if_diff ro.boot.selinux enforcing
|
||||
# use delete since it can be 0 or 1 for enforcing depending on OEM
|
||||
if [ -n "$(resetprop ro.build.selinux)" ]; then
|
||||
resetprop --delete ro.build.selinux
|
||||
if ! $SKIPDELPROP; then
|
||||
delprop_if_exist ro.build.selinux
|
||||
fi
|
||||
# use toybox to protect *stat* access time reading
|
||||
# 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
|
||||
@@ -22,25 +22,28 @@ fi
|
||||
|
||||
# Conditional late sensitive properties
|
||||
|
||||
# SafetyNet/Play Integrity
|
||||
# must be set after boot_completed for various OEMs
|
||||
{
|
||||
# must be set after boot_completed for various OEMs
|
||||
until [ "$(getprop sys.boot_completed)" = "1" ]; do
|
||||
sleep 1
|
||||
done
|
||||
until [ "$(getprop sys.boot_completed)" = "1" ]; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# avoid breaking Realme fingerprint scanners
|
||||
resetprop_if_diff ro.boot.flash.locked 1
|
||||
resetprop_if_diff ro.boot.realme.lockstate 1
|
||||
# SafetyNet/Play Integrity + OEM
|
||||
# avoid bootloop on some Xiaomi devices
|
||||
resetprop_if_diff ro.secureboot.lockstate locked
|
||||
# avoid breaking Realme fingerprint scanners
|
||||
resetprop_if_diff ro.boot.flash.locked 1
|
||||
resetprop_if_diff ro.boot.realme.lockstate 1
|
||||
# avoid breaking Oppo fingerprint scanners
|
||||
resetprop_if_diff ro.boot.vbmeta.device_state locked
|
||||
# avoid breaking OnePlus display modes/fingerprint scanners
|
||||
resetprop_if_diff vendor.boot.verifiedbootstate green
|
||||
# avoid breaking OnePlus/Oppo fingerprint scanners on OOS/ColorOS 12+
|
||||
resetprop_if_diff ro.boot.verifiedbootstate green
|
||||
resetprop_if_diff ro.boot.veritymode enforcing
|
||||
resetprop_if_diff vendor.boot.vbmeta.device_state locked
|
||||
|
||||
# avoid breaking Oppo fingerprint scanners
|
||||
resetprop_if_diff ro.boot.vbmeta.device_state locked
|
||||
# Other
|
||||
resetprop_if_diff sys.oem_unlock_allowed 0
|
||||
|
||||
# avoid breaking OnePlus display modes/fingerprint scanners
|
||||
resetprop_if_diff vendor.boot.verifiedbootstate green
|
||||
|
||||
# avoid breaking OnePlus/Oppo fingerprint scanners on OOS/ColorOS 12+
|
||||
resetprop_if_diff ro.boot.verifiedbootstate green
|
||||
resetprop_if_diff ro.boot.veritymode enforcing
|
||||
resetprop_if_diff vendor.boot.vbmeta.device_state locked
|
||||
}&
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "v9",
|
||||
"versionCode": 90000,
|
||||
"zipUrl": "https://github.com/osm0sis/PlayIntegrityFork/releases/download/v9/PlayIntegrityFork-v9.zip",
|
||||
"version": "v13",
|
||||
"versionCode": 130000,
|
||||
"zipUrl": "https://github.com/osm0sis/PlayIntegrityFork/releases/download/v13/PlayIntegrityFork-v13.zip",
|
||||
"changelog": "https://raw.githubusercontent.com/osm0sis/PlayIntegrityFork/main/CHANGELOG.md"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user