84 Commits

Author SHA1 Message Date
Chris Renshaw
1afd4278be Avoid potential issues from greedy matching 2025-06-28 01:19:15 -03:00
Chris Renshaw
77d5ccdc99 Cosmetic changes to match other cut usage 2025-06-28 01:06:52 -03:00
Chris Renshaw
a2f726b633 Improve overlay AndroidManifest.xml parsing, support PixelOS 15 2025-06-28 00:52:06 -03:00
Chris Renshaw
38631f685a Allow CI builds on demand 2025-06-23 19:17:21 -03:00
osm0sis
39d2610579 Refine proguard rules further
Thanks @TheFreeman193!
2025-06-22 20:38:24 -03:00
Chris Renshaw
0132ebb272 Fix persistprop during installation
Thanks geekboy38 on xda!
2025-06-20 09:03:18 -03:00
osm0sis
a82914221e README: document spoofVendingSdk, add credit for original PIF repo, fixes 2025-06-16 23:03:10 -03:00
Chris Renshaw
4755f88180 Promote autopif2 --match to documented feature
-m or --match will attempt to match the print to your current device if run on a Pixel, and will otherwise fall back to random

- make matching the Action button default since there was some evidence that matching your actual Pixel device may be important for accessing the Pixel exclusive features for your device
2025-06-11 23:05:58 -03:00
Chris Renshaw
62150ce6d4 Add Advanced Settings to example.pif.json
- needing the Advanced Settings is the more likely scenario nowadays, so display them more prominently to help people know how to use them
2025-06-11 22:36:15 -03:00
Chris Renshaw
88573ca743 Show Advanced Settings by default from install migrate and autopif2 2025-06-11 22:17:29 -03:00
Chris Renshaw
89de098a83 Update SDK Build Tools 2025-06-11 10:22:04 -03:00
Chris Renshaw
c6739dfa42 Promote experimental spoofVendingSdk to Advanced Settings
- many are experimenting and using it already across forks anyway 
- proper documentation to come for next stable release with known issues and potential use cases
2025-06-11 10:19:34 -03:00
osm0sis
a7dd416873 Revert "Disable R8 until proguard rules can be reimplemented correctly"
- resolved in 539ff7351a

This reverts commit 2cdee60781.
2025-06-11 01:16:44 -03:00
osm0sis
539ff7351a Fix proguard rules for AGP 8.9.0+
- CustomPackageInfoCreator public methods must now be explicitly kept to avoid spoofSignature crashes documented in 2cdee60781
2025-06-11 01:14:03 -03:00
osm0sis
0cd56584df Update AGP 2025-06-09 23:06:39 -03:00
osm0sis
2cdee60781 Disable R8 until proguard rules can be reimplemented correctly
- most Java classes were being kept fully unoptimized anyway, which should be generally avoided
- AGP 8.9.0-alpha07 is the last where spoofSignature works with R8 enabled, alpha08 and all later AGP results in:
  msg: java.lang.StackOverflowError: stack size 8188KB
  stacktrace: java.lang.StackOverflowError: stack size 8188KB
	at es.chiteroman.playintegrityfix.CustomPackageInfoCreator.createFromParcel(Unknown Source:2)
  [TRUNCATED 3288424 CHARS]
	at es.chiteroman.playintegrityfix.CustomPackageInfoCreator.createFromParcel(Unknown Source:2)
	at android.os.Parcel.readTypedObject(Parcel.java:4025)
	at android.content.pm.IPackageManager$Stub$Proxy.getPackageInfo(IPackageManager.java:4470)
	at android.content.pm.PackageManager.getPackageInfoAsUserUncached(PackageManager.java:10969)
	at android.content.pm.PackageManager.-$$Nest$smgetPackageInfoAsUserUncached(Unknown Source:0)
	at android.content.pm.PackageManager$2.recompute(PackageManager.java:10982)
	at android.content.pm.PackageManager$2.recompute(PackageManager.java:10979)
	at android.app.PropertyInvalidatedCache.query(PropertyInvalidatedCache.java:999)
	at android.content.pm.PackageManager.getPackageInfoAsUserCached(PackageManager.java:10996)
	at android.app.LoadedApk.initializeJavaContextClassLoader(LoadedApk.java:1215)
	at android.app.LoadedApk.makeApplicationInner(LoadedApk.java:1448)
	at android.app.LoadedApk.makeApplicationInner(LoadedApk.java:1405)
	at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7029)
	at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2262)
	at android.os.Handler.dispatchMessage(Handler.java:106)
	at android.os.Looper.loopOnce(Looper.java:205)
	at android.os.Looper.loop(Looper.java:294)
	at android.app.ActivityThread.main(ActivityThread.java:8282)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:554)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:885)
2025-06-09 23:03:47 -03:00
Chris Renshaw
7e376e5627 Update libcxx 2025-06-08 01:59:21 -03:00
Chris Renshaw
ec34417cd9 Also add new PIHooks detection to empty prop workaround 2025-06-08 01:46:26 -03:00
Chris Renshaw
0b957b13b9 Add support for disabling more PIHooks variants 2025-06-08 01:34:30 -03:00
Chris Renshaw
ec374a7d9b Fix persist prop deletion 2025-06-08 00:38:26 -03:00
Chris Renshaw
17db1e7177 Keep uninstall.sh through updates
- uninstall.sh is generated at first install so it must be kept to ensure it has the original states/values for the persist props
- run then remove uninstall.sh if it exists when switching to Scripts-Only Mode
2025-06-07 23:54:50 -03:00
osm0sis
451769c341 Clean up any modified custom ROM persist props on uninstall 2025-06-07 23:54:48 -03:00
osm0sis
77f91e3a85 Add new persistprop common function 2025-06-07 08:57:58 -03:00
osm0sis
b4eae8a6b6 Update Gradle 2025-06-07 08:38:53 -03:00
Chris Renshaw
05520f7881 autopif2.sh: abort if --depth arg is not a single digit positive integer 2025-06-01 21:54:05 -03:00
Chris Renshaw
1745060524 No stacktraces needed though
The remaining Gradle deprecation warnings are from Android Gradle Plugin (AGP), so figuring out why AGP 8.9.x+ breaks spoofSignature, and fixing that so that AGP can be updated is the only way to resolve things for Gradle 9.0:

Declaring an 'is-' property with a Boolean type has been deprecated. Starting with Gradle 9.0, this property will be ignored by Gradle.
[...]
Add a method named 'getCrunchPngs' with the same behavior and mark the old one with @Deprecated, or change the type of 'com.android.build.gradle.internal.dsl.BuildType$AgpDecorated.isCrunchPngs' (and the setter) to 'boolean'. [...]
Add a method named 'getUseProguard' with the same behavior and mark the old one with @Deprecated, or change the type of 'com.android.build.gradle.internal.dsl.BuildType.isUseProguard' (and the setter) to 'boolean'. [...]
Add a method named 'getWearAppUnbundled' with the same behavior and mark the old one with @Deprecated, or change the type of 'com.android.build.api.variant.impl.ApplicationVariantImpl.isWearAppUnbundled' (and the setter) to 'boolean'. [...]
2025-06-01 20:49:48 -03:00
Chris Renshaw
512ed8a1f1 Show all Gradle warnings in CI 2025-05-31 23:45:56 -03:00
osm0sis
0d8d090014 Suppress PackageInfo signatures deprecated API warning 2025-05-31 21:51:15 -03:00
osm0sis
0d03f99499 Fix Gradle Task.project execution time deprecation warning 2025-05-31 21:24:48 -03:00
osm0sis
85dd219ea3 Update Gradle 2025-05-31 11:32:11 -03:00
osm0sis
36cc9573ba Update Dobby submodule to JingMatrix fork 2025-05-31 11:27:28 -03:00
osm0sis
d72fc9ee04 Update nlohmann/json submodule to v3.12.0 2025-05-31 11:02:11 -03:00
Chris Renshaw
84adafc3ac autopif2.sh: retain experimental spoofVendingSdk entry and value if it exists 2025-05-30 10:14:34 -03:00
Chris Renshaw
cb49481c45 Begin next development cycle 2025-05-30 09:55:23 -03:00
Chris Renshaw
b5a9b26b70 README: update for May 20th legacyDeviceRecognitionVerdict removal from PI API 2025-05-20 22:37:32 -03:00
osm0sis
39922653db README: fix KSU-Next link typo 2025-05-16 16:35:48 -03:00
osm0sis
58f2c2de57 Prepare v13 2025-05-16 16:29:06 -03:00
Chris Renshaw
e858134828 Update HiddenApiBypass 2025-05-16 13:49:22 -03:00
Chris Renshaw
fafaf418e4 Update NDK 2025-04-29 21:59:01 -03:00
osm0sis
da758bc33c Update Gradle 2025-04-29 21:56:56 -03:00
Chris Renshaw
d66260c3f6 Revert AGP to 8.8.x due to reported instability 2025-03-27 06:55:50 -03:00
Chris Renshaw
1a01e35862 Update AGP 2025-03-26 21:17:41 -03:00
Chris Renshaw
028e94e71b Organize common functions better (again) 2025-03-09 23:52:16 -03:00
Chris Renshaw
9e04c5cc5b Update AGP 2025-03-05 18:51:35 -04:00
Chris Renshaw
46e5e0a6d2 Force Platform builds via Action button 2025-03-03 07:02:37 -04:00
Chris Renshaw
d2db871892 Update AGP 2025-02-26 22:56:35 -04:00
osm0sis
7e7812bede Update Gradle 2025-02-25 16:14:33 -04:00
Chris Renshaw
c2af0fcad5 autopif2.sh: use wget2 over wget since arm busybox doesn't have LFS 2025-02-25 16:10:41 -04:00
osm0sis
1493650b65 autopif2.sh: promote --preview and --depth to documented features
-p or --preview forces not to ignore Android Platform Preview builds (Developer Previews and Betas)
-d # or --depth # chooses the depth to crawl down the QPR Betas list when there are multiple active Betas, e.g. when QPR2 was 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)
2025-02-21 23:19:07 -04:00
Chris Renshaw
3f62cb6a3a Update README.md 2025-02-15 06:53:11 -04:00
Chris Renshaw
5daf1b933e Update AGP 2025-02-14 18:03:29 -04:00
Chris Renshaw
e8375a02d1 Update NDK 2025-02-12 23:01:58 -04:00
Chris Renshaw
fa937983e8 Improve overlay AndroidManifest.xml parsing, support YAAP 2025-02-11 21:27:17 -04:00
Chris Renshaw
83b9d96ce4 autopif2.sh: always default to all= since TS system= date parsing seems different/bugged across some devices 2025-02-09 23:31:59 -04:00
Chris Renshaw
4bcf51ccfd autopif2.sh: use all instead of system if boot or vendor 11 months or more old 2025-02-08 20:01:37 -04:00
Chris Renshaw
e653659895 autopif2.sh: automatically update TrickyStore security_patch.txt system date
- opt in by creating /data/adb/tricky_store/security_patch.txt
- OS Patch Level (system= entry in TS 1.2.1+) must match *.security_patch spoofed to gms in order to pass Legacy PI Strong so automatically update with Beta print
- if boot= or vendor= entries are also needed in security_patch.txt to pass New PI Strong (due to an old/custom ROM) these must be manually added, or, all= may be used instead of system= and autopif2 will keep it up to date

Note: TS's OS Patch Level (system=), Boot Patch Level (boot=), and Vendor Patch Level (vendor=) must all be 11 months or less old in order to pass New PI Strong.
2025-02-08 10:50:57 -04:00
Nicholas Bissell
11e2629a26 Remove special case for logFields, simplify logs
- Run logFields only when spoofProvider, spoofBuild, or spoofSignature is on
- Simplify log outputs; PS -> Play Store, DG -> DroidGuard
2025-02-08 10:34:11 -04:00
Chris Renshaw
8805c3736d Add com.android.vending to DenyList changes 2025-02-08 10:34:11 -04:00
Nicholas Bissell
a52cc16b43 No class loading if Java features disabled
- No longer loads custom classes if not needed for respective packages
- Renames isGmsUnstable to isDroidGuardOrVending
- Removes spoofVendingSdk from migrate/autopif scripts (don't document yet)
- Adds missing setAccessible() call for early return in EntryPointVending.init()
- Adds missing set of spoofSignature -> 0 for vending
2025-02-08 10:34:11 -04:00
Nicholas Bissell
4740d2048d Add spoofVendingSdk to force legacy verdicts from new PI
Squashed: Add spoofVendingSdk for forcing new PI legacy verdicts
Squashed: Move vending SDK spoof to EntryPointVending, replace killgms.sh with killpi.sh
2025-02-08 10:34:11 -04:00
Chris Renshaw
e2b8a3c4b0 Group resetprop common functions together 2025-02-07 00:22:31 -04:00
Chris Renshaw
4dbe12ae58 Update HiddenApiBypass 2025-01-27 00:09:49 -04:00
osm0sis
996981a8e7 Update Gradle 2025-01-26 17:11:15 -04:00
Chris Renshaw
d278b77ced autopif2.sh: handle platform preview Betas like Developer Previews 2025-01-23 23:43:24 -04:00
Chris Renshaw
a3f68d392e README: be clear this is all legacyDeviceRecognitionVerdict 2025-01-18 13:14:23 -04:00
Chris Renshaw
9b3801a117 Add new verified boot error props deletion 2025-01-18 00:00:41 -04:00
Chris Renshaw
df5d5b7ce9 Remove action.sh in scripts-only-mode 2025-01-17 23:57:23 -04:00
Chris Renshaw
b644573e52 Update SDK Build Tools 2025-01-16 19:23:22 -04:00
Chris Renshaw
3e30d553c9 Update AGP 2025-01-09 22:13:05 -04:00
Chris Renshaw
8a64752923 KernelSU-Next does not auto-close Action dialog when successful 2025-01-08 10:25:39 -04:00
Chris Renshaw
264a218a79 Support more PIH and PPU variants and hybrids 2025-01-07 00:25:53 -04:00
Chris Renshaw
59781b1682 Properly support all known opt-out props for PixelPropUtils and PropImitationHooks 2025-01-05 23:20:20 -04:00
Chris Renshaw
a4c8aab031 Add other custom ROMs now using PIHooks 2025-01-05 22:57:13 -04:00
Chris Renshaw
abe69d201b Remove unnecessary/unenforced adb prop spoofs 2025-01-05 19:21:13 -04:00
Chris Renshaw
da0fad725a MMRL (3rd party module manager) doesn't auto-close Actions so exclude it 2024-12-29 23:59:50 -04:00
Chris Renshaw
d9794b2017 APatch upstream now also auto-closes successful Actions 2024-12-29 23:55:44 -04:00
osm0sis
d08ca33633 Update Gradle 2024-12-24 21:53:13 -04:00
Chris Renshaw
a7ba40a36c Use latest Apple Silicon for CI 2024-12-24 15:22:20 -04:00
osm0sis
140c32befd Update Gradle 2024-12-07 15:17:23 -04:00
Chris Renshaw
6fc3200df2 Update AGP 2024-12-07 15:11:18 -04:00
Chris Renshaw
c3ee7e5c0a autopif2.sh: ignore Developer Previews to only use latest Beta 2024-12-07 14:50:19 -04:00
Chris Renshaw
c635a9e3ba Only KSU auto-closes if successful now 2024-12-07 14:38:02 -04:00
Chris Renshaw
8ddab06840 Begin next development cycle 2024-12-07 14:36:30 -04:00
Chris Renshaw
16002e28c6 README: move skipdelprop down and touch up wording 2024-11-18 00:40:12 -04:00
31 changed files with 318 additions and 165 deletions

View File

@@ -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

2
.gitmodules vendored
View File

@@ -1,6 +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

View File

@@ -1,19 +1,23 @@
## Custom Fork v12
- Add support to autopif2 for generating from Pixel Beta point releases
- Improve autopif2 by catching more unsupported/broken environments
- Improve migrate parsing lines with comments
- Update default/example app replace list for helluvaOS
- Fix retaining disabled non-system ROM apps on KSU/APatch
- Add autopif2 --strong arg for initial setup with Tricky Store
- Add skipping resetprop --delete to avoid app detections if skipdelprop file exists
## Custom Fork v13
## Custom Fork v11
- Improve autopif busybox tests, default api_level 32, pass --advanced arg
- Improve scripts for special configs with Tricky Store
- Fix resetprop fallback Magisk check
- Add Action button support to run autopif in root managers
- Fix root check for Termux/KSU/APatch
- Improve PixelPropsUtils workaround on more setups
- Replace autopif with autopif2 to generate a random print from latest Pixel Beta
- 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)_

View File

@@ -6,27 +6,26 @@
[![GitHub Releases](https://img.shields.io/github/downloads/osm0sis/PlayIntegrityFork/latest/total?label=Downloads%20%28Latest%20Release%29&color=blue&style=flat)](https://github.com/osm0sis/PlayIntegrityFork/releases/latest)
[![GitHub All Releases](https://img.shields.io/github/downloads/osm0sis/PlayIntegrityFork/total?label=Total%20Downloads%20%28All%20Releases%29&color=brightgreen&style=flat)](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 Pixel Beta 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.
@@ -50,34 +49,40 @@ A migration may also be performed manually with `sh migrate.sh` and custom.pif.j
- [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 'autopif2.sh' and 'killgms.sh' script files
## About 'autopif2.sh' and 'killpi.sh' script files
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 then simply run the generation script from a root manager app that supports the module Action button, a root prompt with `sh autopif2.sh` in the module directory (/data/adb/modules/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 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 and SafetyNet in that time.
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 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
@@ -126,23 +131,21 @@ The advanced spoofing options add granular control over what exactly gets spoofe
<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` or `sh autopif2.sh -a` command or configured directly for Tricky Store to achieve STRONG integrity (see below) with the `sh autopif2.sh --strong` or `sh autopif2.sh -s` command. Other than for the "verboseLogs" entry (see above), they are all 0 (disabled) or 1 (enabled).
- 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, and the "spoofSignature" entry (default 0) controls spoofing the ROM Signature.
- 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.
- For spoofing locked bootloader and attempting to pass Play Integrity STRONG verdict I only recommend using the latest official [Tricky Store](https://github.com/5ec1cff/TrickyStore) build.
- 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.
- Note: Using Tricky Store to achieve STRONG integrity (with an unrevoked hardware keybox.xml) requires the Advanced Settings "spoofProvider" disabled and either "spoofProps" disabled or the "*.security_patch" entry commented out, but to achieve DEVICE integrity (with Tricky Store default AOSP software keybox.xml or a revoked keybox.xml) requires at least "spoofProps" enabled, and some fingerprints may also require "spoofProvider". More known working private fingerprints can achieve 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.
- 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 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, either from a root prompt with `touch /data/adb/modules/playintegrityfix/skipdelprop` or from a file explorer app, after the module is already installed, then reboot.
## About Scripts-only mode
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 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>
@@ -155,12 +158,20 @@ An advanced feature intended for older Android <10 ROMs, mostly stock ROMs or th
</details>
## About Play Integrity (SafetyNet is deprecated)
## 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
Original concept and general mechanism of PIF were from kdrag0n's [ProtonAOSP](https://protonaosp.org/) and [Universal SafetyNet Fix (USNF)](https://github.com/kdrag0n/safetynet-fix) projects.
Forked from chiteroman's [Play Integrity Fix (PIF)](https://github.com/chiteroman/PlayIntegrityFix) (no longer online).
Module scripts were adapted from those of Displax's Universal SafetyNet Fix (USNF) MOD module, please see the commit history of [Displax's USNF MOD Fork](https://github.com/Displax/safetynet-fix/tree/dev/magisk) for proper attribution.
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.

View File

@@ -4,9 +4,9 @@ plugins {
android {
namespace = "es.chiteroman.playintegrityfix"
compileSdk = 34
ndkVersion = "27.2.12479018"
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,16 +62,16 @@ android {
}
dependencies {
implementation("org.lsposed.libcxx:libcxx:27.0.12077973")
implementation("org.lsposed.hiddenapibypass:hiddenapibypass:4.3")
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 ->

View File

@@ -1,4 +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.CustomPackageInfoCreator
-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

View File

@@ -12,12 +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;
@@ -32,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();
@@ -90,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);
@@ -102,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);
@@ -119,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;
}
@@ -168,8 +164,12 @@ public:
if (dexVector.empty() || json.empty()) return;
readJson();
if (pkgName == VENDING_PACKAGE) spoofProps = spoofBuild = spoofProvider = spoofSignature = 0;
else spoofVendingSdk = 0;
if (spoofProps > 0) doHook();
inject();
if (spoofBuild + spoofProvider + spoofSignature + spoofVendingSdk > 0) inject();
dexVector.clear();
json.clear();
@@ -184,6 +184,7 @@ 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()));
@@ -200,6 +201,19 @@ private:
}
// 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>());
@@ -262,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", "(IIII)V");
env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofBuild, spoofProvider, spoofSignature);
LOGD("JNI %s: Calling EntryPoint.init", niceName);
auto entryInit = env->GetStaticMethodID(entryClass, "init", "(IIII)V");
env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofBuild, spoofProvider, spoofSignature);
}
}
};

View File

@@ -16,6 +16,7 @@ public class CustomPackageInfoCreator implements Parcelable.Creator<PackageInfo>
}
@Override
@SuppressWarnings("deprecation")
public PackageInfo createFromParcel(Parcel source) {
PackageInfo packageInfo = originalCreator.createFromParcel(source);
if (packageInfo.packageName.equals("android")) {

View File

@@ -265,6 +265,6 @@ public final class EntryPoint {
}
static void LOG(String msg) {
Log.d("PIF/Java", msg);
Log.d("PIF/Java:DG", msg);
}
}

View File

@@ -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);
}
}
}

View File

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

Binary file not shown.

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

9
gradlew vendored
View File

@@ -86,8 +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 -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || 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
@@ -115,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.
@@ -206,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.
@@ -214,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.

4
gradlew.bat vendored
View File

@@ -70,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

View File

@@ -4,12 +4,12 @@ MODPATH="${0%/*}"
set +o standalone
unset ASH_STANDALONE
sh $MODPATH/autopif2.sh || exit 1
sh $MODPATH/autopif2.sh -a -m -p || exit 1
echo -e "\nDone!"
# warn since Magisk/KernelSU's implementation automatically closes if successful
if [ "$APATCH" != "true" ]; then
# 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

View File

@@ -7,11 +7,18 @@ case "$HOME" in
*termux*) echo "autopif2: need su root environment"; exit 1;;
esac;
case "$1" in
-h|--help|help) echo "sh autopif2.sh [-a|-s]"; exit 0;;
-a|--advanced|advanced) ARGS="-a"; shift;;
-s|--strong|strong) ARGS="-a"; PATCH_COMMENT=1; spoofProvider=0; shift;;
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";
@@ -37,7 +44,9 @@ find_busybox() {
return 1;
}
if ! which wget >/dev/null || grep -q "wget-curl" $(which wget); then
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
@@ -71,9 +80,15 @@ 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 -m1 'developer.android.com/about/versions/' PIXEL_VERSIONS_HTML | cut -d\" -f2) 2>&1 || exit 1;
wget -q -O PIXEL_OTA_HTML --no-check-certificate https://developer.android.com$(grep -om1 'href=".*download-ota"' PIXEL_LATEST_HTML | cut -d\" -f2) 2>&1 || exit 1;
grep -m1 -o 'data-category.*Beta' PIXEL_OTA_HTML | cut -d\" -f2;
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')";
@@ -84,18 +99,16 @@ MODEL_LIST="$(grep -A1 'tr id=' PIXEL_OTA_HTML | grep 'td' | sed 's;.*<td>\(.*\)
PRODUCT_LIST="$(grep -o 'ota/.*_beta' PIXEL_OTA_HTML | cut -d\/ -f2)";
OTA_LIST="$(grep 'ota/.*_beta' PIXEL_OTA_HTML | cut -d\" -f2)";
case "$1" in
-m)
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;
;;
esac;
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() {
@@ -115,8 +128,8 @@ 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 | cut -d= -f2)";
SECURITY_PATCH="$(grep -am1 'security-patch-level=' PIXEL_ZIP_METADATA | cut -d= -f2)";
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;
@@ -144,13 +157,14 @@ if [ -f "$MIGRATE" ]; 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 verboseLogs";
ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingSdk verboseLogs";
for SETTING in $ADVSETTINGS; do
eval [ -z \"\$$SETTING\" ] \&\& $SETTING=$(grep_json "$SETTING" $OLDJSON);
eval TMPVAL=\$$SETTING;
@@ -174,8 +188,16 @@ if [ "$DIR" = /data/adb/modules/playintegrityfix/autopif2 ]; then
fi;
item "Installing new json ...";
cp -fv $NEWNAME ..;
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 || true;
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;

View File

@@ -1,6 +1,29 @@
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
@@ -24,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')"

View File

@@ -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,16 +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
# 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\]" || resetprop -n -p "$PROP" ""
resetprop | grep -q "\[$PROP\]" || persistprop "$PROP" ""
done
fi
# Work around supported custom ROM PixelPropsUtils conflict when spoofProvider is disabled
if [ -n "$(resetprop persist.sys.pixelprops.pi)" ]; then
resetprop -n -p persist.sys.pixelprops.pi false
resetprop -n -p persist.sys.pixelprops.gapps false
resetprop -n -p persist.sys.pixelprops.gms false
# 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

View File

@@ -3,11 +3,14 @@ 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/autopif2.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/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
@@ -17,7 +20,7 @@ if [ -d /data/adb/modules/playintegrityfix/system ]; then
fi
# Copy any supported custom files to updated module
for FILE in custom.app_replace.list custom.pif.json skipdelprop; 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

View File

@@ -11,7 +11,7 @@
/system/app/EliteDevelopmentModule
/system/app/XInjectModule
# helluvaOS / hentaiOS
# helluvaOS, hentaiOS
/system_ext/app/helluvaProductDevice*
/system_ext/app/helluvaProductSecretStub
/system_ext/app/hentaiLewdbSVTDummy
@@ -19,5 +19,5 @@
# Evolution X
/system_ext/app/PifPrebuilt
# PixelOS
# PixelOS, YAAP
/system_ext/overlay/CertifiedPropsOverlay.apk

View File

@@ -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"
}

View File

@@ -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" -a "$(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
View 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;

View File

@@ -114,12 +114,13 @@ if [ -z "$DEVICE_INITIAL_SDK_INT" -o "$DEVICE_INITIAL_SDK_INT" = "null" ]; then
DEVICE_INITIAL_SDK_INT=25;
fi;
ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature verboseLogs";
ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature spoofVendingSdk verboseLogs";
spoofBuild=1;
spoofProps=1;
spoofProvider=1;
spoofSignature=0;
spoofVendingSdk=0;
verboseLogs=0;
if [ -f "$OUT" ]; then

View File

@@ -1,7 +1,7 @@
id=playintegrityfix
name=Play Integrity Fork
version=v12
versionCode=120000
version=v13
versionCode=130001
author=osm0sis & chiteroman @ xda-developers
description=Fix ctsProfile (SafetyNet) and DEVICE (Play Integrity) verdicts
description=Fix <A13 DEVICE (Play Integrity) verdict
updateJson=https://raw.githubusercontent.com/osm0sis/PlayIntegrityFork/main/update.json

View File

@@ -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
@@ -37,6 +39,11 @@ 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

View File

@@ -11,8 +11,8 @@ 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 ! $SKIPDELPROP && [ -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
if [ "$(toybox cat /sys/fs/selinux/enforce)" = "0" ]; then

View File

@@ -1,6 +1,6 @@
{
"version": "v12",
"versionCode": 120000,
"zipUrl": "https://github.com/osm0sis/PlayIntegrityFork/releases/download/v12/PlayIntegrityFork-v12.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"
}