188 Commits
v5 ... v11

Author SHA1 Message Date
osm0sis
fe57017255 Prepare v11 2024-10-06 19:05:38 -03:00
osm0sis
0d05112f38 Replace autopif with autopif2 2024-10-06 18:51:30 -03:00
xqyz
d8ff58d9ca Add additional PixelPropsUtils props to workaround 2024-10-06 18:48:35 -03:00
Chris Renshaw
ea65aef097 Only show dialog auto-close message on Magisk where it's needed 2024-10-03 22:40:22 -03:00
Chris Renshaw
ebdbccdad2 Fix fallback whoami root check logic 2024-10-03 17:13:51 -03:00
Chris Renshaw
08e3fb4d29 Update AGP 2024-10-01 22:45:58 -03:00
Chris Renshaw
a671c3b0d3 README: latest Advanced Settings best practices 2024-09-28 23:44:38 -03:00
Chris Renshaw
c13a7b1299 20 second Action dialog timeout seems about right 2024-09-27 07:19:05 -03:00
Chris Renshaw
629de14990 Increase action.sh dialog timeout 2024-09-26 23:06:38 -03:00
osm0sis
bd4fdcf0c3 Update Gradle 2024-09-25 21:09:45 -03:00
Chris Renshaw
8c216e2d40 Add action.sh support to run autopif.sh from root managers 2024-09-25 12:43:39 -03:00
Chris Renshaw
27fc24337b Copy pasta fixes 2024-09-23 22:37:36 -03:00
Chris Renshaw
796f776534 autopif.sh: pass advanced argument to migrate script 2024-09-22 20:08:42 -03:00
Chris Renshaw
c972637347 migrate.sh: clean up user argument parsing 2024-09-22 19:28:23 -03:00
Chris Renshaw
b10828f199 Update NDK 2024-09-18 23:01:36 -03:00
osm0sis
726aecb2be Add nlohmann/json as submodule 2024-09-18 21:35:00 -03:00
Chris Renshaw
a790f2c0db Update AGP 2024-09-18 12:48:09 -03:00
Chris Renshaw
165d370bc8 migrate.sh: retain commented security_patch if advanced 2024-09-12 20:07:35 -03:00
Chris Renshaw
915b87e6be autopif.sh: retain commented security_patch if present
- commenting out the security_patch line is needed if enabling spoofProps (e.g. for api_level) when used with Tricky Store
2024-09-12 20:00:58 -03:00
Chris Renshaw
1255a49274 Fix Magisk version check
- the variable only gets set during installations, not in the boot script env
2024-09-12 06:51:24 -03:00
osm0sis
6cc82e3e7b Update Gradle 2024-09-11 22:22:44 -03:00
Chris Renshaw
87fde1f4ca Update AGP 2024-09-11 21:36:18 -03:00
Chris Renshaw
d535747c91 autopif.sh: improve error catching, busybox finding, etc.
- simplify error display
- catch missing inject_fields.xml or FINGERPRINT, from e.g. bad download/extraction failure
- more robust busybox finding function
- accept a local migrate.sh and give it precedence over the module copy
2024-09-11 21:31:25 -03:00
Chris Renshaw
98bb23460e autopif.sh: default to api_level 32 now that the betas are served 2024-09-11 21:21:42 -03:00
Chris Renshaw
027e5855a0 Begin next development cycle 2024-09-11 18:25:54 -03:00
Chris Renshaw
8d2d1ecbd2 README: document spoofSignature in Troubleshooting 2024-09-08 22:17:19 -03:00
Chris Renshaw
3775b5448e README: more accurate note about spoofProps
- spoofProps enabled is sometimes necessary to pass STRONG depending on the underlying device/ROM and the fingerprint attempting to be spoofed
2024-08-30 13:47:06 -03:00
Chris Renshaw
00023fb111 README: recommend only latest official Tricky Store 2024-08-20 09:51:02 -03:00
osm0sis
481491758c Hotfix v10(103000) 2024-08-18 21:23:44 -03:00
Chris Renshaw
b42773671a Add missing ro.adb.secure prop early with the others 2024-08-18 19:24:15 -03:00
Chris Renshaw
3d55dc59c1 Work around PixelPropsUtils framework spoof conflict where supported 2024-08-18 19:03:51 -03:00
osm0sis
33f4fa2ce0 Update Gradle 2024-08-18 17:08:35 -03:00
Chris Renshaw
2857e3d2f8 autopif.sh: prefer and use my busybox directly if somehow not on PATH 2024-08-16 14:52:37 -03:00
Chris Renshaw
4b8d6497d0 Hotfix v10(102000) 2024-08-16 00:37:23 -03:00
Chris Renshaw
f3a7f3d5e9 Move Xiaomi fix even later to avoid bootloops on yet more devices 2024-08-16 00:20:49 -03:00
Chris Renshaw
bee755d8f3 Update Changelog 2024-08-14 01:51:13 -03:00
osm0sis
dd4db53ca2 Hotfix v10(101000) 2024-08-14 01:00:22 -03:00
osm0sis
c30b3ab8a8 Fix bootloop on some Xiaomi devices 2024-08-14 00:50:48 -03:00
osm0sis
9d0a67d119 Prepare v10 2024-08-12 23:35:33 -03:00
Chris Renshaw
667efdd6a6 Update AGP 2024-08-09 22:17:44 -03:00
Chris Renshaw
6e7377b3de autopif.sh: tidy using existing if 2024-08-09 12:15:02 -03:00
pershoot
98ab70a0b6 autopif.sh: Do not execute killgms.sh if not in default directory 2024-08-08 22:05:51 -03:00
osm0sis
418e7306e3 Fix advanced spoofing always displaying enabled in logs 2024-08-07 14:16:09 -03:00
osm0sis
44420c89ab autopif.sh: retain previous Advanced Settings values, fixes 2024-08-07 12:01:16 -03:00
osm0sis
adcdd80d65 migrate.sh: tidy up now that functions are multi-line 2024-08-07 11:48:06 -03:00
Chris Renshaw
096c8941b9 migrate.sh: retain previous Advanced Settings values 2024-08-05 22:52:14 -03:00
osm0sis
a926c520f2 Restore resetprop_hexpatch for older Magisk which still needs it 2024-08-04 00:06:54 -03:00
osm0sis
9ef7a7f04e Revert "Use resetprop -w to wait for boot_completed"
This reverts commit 0bc9a45.

Cater to the lowest common denominator (older Magisk) at least until after next Magisk stable
2024-08-03 23:49:42 -03:00
osm0sis
e9c1ec1d5d Clearer log messages for advanced spoof options 2024-08-03 23:49:14 -03:00
osm0sis
a7c2f348ea Add granular advanced spoofing options 2024-08-02 15:30:52 -03:00
4h9fbZ
a5d9980ea7 Fix Signature Data 2024-08-01 23:42:08 -03:00
4h9fbZ
58db03d596 Implement system signature spoofing 2024-08-01 23:42:08 -03:00
Chris Renshaw
64e412c351 Correct module description 2024-07-18 23:07:01 -03:00
Chris Renshaw
914750104f Update libcxx prefab 2024-07-17 23:36:00 -03:00
Chris Renshaw
1db82e2ccb Update NDK 2024-07-17 23:01:56 -03:00
osm0sis
f20c2dff1e Update Gradle 2024-07-12 07:59:05 -03:00
Chris Renshaw
620581b4de Update AGP 2024-07-12 06:20:11 -03:00
Chris Renshaw
ebfd0c292a Make example.pif.json reference more clear 2024-07-11 00:04:08 -03:00
osm0sis
3e58be1e24 Correct type prop heading, add another missing prop
- if sys.oem_unlock_allowed is reset to 0 before sys.boot_completed is 1 it results in a boot hang and then reboot or poweroff
- even though sys.oem_unlock_allowed has been reset to 0 the act of opening Developer Options will set it back to 1 until next reboot
2024-07-05 16:35:04 -03:00
Chris Renshaw
662b9c59c7 Ensure all prop changes bypass property_service
- resetprop only bypasses for ro.* properties by default
2024-07-05 14:15:19 -03:00
Chris Renshaw
0bc9a4543a Use resetprop -w to wait for boot_completed 2024-07-05 12:10:42 -03:00
Chris Renshaw
e3e4bbb95f Match file code style correctly 2024-07-04 15:41:41 -03:00
Chris Renshaw
7c3d0bd8dd Fix all tags and type props, add missing prop 2024-07-04 14:55:45 -03:00
Chris Renshaw
b26b043a02 Remove resetprop_hexpatch since counter is fixed in Magisk Canary 2024-07-04 14:43:50 -03:00
Chris Renshaw
5aabd4b6b5 Don't remove killgms.sh in Scripts-only mode
- it's still useful for testing purposes
2024-07-04 14:36:29 -03:00
Wang Han
6d173fb3a1 Use unique project name
This also works around a shamiko bug which will be
fixed later.
2024-07-04 14:29:20 -03:00
Chris Renshaw
efa3e98a94 Update AGP 2024-07-04 14:25:21 -03:00
Chris Renshaw
8756c3963a Begin next development cycle 2024-07-04 14:22:45 -03:00
Chris Renshaw
6109918511 README: more tweaks 2024-06-16 14:05:52 -03:00
Chris Renshaw
0386e085b5 README: next day fixes 2024-06-14 13:26:06 -03:00
Chris Renshaw
b24d538e82 README: final tidy 2024-06-13 22:30:21 -03:00
osm0sis
dc1ac51008 Prepare v9 2024-06-13 22:17:57 -03:00
Chris Renshaw
e0d288ac10 README: mention Zygisk Assistant as Shamiko alternative 2024-06-10 23:34:02 -03:00
Chris Renshaw
36084324bc Update AGP 2024-06-10 23:29:12 -03:00
osm0sis
07effe41b7 README: AOSP testkey ban, RCS print ban, PPS and testing automation 2024-06-10 22:32:21 -03:00
osm0sis
7b058d9bef Update Gradle 2024-06-01 20:53:22 -03:00
Chris Renshaw
ae1322b907 Work around AOSPA PropImitationHooks conflict 2024-06-01 01:50:52 -03:00
Chris Renshaw
ee8e56b401 migrate.sh: check only trailing quote
- fixes grep_check_json for prop entries with leading wildcard
2024-05-31 10:00:02 -03:00
Chris Renshaw
96a1475ac7 Update AGP 2024-05-20 23:05:47 -03:00
Chris Renshaw
2dd7a17ac2 autopif.sh: don't use half-baked wget-curl wrapper some ROMs include 2024-05-19 04:01:56 -03:00
Chris Renshaw
c7b87b944f autopif.sh: catch Termux issues properly 2024-05-15 23:36:56 -03:00
Chris Renshaw
31adf6b3b9 autopif.sh: install/output improvements
- back up old json if running as built-in to module
- keep Advanced Settings if present in old json
2024-05-11 09:10:13 -03:00
Chris Renshaw
2027b7ba74 migrate.sh: keep Advanced Settings if present in old json 2024-05-11 09:02:58 -03:00
osm0sis
bbfdc87724 Add new files to scripts-only-mode removals 2024-05-06 13:14:56 -03:00
Chris Renshaw
4d116c6a42 Add DroidGuard process killing script 2024-05-06 09:59:41 -03:00
Chris Renshaw
afddeaf340 Add Xiaomi.eu custom.pif.json extraction script 2024-05-06 09:58:44 -03:00
Chris Renshaw
61b018ae21 Update AGP 2024-04-30 23:35:31 -03:00
osm0sis
c7c8b549df Update Gradle 2024-04-25 00:38:06 -03:00
Chris Renshaw
7f1bdf69c5 Update NDK 2024-04-24 22:34:18 -03:00
Chris Renshaw
95e6cbe53b Update AGP 2024-04-10 13:44:43 -03:00
Chris Renshaw
ee714d1e21 Fix description sed with forgotten in-place flag 2024-04-09 08:44:14 -03:00
Chris Renshaw
6aa58bbc5e Indicate scripts-only mode in module description 2024-04-09 08:24:33 -03:00
Chris Renshaw
63bcb3c3f6 README: add examples of known incompatible modules 2024-04-08 12:55:44 -03:00
Chris Renshaw
25262ce07e migrate.sh: fix parsing/formatting regressions
- DEVICE_INITIAL_SDK_INT value would erroneously be used for DEVICE if DEVICE was missing
- a malformed json trailing , on the last input file entry would break the output format
2024-04-07 02:40:51 -03:00
Chris Renshaw
b4821fb03e migrate.sh: fix parsing for \" and , in json values 2024-04-07 01:45:25 -03:00
Chris Renshaw
8e4e7d1cef migrate.sh: add option to override values using derived fingerprint values 2024-04-06 01:37:55 -03:00
Chris Renshaw
58e04392bf migrate.sh: fix deriving from FINGERPRINT values with unexpected spaces 2024-04-05 16:14:14 -03:00
osm0sis
2c13b924ed Tweak/update comments 2024-03-30 15:19:30 -03:00
Chris Renshaw
8215587745 Make scripts-only mode opt-in only
- older custom ROMs may be able to pass only with the Zygisk components active, since the custom ROM doesn't have the correct stock ROM values
2024-03-28 11:33:08 -03:00
Chris Renshaw
8414785806 migrate.sh: allow specifying an output file 2024-03-27 02:27:15 -03:00
Chris Renshaw
75cf629015 Fix mistakenly forced scripts-only mode on clean installs
- use manual opt-in trigger of a scripts-only-mode file existing in the PIF module subdirectory
- clarify installer message since Magisk Zygisk actually functions on Android < 8 now, but the Zygisk attestation fallback and device spoofing aren't necessary to pass on these (and also some later) devices
2024-03-27 00:59:20 -03:00
osm0sis
36ce25f154 Bring back USNF's scripts-only mode for older Android, but better
- do scripts-only mode automatically on Android < 8.0 since it doesn't support Zygisk and generally doesn't need a PIF module to pass at all
- clean up all unused files in scripts-only mode, and modify script behaviors for it, including allowing GMS on DenyList, and even add it if missing since it's necessary on some scripts-only configurations
- allow manually entering scripts-only mode by deleting the zygisk directory of the currently installed module and reinstalling
- intentionally don't alter the Enforce DenyList state, since we don't know what other modules are installed that might depend on it one way or the other, so leave that up to the user
2024-03-25 15:00:49 -03:00
Chris Renshaw
af7063d055 migrate.sh: support compacted json and some CR/LF mangling 2024-03-23 00:26:20 -03:00
Chris Renshaw
ecbf6d1db8 Begin next development cycle 2024-03-22 19:11:02 -03:00
Chris Renshaw
287ce1ee9b Update AGP 2024-03-19 01:18:39 -03:00
Chris Renshaw
77653d25cb README: update for latest APatch supporting official Zygisk Next 2024-03-18 09:51:19 -03:00
Chris Renshaw
009815692c Update NDK 2024-03-12 01:56:54 -03:00
Chris Renshaw
c0618cf9d8 CI only on main again 2024-03-09 22:30:14 -04:00
osm0sis
7d216c30f1 Prepare v8 2024-03-09 22:19:52 -04:00
Chris Renshaw
d620dcdecb Fix CI with AGP 8.3.0 2024-03-09 21:59:52 -04:00
Chris Renshaw
d0acafd34a Update AGP 2024-03-09 02:01:56 -04:00
Chris Renshaw
f99696e894 README: RIP PIFS, point out Resources using words 2024-03-08 17:15:18 -04:00
Chris Renshaw
12b55630fb README: emphasize the flexibility and futureproofing in the json 2024-03-07 13:57:21 -04:00
osm0sis
5703c9bca1 Work around inconsitent wildcard matching behavior in ash [[
- *"/overlay"* is correct for bash [[, and works during an install in ash, but during a boot script in ash results in attempted filename completion and gives an operand error
- "*/overlay/*" works in ash [[, but shouldn't, since it doesn't work in bash [[
- the inconsitent ash behavior in install vs. boot script is likely due to the operating directory of the script in each scenario
2024-03-04 16:16:12 -04:00
osm0sis
ffd510aee5 Fix retaining disabled ROM apps through module updates in some scenarios
- KernelSU or APatch have completely hidden directories/files so would not get recreated
- for .apk files with a config.xml the config.xml would not get recreated due to the 0-size/hidden .apk
2024-03-04 13:48:16 -04:00
osm0sis
b30b43f2ae Fix app replacement messages during install/update 2024-03-03 23:47:36 -04:00
osm0sis
affe99b5ae Handle overlay APKs with config.xml entries correctly 2024-03-03 22:16:21 -04:00
Chris Renshaw
e2bb20b077 README: be painfully clear about where a Magisk module keeps its files 2024-03-02 22:57:11 -04:00
osm0sis
79052ff455 Separate common installation and boot-time scripts and source it 2024-03-02 22:49:46 -04:00
osm0sis
4ab07b71f8 migrate.sh: fix deprecated vndk property entry 2024-03-01 20:13:24 -04:00
osm0sis
34966f58a0 Don't hide CertifiedPropsOverlay config.xml by default to not break GSIs
- GSIs and possibly other ROMs use /system_ext/overlay/config/config.xml with overlay package names and options
- replacing/hiding either CertifiedPropsOverlay.apk or config.xml alone causes bootloops
2024-02-27 15:29:32 -04:00
Chris Renshaw
0299c76061 README: note GMS must not be on DenyList 2024-02-27 13:32:32 -04:00
osm0sis
163678c49a Add PifPrebuilt (com.goolag.pif) to default/example app replace list 2024-02-23 13:55:12 -04:00
Chris Renshaw
f61fd571e0 README: clarify caveat for format migration from cross-forks 2024-02-22 14:20:10 -04:00
Chris Renshaw
26979bd73e migrate.sh: ensure only one value match 2024-02-16 09:58:06 -04:00
Chris Renshaw
c19224b138 Correct comment 2024-02-16 09:50:43 -04:00
Chris Renshaw
ccb696d334 README: add other package names 2024-02-16 09:33:01 -04:00
Chris Renshaw
8014d71934 Consistent numbers 2024-02-14 10:01:49 -04:00
Chris Renshaw
52edfcfb7c README: use PixelFlasher thread UI Workflow post 2024-02-11 15:41:27 -04:00
Chris Renshaw
938ae86c8e README: Touch-ups 2024-02-08 23:14:21 -04:00
osm0sis
bdd846add6 Tidy scripts, clarify KernelSU/APatch hide files/directories 2024-02-08 00:08:57 -04:00
osm0sis
1a7c5103d1 verbose_logs is now verboseLogs
- differentiate all the ways from a BUILD_FIELD_ENTRY and a system.property_entry
- probably better this way in the long run
2024-02-07 22:53:13 -04:00
osm0sis
686af702dc README: improve Resources formatting 2024-02-07 22:19:36 -04:00
Chris Renshaw
18f8277f16 No CI for documentation changes 2024-02-07 21:28:23 -04:00
osm0sis
484ab2aa63 Documentation: fixes, and moar Resources! 2024-02-07 11:29:51 -04:00
osm0sis
87eb713cbd migrate.sh: be more verbose migrating from v4, catch another edge case 2024-02-04 21:57:42 -04:00
Chris Renshaw
fa418290b3 migrate.sh: optionally add advanced settings to json 2024-02-02 18:49:35 -04:00
osm0sis
608e60adbb Allow files on the app replace list 2024-02-02 16:46:59 -04:00
osm0sis
fae28159b9 Update AGP 2024-02-02 15:21:17 -04:00
osm0sis
71b40dcb09 Update gradle 2024-02-02 14:59:53 -04:00
Chris Renshaw
1f0c921773 Test Apple Silicon CI 2024-02-01 22:46:52 -04:00
Chris Renshaw
3b00a7249b README: add Banned Kernel troubleshooting 2024-02-01 11:56:07 -04:00
osm0sis
48014b9450 Revert "Hook uname to spoof kernel release version string"
This reverts commit 7997954f74.

Hook wasn't functional for intercepting the uname call despite many attempted methods, both on .gms and .gms.unstable

See: https://github.com/chiteroman/PlayIntegrityFix/issues/236
2024-02-01 09:37:52 -04:00
Chris Renshaw
3451dd72ec README: add FAQ 2024-01-31 12:14:55 -04:00
osm0sis
9cc8451c90 VERBOSE_LOGS is now verbose_logs
- differentiate advanced settings better from a Build field (all caps) or a System property (has .)
- match new advanced setting uname_release
2024-01-29 13:27:18 -04:00
osm0sis
7997954f74 Hook uname to spoof kernel release version string
Co-authored-by: chiteroman <98092901+chiteroman@users.noreply.github.com>
2024-01-29 13:15:11 -04:00
osm0sis
fc8e5108de Update default/example app replace list 2024-01-28 15:40:52 -04:00
Chris Renshaw
3ec6a4b039 Begin next development cycle 2024-01-25 15:03:42 -04:00
Chris Renshaw
5b9d0dfdd3 Changelog corrections 2024-01-25 14:36:30 -04:00
Chris Renshaw
278cbf1732 Update GitHub Actions again since https://github.com/actions/upload-artifact/issues/473 is fixed 2024-01-24 22:57:03 -04:00
osm0sis
594ac7c8ac Prepare v7 2024-01-24 14:22:23 -04:00
osm0sis
b8e68d059e Correct XInjectModule placement in replace list 2024-01-24 10:41:34 -04:00
osm0sis
198c2e5486 Fix ROM injection app replacement when using APatch 2024-01-23 12:31:36 -04:00
Chris Renshaw
919526bcd7 Add prop hack return codes for testing, tidy other functions 2024-01-23 00:56:47 -04:00
osm0sis
0b34f95282 Use app data dir to detect GMS package
Prevent injecting into unrelated apps because apps can use whatever process name. This effectively restores df20bdb but with null checks added to prevent crash.

Reference: topjohnwu/Magisk@07c22cc

Co-authored-by: chiteroman <98092901+chiteroman@users.noreply.github.com>
Co-authored-by: Wang Han <416810799@qq.com>
2024-01-22 19:34:23 -04:00
Chris Renshaw
63e4c571bf Hide adbd service state since DroidGuard looks at it
- not currently enforced, but play it safe and spoof it by default like with USB state
2024-01-21 00:50:27 -04:00
osm0sis
bdcfd283f1 Fix ROM injection app replacement when using KernelSU 2024-01-20 23:21:53 -04:00
osm0sis
dbd60afe68 migrate.sh: allow any filename to be specified as input file
- if none is provided it still falls back to looking for custom.pif.json in the current directory
2024-01-20 15:00:07 -04:00
osm0sis
e2cb4e1523 More logging
Co-authored-by: chiteroman <98092901+chiteroman@users.noreply.github.com>
2024-01-19 14:44:35 -04:00
osm0sis
5901844ce3 Add XiaomiEUInject-Stub to the default/example replace list 2024-01-19 09:46:54 -04:00
osm0sis
efb8ee930a Don't attempt to hack props if we don't have a context file 2024-01-18 16:56:45 -04:00
osm0sis
d36b35b7e9 Fix ROM injection app replacement on partitions other than /system 2024-01-18 14:27:55 -04:00
Chris Renshaw
4c08eb1e42 Begin next development cycle 2024-01-18 14:18:52 -04:00
osm0sis
2fa007afa3 Prepare v6 2024-01-17 16:13:20 -04:00
osm0sis
05c2474963 Fix Realme fingerprint scanners 2024-01-17 16:06:39 -04:00
Chris Renshaw
e0931c829d Reduce somewhat unnecessary extra Build field spoofing calls
Co-authored-by: chiteroman <98092901+chiteroman@users.noreply.github.com>
2024-01-16 20:28:28 -04:00
osm0sis
b57f46eed0 Revert "Fix seemingly unnecessary extra Build field spoofing calls"
This reverts commit 05927c60e1.

Seemingly necessary on some ROMs that do their own framework-level spoofing. May our logcats forgive us.
2024-01-16 14:44:29 -04:00
osm0sis
73d89d7a50 Clean up remaining .idea missing trailing newlines 2024-01-15 23:19:32 -04:00
osm0sis
475185c3ee Switch hooking method to Dobby
- Android 14 QPR2 (currently in Beta and due for Stable in March) breaks ShadowHook libc hooking needed for property spoofing
- there are currently no signs of life over at ShadowHook to resolve this despite my reporting it to them over a month ago

Co-authored-by: Nicholas Bissell <thefreeman193@hotmail.com>
Co-authored-by: chiteroman <98092901+chiteroman@users.noreply.github.com>
2024-01-15 23:16:21 -04:00
osm0sis
802c0a7617 Improve logging messages further 2024-01-15 17:18:26 -04:00
osm0sis
9a24cd6f23 Tidy JNI JSON sending/receiving code and logging 2024-01-15 17:05:26 -04:00
osm0sis
22e3a14a6f Refactor VERBOSE_LOGS parsing to directly pass level from Native to Java 2024-01-15 16:36:52 -04:00
osm0sis
24db525cf3 Add advanced Build classes field logging
Co-authored-by: Nicholas Bissell <thefreeman193@hotmail.com>
2024-01-13 14:09:29 -04:00
osm0sis
21a309dd12 More consistent replace file naming, retain custom through an update 2024-01-09 10:52:17 -04:00
osm0sis
05927c60e1 Fix seemingly unnecessary extra Build field spoofing calls
Co-authored-by: arda99 <arda99@noreply.xdaforums.com>
2024-01-08 21:36:34 -04:00
Chris Renshaw
008c0d0ada Add CI run number to zip filename 2024-01-08 20:57:35 -04:00
osm0sis
93ac718229 Support prop hacking on older Android 2024-01-08 16:44:26 -04:00
osm0sis
5aea2e877f README tweaks 2024-01-08 16:09:50 -04:00
osm0sis
d106e2a964 Allow customizable path replacement for conflicting custom ROM apps 2024-01-08 16:06:24 -04:00
osm0sis
a9630901b3 Reorganize slightly and add missing props 2024-01-08 14:15:58 -04:00
osm0sis
d7090f3f73 Use custom function to hack props without increasing prop change counter
- some apps were detecting tampered props from the increased prop_info serial counter using resetprop
- patching doesn't rely on magiskboot hexpatch so should work on KernelSU and APatch as well
- hopefully temporary until all root solutions adopt a patched system_properties repo to fix counters via resetprop
2024-01-08 13:55:55 -04:00
Chris Renshaw
3088f4b179 migrate.sh: remove all use of echo \n to be even more portable 2023-12-28 23:52:50 -04:00
Chris Renshaw
9673971b70 README: document VERBOSE_LOGS advanced logging levels 2023-12-28 20:10:19 -04:00
osm0sis
f6a9f855ef README: document manual migrate.sh execution 2023-12-28 13:28:31 -04:00
Chris Renshaw
edcb94e179 migrate.sh: add help, add force option, fix on shells without echo -e 2023-12-28 13:21:40 -04:00
osm0sis
a3cbed9a4e Clean up last remaining CR+LF 2023-12-27 23:32:40 -04:00
Chris Renshaw
e9b7289950 Begin next development cycle 2023-12-27 22:44:06 -04:00
Chris Renshaw
63fab9cca7 Fix Previous Changelogs link 2023-12-27 17:36:51 -04:00
45 changed files with 1275 additions and 25270 deletions

View File

@@ -2,37 +2,39 @@ name: Android CI
on:
push:
branches: [ "main" ]
branches: main
paths-ignore: '**.md'
pull_request:
branches: [ "main" ]
branches: main
paths-ignore: '**.md'
jobs:
build:
runs-on: ubuntu-latest
runs-on: macos-14
steps:
- name: Check out
uses: actions/checkout@v4
with:
submodules: "recursive"
submodules: 'recursive'
fetch-depth: 0
- name: Set up JDK 17
- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
java-version: 17
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew assembleRelease
- name: Upload CI module zip as artifact zip
uses: actions/upload-artifact@v4
with:
name: PlayIntegrityFork-CI
path: module/*
name: PlayIntegrityFork-CI_#${{ github.run_number }}
path: 'module/*'
compression-level: 9

12
.gitmodules vendored
View File

@@ -1,6 +1,6 @@
[submodule "libcxx"]
path = app/src/main/cpp/libcxx
url = https://github.com/topjohnwu/libcxx.git
[submodule "shadowhook"]
path = app/src/main/cpp/shadowhook
url = https://github.com/bytedance/android-inline-hook
[submodule "Dobby"]
path = app/src/main/cpp/Dobby
url = https://github.com/jmpews/Dobby
[submodule "json"]
path = app/src/main/cpp/json
url = https://github.com/nlohmann/json

2
.idea/compiler.xml generated
View File

@@ -3,4 +3,4 @@
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" />
</component>
</project>
</project>

View File

@@ -7,4 +7,4 @@
</entry>
</value>
</component>
</project>
</project>

2
.idea/gradle.xml generated
View File

@@ -16,4 +16,4 @@
</GradleProjectSettings>
</option>
</component>
</project>
</project>

View File

@@ -7,4 +7,4 @@
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>
</component>

View File

@@ -3,4 +3,4 @@
<option name="PROJECT_PROFILE" value="Default" />
<option name="USE_PROJECT_PROFILE" value="false" />
</settings>
</component>
</component>

2
.idea/migrations.xml generated
View File

@@ -7,4 +7,4 @@
</set>
</option>
</component>
</project>
</project>

2
.idea/misc.xml generated
View File

@@ -6,4 +6,4 @@
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
</project>

4
.idea/vcs.xml generated
View File

@@ -2,6 +2,6 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/src/main/cpp/libcxx" vcs="Git" />
<mapping directory="$PROJECT_DIR$/app/src/main/cpp/Dobby" vcs="Git" />
</component>
</project>
</project>

View File

@@ -1,17 +1,22 @@
## Custom Fork v5
- Allow spoofing literally any system property, supporting * lead wildcard to match multiple
- Remove all backwards compat cruft and deprecated entries
- Add log levels with VERBOSE_LOGS last json entry of 0, 1, 2, 3 or 100
- Spoof sys.usb.state to DroidGuard by default to hide USB Debugging
- Update example json for properties
- Add migration script to automatically upgrade old custom.pif.json during install/update (may also be run manually)
## 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
## Custom Fork v4
- Very verbose logging (for now)
- Allow spoofing literally any field from android.os.Build or android.os.Build.VERSION
- Add BUILD_ID and VNDK_VERSION support to keep cross-fork API compatibility
- Add exceptions for FIRST_API_VERSION (actually DEVICE_INITIAL_SDK_INT) and BUILD_ID (actually ID) for backwards API compatibility
- Add empty example.pif.json with reference link
- Fix GMS crashes if a null/bad value was read from json
## Custom Fork v10
- Work around Shamiko 1.1 bug causing DenyList app hangs
- Keep killgms in Scripts-only mode for testing
- Add missing global props, fix all tags/type props
- Use newer resetprop, fall back to custom func
- Add ROM sig spoof to Advanced, default off
- Add granular spoof to Advanced for Tricky Store
- Improve scripts to keep Advanced values
- Improve autopif to catch Magisk Canary busybox regression
- Fix bootloop on some Xiaomi devices
- Work around PixelPropsUtils conflict
###[Previous changelogs](https://github.com/osm0sis/PlayIntegrityFork/releases)
_[Previous changelogs](https://github.com/osm0sis/PlayIntegrityFork/releases)_

136
README.md
View File

@@ -1,5 +1,5 @@
# Play Integrity Fork
*PIF forked to bring back the custom.pif.json restore feature and develop more methodically*
*PIF forked to be more futureproof and develop more methodically*
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/osm0sis/PlayIntegrityFork?label=Release&color=blue&style=flat)](https://github.com/osm0sis/PlayIntegrityFork/releases/latest)
[![GitHub Release Date](https://img.shields.io/github/release-date/osm0sis/PlayIntegrityFork?label=Release%20Date&color=brightgreen&style=flat)](https://github.com/osm0sis/PlayIntegrityFork/releases)
@@ -8,78 +8,152 @@
A Zygisk module which fixes "ctsProfileMatch" (SafetyNet) and "MEETS_DEVICE_INTEGRITY" (Play Integrity).
To use this module you must have one of the following:
To use this module you must have one of the following (latest versions):
- Magisk with Zygisk enabled.
- KernelSU with [ZygiskNext](https://github.com/Dr-TSNG/ZygiskNext) module installed.
- [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)
- [KernelSU](https://github.com/tiann/KernelSU) 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 a few 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.
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.
## 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 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.
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).
You can't use values from recent devices due them triggering full hardware backed attestation.
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.
Older formatted custom.pif.json files from cross-forks and previous releases will be automatically migrated to the latest format.
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.
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.
A migration may also be performed manually with `sh migrate.sh` and custom.pif.json in the same directory, or from a file explorer app that supports script execution.
<details>
<summary>Resources</summary>
<summary><strong>Resources</strong></summary>
- [How-To Guide - Info to help find build.prop files, then create and use a custom.pif.json](https://xdaforums.com/t/module-play-integrity-fix-safetynet-fix.4607985/post-89189572)
- [gen_pif_custom.sh - Script to generate a custom.pif.json from device dump build.prop files](https://xdaforums.com/t/tools-zips-scripts-osm0sis-odds-and-ends-multiple-devices-platforms.2239421/post-89173470)
- [UI Workflow Guide - Build, edit and test custom.pif.json using PixelFlasher on PC](https://xdaforums.com/t/module-play-integrity-fix-safetynet-fix.4607985/post-89189970)
- FAQ:
- [PIF FAQ](https://xdaforums.com/t/pif-faq.4653307/) - Frequently Asked Questions (READ FIRST!)
- Guides:
- [How-To Guide](https://xdaforums.com/t/module-play-integrity-fix-safetynet-fix.4607985/post-89189572) - Info to help find build.prop files, then manually create and use a custom.pif.json
- [Complete Noobs' Guide](https://xdaforums.com/t/how-to-search-find-your-own-fingerprints-noob-friendly-a-comprehensive-guide-w-tips-discussion-for-complete-noobs-from-one.4645816/) - A more in-depth basic explainer of the How-To Guide above
- [UI Workflow Guide](https://xdaforums.com/t/pixelflasher-a-gui-tool-for-flashing-updating-rooting-managing-pixel-phones.4415453/post-87412305) - Build/find, edit, and test custom.pif.json using PixelFlasher on PC
- [Tasker PIF Testing Helper](https://xdaforums.com/t/pif-testing-helper-tasker-profile-for-testing-fingerprints.4644827/) - Test custom.pif.json using Tasker on device
- 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
- [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
</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
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.
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 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.
## 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.
### 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:
- Disable all modules except this one
- Try a different (ideally known working) custom.pif.json
Some modules which modify system can trigger DroidGuard detection, never hook GMS processes.
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)
### Failing DEVICE verdict (on KernelSU/APatch)
- Disable ZygiskNext
- Disable Zygisk Next
- Reboot
- Enable ZygiskNext
- Enable Zygisk Next
- Reboot again
### Play Protect/Store Certification and Google Wallet Tap To Pay Setup Security Requirements
### Failing DEVICE verdict (on custom kernel/ROM)
Follow these steps:
- Check the kernel release string with command `adb shell uname -r` or `uname -r`
- If it's on the [Known Banned Kernel List](https://xdaforums.com/t/module-play-integrity-fix-safetynet-fix.4607985/post-89308909) then inform your kernel developer/ROM maintainer to remove their branding for their next build
- You may also try a different custom kernel, or go back to the default kernel for your ROM, if available/possible
- Flash the module in Magisk/KernelSU
- Clear Google Wallet cache (if you have it)
- Clear Google Play Store cache and data
- Clear Google Play Services (com.google.android.gms) cache and data (Optionally skip clearing data and wait some time, ~24h, for it to resolve on its own)
### 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 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
- Reflash the module in your root manager app
- Clear Google Wallet (com.google.android.apps.walletnfcrel) and/or Google Pay (com.google.android.apps.nbu.paisa.user) cache, if you have them installed
- Clear Google Play Store (com.android.vending) and, if present, Google Play Protect Service (com.google.android.odad) cache and data
- Clear Google Play Services (com.google.android.gms) cache and data, or, optionally skip clearing data and wait some time (~24h) for it to resolve on its own
- Reboot
Note clearing Google Play Services app ***data*** will then require you to reset any WearOS devices paired to your device.
Note: Clearing Google Play Services app ***data*** will then require you to reset any WearOS devices paired to your device.
### Read module logs
You can read module logs using this command directly after boot:
You can read module logs using one of these commands directly after boot:
```
adb shell "logcat | grep 'PIF'"
```
`adb shell "logcat | grep 'PIF/'"` or `su -c "logcat | grep 'PIF/'"`
Add a "verboseLogs" entry with a value of "0", "1", "2", "3" or "100" to your custom.pif.json to enable higher logging levels; "100" will dump all Build fields, and all the system properties that DroidGuard is checking. Adding the entry can also be done using the migration script with the `sh migrate.sh --force --advanced` or `sh migrate.sh -f -a` command.
## Can this module pass MEETS_STRONG_INTEGRITY?
No.
No...
## About Play Integrity, SafetyNet is deprecated
## About spoofing Advanced Settings
You can read more
here: [Play Integrity API Info - XDA Forums](https://xdaforums.com/t/info-play-integrity-api-replacement-for-safetynet.4479337/)
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. 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.
- 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.
- 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.
</details>
## 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.
<details>
<summary><strong>Details</strong></summary>
- Manually opt-in by creating a file named scripts-only-mode in the module directory, either from a root prompt with `mkdir -p /data/adb/modules/playintegrityfix; touch /data/adb/modules/playintegrityfix/scripts-only-mode` or from a file explorer app, and then re/flashing the module. Scripts-only mode will remain enabled until this file is removed and the module is reflashed again.
- During install all unused default mode files (including custom.pif.json) are removed from the module directory, effectively disabling the Zygisk components of PIF: attestation fallback and device spoofing. You'll see "Scripts-only mode" indicated in the module description in your root manager app.
- For best results, you should still most likely enable Magisk's Enforce DenyList option if NOT also using [Shamiko](https://github.com/LSPosed/LSPosed.github.io/releases) or [Zygisk Assistant](https://github.com/snake-4/Zygisk-Assistant). The module will automatically add the Google Play Services DroidGuard process (com.google.android.gms.unstable) to the Magisk DenyList, if missing, since for Scripts-only mode it's necessary on some configurations (generally Android 9).
</details>
## About Play Integrity (SafetyNet is deprecated)
[Play Integrity API](https://xdaforums.com/t/info-play-integrity-api-replacement-for-safetynet.4479337/) - FAQ/information about PI (Play Integrity) replacing SN (SafetyNet)
## Credits

View File

@@ -5,9 +5,20 @@ plugins {
android {
namespace = "es.chiteroman.playintegrityfix"
compileSdk = 34
ndkVersion = "26.1.10909125"
ndkVersion = "27.1.12297006"
buildToolsVersion = "34.0.0"
buildFeatures {
prefab = true
}
packaging {
jniLibs {
excludes += "**/liblog.so"
excludes += "**/libdobby.so"
}
}
defaultConfig {
applicationId = "es.chiteroman.playintegrityfix"
minSdk = 26
@@ -16,10 +27,15 @@ android {
versionName = "1.0"
externalNativeBuild {
ndk {
jobs = Runtime.getRuntime().availableProcessors()
abiFilters += "armeabi-v7a"
abiFilters += "arm64-v8a"
cmake {
arguments += "-DANDROID_STL=none"
arguments += "-DCMAKE_BUILD_TYPE=Release"
cppFlags += "-std=c++20"
cppFlags += "-fno-exceptions"
cppFlags += "-fno-rtti"
cppFlags += "-fvisibility=hidden"
cppFlags += "-fvisibility-inlines-hidden"
}
}
}
@@ -38,17 +54,23 @@ android {
}
externalNativeBuild {
ndkBuild {
path = file("src/main/cpp/Android.mk")
cmake {
path = file("src/main/cpp/CMakeLists.txt")
version = "3.22.1"
}
}
}
dependencies {
implementation("org.lsposed.libcxx:libcxx:27.0.12077973")
implementation("org.lsposed.hiddenapibypass:hiddenapibypass:4.3")
}
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/out/lib")
val soDir = project.layout.buildDirectory.get().asFile.resolve("intermediates/stripped_native_libs/release/stripReleaseDebugSymbols/out/lib")
dexFile.copyTo(moduleFolder.resolve("classes.dex"), overwrite = true)

View File

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

View File

@@ -1,33 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := zygisk
LOCAL_SRC_FILES := main.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/*.c)
LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/common/*.c)
LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/third_party/xdl/*.c)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/common
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/third_party/bsd
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/third_party/lss
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/third_party/xdl
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/arch/arm/*.c)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/arch/arm
endif
ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/arch/arm64/*.c)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/shadowhook/src/main/cpp/arch/arm64
endif
LOCAL_STATIC_LIBRARIES := libcxx
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
include $(LOCAL_PATH)/libcxx/Android.mk

View File

@@ -1,3 +0,0 @@
APP_STL := none
APP_CFLAGS := -Oz -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden
APP_CPPFLAGS := -std=c++20

View File

@@ -1,15 +1,15 @@
cmake_minimum_required(VERSION 3.22.1)
project(zygisk)
project(playintegrityfix)
include_directories(${CMAKE_SOURCE_DIR}/libcxx/include)
find_package(cxx REQUIRED CONFIG)
link_libraries(${CMAKE_SOURCE_DIR}/libcxx/${CMAKE_ANDROID_ARCH_ABI}.a)
link_libraries(cxx::cxx)
add_library(${CMAKE_PROJECT_NAME} SHARED ${CMAKE_SOURCE_DIR}/main.cpp)
add_subdirectory(Dobby)
SET_OPTION(Plugin.Android.BionicLinkerUtil ON)
target_compile_features(${CMAKE_PROJECT_NAME} PRIVATE c_std_23 cxx_std_23)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE log)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE log dobby_static)

1
app/src/main/cpp/json Submodule

Submodule app/src/main/cpp/json added at 9cca280a4d

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,8 @@
#include <unistd.h>
#include "zygisk.hpp"
#include "shadowhook.h"
#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__)
@@ -13,7 +13,11 @@
#define JSON_FILE_PATH "/data/adb/modules/playintegrityfix/pif.json"
#define CUSTOM_JSON_FILE_PATH "/data/adb/modules/playintegrityfix/custom.pif.json"
static int VERBOSE_LOGS = 0;
static int verboseLogs = 0;
static int spoofBuild = 1;
static int spoofProps = 1;
static int spoofProvider = 1;
static int spoofSignature = 0;
static std::map<std::string, std::string> jsonProps;
@@ -22,7 +26,6 @@ typedef void (*T_Callback)(void *, const char *, const char *, uint32_t);
static std::map<void *, T_Callback> callbacks;
static void modify_callback(void *cookie, const char *name, const char *value, uint32_t serial) {
if (cookie == nullptr || name == nullptr || value == nullptr || !callbacks.contains(cookie)) return;
const char *oldValue = value;
@@ -30,7 +33,9 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
std::string prop(name);
// Spoof specific property values
if (prop == "sys.usb.state") {
if (prop == "init.svc.adbd") {
value = "stopped";
} else if (prop == "sys.usb.state") {
value = "mtp";
}
@@ -48,7 +53,7 @@ static void modify_callback(void *cookie, const char *name, const char *value, u
}
if (oldValue == value) {
if (VERBOSE_LOGS > 99) LOGD("[%s]: %s (unchanged)", name, value);
if (verboseLogs > 99) LOGD("[%s]: %s (unchanged)", name, oldValue);
} else {
LOGD("[%s]: %s -> %s", name, oldValue, value);
}
@@ -67,18 +72,14 @@ static void my_system_property_read_callback(const prop_info *pi, T_Callback cal
}
static void doHook() {
shadowhook_init(SHADOWHOOK_MODE_UNIQUE, false);
void *handle = shadowhook_hook_sym_name(
"libc.so",
"__system_property_read_callback",
reinterpret_cast<void *>(my_system_property_read_callback),
reinterpret_cast<void **>(&o_system_property_read_callback)
);
void *handle = DobbySymbolResolver(nullptr, "__system_property_read_callback");
if (handle == nullptr) {
LOGD("Couldn't find '__system_property_read_callback' handle");
return;
}
LOGD("Found '__system_property_read_callback' handle at %p", handle);
DobbyHook(handle, reinterpret_cast<dobby_dummy_func_t>(my_system_property_read_callback),
reinterpret_cast<dobby_dummy_func_t *>(&o_system_property_read_callback));
}
class PlayIntegrityFix : public zygisk::ModuleBase {
@@ -92,21 +93,30 @@ public:
bool isGms = false, isGmsUnstable = false;
auto rawProcess = env->GetStringUTFChars(args->nice_name, nullptr);
auto rawDir = env->GetStringUTFChars(args->app_data_dir, nullptr);
if (rawProcess) {
std::string_view process(rawProcess);
isGms = process.starts_with("com.google.android.gms");
isGmsUnstable = process.compare("com.google.android.gms.unstable") == 0;
// Prevent crash on apps with no data dir
if (rawDir == nullptr) {
env->ReleaseStringUTFChars(args->nice_name, rawProcess);
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
std::string_view process(rawProcess);
std::string_view dir(rawDir);
isGms = dir.ends_with("/com.google.android.gms");
isGmsUnstable = process == "com.google.android.gms.unstable";
env->ReleaseStringUTFChars(args->nice_name, rawProcess);
env->ReleaseStringUTFChars(args->app_data_dir, rawDir);
if (!isGms) {
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
// We are in GMS now, force unmount
api->setOption(zygisk::FORCE_DENYLIST_UNMOUNT);
if (!isGmsUnstable) {
@@ -114,7 +124,9 @@ public:
return;
}
std::vector<char> jsonVector;
long dexSize = 0, jsonSize = 0;
int fd = api->connectCompanion();
read(fd, &dexSize, sizeof(long));
@@ -122,43 +134,41 @@ public:
if (dexSize < 1) {
close(fd);
LOGD("Couldn't read classes.dex");
LOGD("Couldn't read dex file");
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
if (jsonSize < 1) {
close(fd);
LOGD("Couldn't read pif.json");
LOGD("Couldn't read json file");
api->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
return;
}
LOGD("Read from file descriptor for 'dex' -> %ld bytes", dexSize);
LOGD("Read from file descriptor for 'json' -> %ld bytes", jsonSize);
dexVector.resize(dexSize);
read(fd, dexVector.data(), dexSize);
std::vector<char> jsonVector(jsonSize);
jsonVector.resize(jsonSize);
read(fd, jsonVector.data(), jsonSize);
close(fd);
LOGD("Read from file descriptor file 'classes.dex' -> %ld bytes", dexSize);
LOGD("Read from file descriptor file 'pif.json' -> %ld bytes", jsonSize);
std::string data(jsonVector.cbegin(), jsonVector.cend());
json = nlohmann::json::parse(data, nullptr, false, true);
std::string jsonString(jsonVector.cbegin(), jsonVector.cend());
json = nlohmann::json::parse(jsonString, nullptr, false, true);
jsonVector.clear();
data.clear();
jsonString.clear();
}
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
if (dexVector.empty() || json.empty()) return;
readJson();
doHook();
if (spoofProps > 0) doHook();
inject();
dexVector.clear();
@@ -178,26 +188,65 @@ private:
void readJson() {
LOGD("JSON contains %d keys!", static_cast<int>(json.size()));
// Verbose logging if VERBOSE_LOGS with level number is last entry
if (json.contains("VERBOSE_LOGS")) {
if (!json["VERBOSE_LOGS"].is_null() && json["VERBOSE_LOGS"].is_string() && json["VERBOSE_LOGS"] != "") {
VERBOSE_LOGS = stoi(json["VERBOSE_LOGS"].get<std::string>());
if (VERBOSE_LOGS > 0) LOGD("Verbose logging (level %d) enabled!", VERBOSE_LOGS);
// 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>());
if (verboseLogs > 0) LOGD("Verbose logging (level %d) enabled!", verboseLogs);
} else {
LOGD("Error parsing VERBOSE_LOGS!");
LOGD("Error parsing verboseLogs!");
}
json.erase("verboseLogs");
}
// Advanced spoofing settings
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 (VERBOSE_LOGS > 1) LOGD("Parsing %s...", jsonList.key().c_str());
if (verboseLogs > 1) LOGD("Parsing %s", jsonList.key().c_str());
if (jsonList.key().find_first_of("*.") != std::string::npos) {
// Name contains . or * (wildcard) so assume real property name
if (!jsonList.value().is_null() && jsonList.value().is_string()) {
if (jsonList.value() == "") {
LOGD("%s is empty, skipping...", jsonList.key().c_str());
LOGD("%s is empty, skipping", jsonList.key().c_str());
} else {
if (VERBOSE_LOGS > 0) LOGD("Adding '%s' to properties list", jsonList.key().c_str());
if (verboseLogs > 0) LOGD("Adding '%s' to properties list", jsonList.key().c_str());
jsonProps[jsonList.key()] = jsonList.value();
}
} else {
@@ -213,37 +262,32 @@ private:
}
void inject() {
LOGD("get system classloader");
LOGD("JNI: Getting system classloader");
auto clClass = env->FindClass("java/lang/ClassLoader");
auto getSystemClassLoader = env->GetStaticMethodID(clClass, "getSystemClassLoader",
"()Ljava/lang/ClassLoader;");
auto getSystemClassLoader = env->GetStaticMethodID(clClass, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
auto systemClassLoader = env->CallStaticObjectMethod(clClass, getSystemClassLoader);
LOGD("create class loader");
LOGD("JNI: Creating module classloader");
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 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("load class");
auto loadClass = env->GetMethodID(clClass, "loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;");
LOGD("JNI: Loading module class");
auto loadClass = env->GetMethodID(clClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
auto entryClassName = env->NewStringUTF("es.chiteroman.playintegrityfix.EntryPoint");
auto entryClassObj = env->CallObjectMethod(dexCl, loadClass, entryClassName);
auto entryClass = (jclass) entryClassObj;
LOGD("read json");
auto readProps = env->GetStaticMethodID(entryClass, "readJson",
"(Ljava/lang/String;)V");
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, readProps, javaStr);
env->CallStaticVoidMethod(entryClass, receiveJson, javaStr);
LOGD("call init");
auto entryInit = env->GetStaticMethodID(entryClass, "init", "()V");
env->CallStaticVoidMethod(entryClass, entryInit);
LOGD("JNI: Calling init");
auto entryInit = env->GetStaticMethodID(entryClass, "init", "(IIII)V");
env->CallStaticVoidMethod(entryClass, entryInit, verboseLogs, spoofBuild, spoofProvider, spoofSignature);
}
};

View File

@@ -0,0 +1,41 @@
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
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);
}
}

View File

@@ -12,7 +12,10 @@ public final class CustomProvider extends Provider {
@Override
public synchronized Service getService(String type, String algorithm) {
EntryPoint.spoofDevice();
if (EntryPoint.getVerboseLogs() > 2) EntryPoint.LOG(String.format("Service: Caller type '%s' with algorithm '%s'", type, algorithm));
if (EntryPoint.getSpoofBuildEnabled() > 0) {
if (type.equals("KeyStore")) EntryPoint.spoofDevice();
}
return super.getService(type, algorithm);
}
}

View File

@@ -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,15 +26,56 @@ 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<>();
public static void init() {
spoofProvider();
spoofDevice();
public static Integer getVerboseLogs() {
return verboseLogs;
}
public static void readJson(String data) {
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();
if (spoofProviderVal > 0) spoofProvider();
if (spoofBuildVal > 0) spoofDevice();
if (spoofSignatureVal > 0) spoofPackageManager();
}
public static void receiveJson(String data) {
try (JsonReader reader = new JsonReader(new StringReader(data))) {
reader.beginObject();
while (reader.hasNext()) {
@@ -68,13 +118,65 @@ public final class EntryPoint {
static void spoofDevice() {
for (String key : map.keySet()) {
// Verbose logging if VERBOSE_LOGS with level number is last entry
if (key.equals("VERBOSE_LOGS")) {
verboseLogs = Integer.parseInt(map.get("VERBOSE_LOGS"));
} else {
setField(key, map.get(key));
setField(key, map.get(key));
}
}
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) {
@@ -86,7 +188,7 @@ public final class EntryPoint {
private static void setField(String name, String value) {
if (value.isEmpty()) {
LOG(String.format("%s is empty, skipping...", name));
LOG(String.format("%s is empty, skipping", name));
return;
}
@@ -141,6 +243,27 @@ public final class EntryPoint {
LOG(String.format("[%s]: %s -> %s", name, oldValue, value));
}
private static String logParseField(Field field) {
Object value = null;
String type = field.getType().getName();
String name = field.getName();
try {
value = field.get(null);
} catch (IllegalAccessException|NullPointerException e) {
return String.format("Couldn't access '%s' field value: " + e, name);
}
return String.format("<%s> %s: %s", type, name, String.valueOf(value));
}
private static void logFields() {
for (Field field : Build.class.getDeclaredFields()) {
LOG("Build " + logParseField(field));
}
for (Field field : Build.VERSION.class.getDeclaredFields()) {
LOG("Build.VERSION " + logParseField(field));
}
}
static void LOG(String msg) {
Log.d("PIF/Java", msg);
}

View File

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

Binary file not shown.

View File

@@ -1,6 +1,7 @@
#Tue Oct 31 00:21:30 CET 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

297
gradlew vendored
View File

@@ -1,7 +1,7 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,69 +15,104 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# This is normally unused
# 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
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +122,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,88 +133,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
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,
# 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.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

183
gradlew.bat vendored
View File

@@ -1,89 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@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 ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -1 +1 @@
#MAGISK
#MAGISK

15
module/action.sh Normal file
View 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 || exit 1
echo -e "\nDone!"
# warn since Magisk's implementation automatically closes if successful
if [ "$KSU" != "true" -a "$APATCH" != "true" ]; then
echo -e "\nClosing dialog in 20 seconds ..."
sleep 20
fi

164
module/autopif2.sh Normal file
View File

@@ -0,0 +1,164 @@
#!/system/bin/sh
if [ "$USER" != "root" -a "$(whoami 2>/dev/null)" != "root" ]; then
echo "autopif2: need root permissions";
exit 1;
fi;
case "$1" in
-h|--help|help) echo "sh autopif2.sh [-a]"; exit 0;;
-a|--advanced|advanced) ARGS="-a"; shift;;
esac;
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 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 -q "bad date"; then
if ! find_busybox; then
die "date broken";
else
date() { $BUSYBOX date "$@"; }
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_GSI_HTML --no-check-certificate https://developer.android.com/topic/generic-system-image/releases 2>&1 || exit 1;
grep -m1 -o 'li>.*(Beta)' PIXEL_GSI_HTML | cut -d\> -f2;
BETA_REL_DATE="$(date -D '%B %e, %Y' -d "$(grep -m1 -o 'Date:.*' PIXEL_GSI_HTML | cut -d\ -f2-4)" '+%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";
RELEASE="$(grep -m1 'corresponding Google Pixel builds' PIXEL_GSI_HTML | grep -o '/versions/.*' | cut -d\/ -f3)";
ID="$(grep -m1 -o 'Build:.*' PIXEL_GSI_HTML | cut -d\ -f2)";
INCREMENTAL="$(grep -m1 -o "$ID-.*-" PIXEL_GSI_HTML | cut -d- -f2)";
wget -q -O PIXEL_GET_HTML --no-check-certificate https://developer.android.com$(grep -m1 'corresponding Google Pixel builds' PIXEL_GSI_HTML | grep -o 'href.*' | cut -d\" -f2) 2>&1 || exit 1;
wget -q -O PIXEL_BETA_HTML --no-check-certificate https://developer.android.com$(grep -m1 'Factory images for Google Pixel' PIXEL_GET_HTML | grep -o 'href.*' | cut -d\" -f2) 2>&1 || exit 1;
MODEL_LIST="$(grep -A1 'tr id=' PIXEL_BETA_HTML | grep 'td' | sed 's;.*<td>\(.*\)</td>;\1;')";
PRODUCT_LIST="$(grep -o 'factory/.*_beta' PIXEL_BETA_HTML | cut -d\/ -f2)";
wget -q -O PIXEL_SECBULL_HTML --no-check-certificate https://source.android.com/docs/security/bulletin/pixel 2>&1 || exit 1;
SECURITY_PATCH="$(grep -A15 "$(grep -m1 -o 'Security patch level:.*' PIXEL_GSI_HTML | cut -d\ -f4-)" PIXEL_SECBULL_HTML | grep -m1 -B1 '</tr>' | grep 'td' | sed 's;.*<td>\(.*\)</td>;\1;')";
case "$1" in
-m)
DEVICE="$(getprop ro.product.device)";
case "$PRODUCT_LIST" in
*${DEVICE}_beta*)
MODEL="$(getprop ro.product.model)";
PRODUCT="${DEVICE}_beta";
;;
esac;
;;
esac;
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})";
DEVICE="$(echo "$PRODUCT" | sed 's/_beta//')";
}
set_random_beta;
fi;
echo "$MODEL ($PRODUCT)";
item "Dumping values to minimal pif.json ...";
cat <<EOF | tee pif.json;
{
"MANUFACTURER": "Google",
"MODEL": "$MODEL",
"FINGERPRINT": "google/$PRODUCT/$DEVICE:$RELEASE/$ID/$INCREMENTAL:user/release-keys",
"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;
[ -f "$OLDJSON" ] && grep -qE "verboseLogs|VERBOSE_LOGS" $OLDJSON && ARGS="-a";
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() { grep -m1 "$1" $2 | cut -d\" -f4; }
verboseLogs=$(grep_json "VERBOSE_LOGS" $OLDJSON);
ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature 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;
grep -q '//"\*.security_patch"' $OLDJSON && 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 ..;
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;
fi;
fi;

56
module/common_func.sh Normal file
View File

@@ -0,0 +1,56 @@
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
-f|--force) local FORCE=1; shift;;
esac
local NAME="$1"
local NEWVALUE="$2"
local CURVALUE="$(resetprop "$NAME")"
[ ! "$NEWVALUE" -o ! "$CURVALUE" ] && return 1
[ "$NEWVALUE" = "$CURVALUE" -a ! "$FORCE" ] && return 2
local NEWLEN=${#NEWVALUE}
if [ -f /dev/__properties__ ]; then
local PROPFILE=/dev/__properties__
else
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)
#<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')"
printf "Patch '$NAME' to '$NEWVALUE' in '$PROPFILE' @ 0x%08x -> \n[0000??$NEWHEX]\n" $((NAMEOFFSET-96))
echo -ne "\x00\x00" \
| dd obs=1 count=2 seek=$((NAMEOFFSET-96)) conv=notrunc of="$PROPFILE"
echo -ne "$(printf "$NEWHEX" | sed -e 's/.\{2\}/&\\x/g' -e 's/^/\\x/' -e 's/\\x$//')" \
| dd obs=1 count=93 seek=$((NAMEOFFSET-93)) conv=notrunc of="$PROPFILE"
}
# resetprop_if_diff <prop name> <expected value>
resetprop_if_diff() {
local NAME="$1"
local EXPECTED="$2"
local CURRENT="$(resetprop "$NAME")"
[ -z "$CURRENT" ] || [ "$CURRENT" = "$EXPECTED" ] || $RESETPROP "$NAME" "$EXPECTED"
}
# resetprop_if_match <prop name> <value match string> <new value>
resetprop_if_match() {
local NAME="$1"
local CONTAINS="$2"
local VALUE="$3"
[[ "$(resetprop "$NAME")" = *"$CONTAINS"* ]] && $RESETPROP "$NAME" "$VALUE"
}
# stub for boot-time
ui_print() { return; }

74
module/common_setup.sh Normal file
View File

@@ -0,0 +1,74 @@
# Remove any definitely conflicting modules that are installed
if [ -d /data/adb/modules/safetynet-fix ]; then
touch /data/adb/modules/safetynet-fix/remove
ui_print "! Universal SafetyNet Fix (USNF) module will be removed on next reboot"
fi
# Replace/hide conflicting custom ROM injection app folders/files to disable them
LIST=$MODPATH/example.app_replace.list
[ -f "$MODPATH/custom.app_replace.list" ] && LIST=$MODPATH/custom.app_replace.list
for APP in $(grep -v '^#' $LIST); do
if [ -e "$APP" ]; then
case $APP in
/system/*) ;;
*) PREFIX=/system;;
esac
HIDEPATH=$MODPATH$PREFIX$APP
if [ -d "$APP" ]; then
mkdir -p $HIDEPATH
if [ "$KSU" = "true" -o "$APATCH" = "true" ]; then
setfattr -n trusted.overlay.opaque -v y $HIDEPATH
else
touch $HIDEPATH/.replace
fi
else
mkdir -p $(dirname $HIDEPATH)
if [ "$KSU" = "true" -o "$APATCH" = "true" ]; then
mknod $HIDEPATH c 0 0
else
touch $HIDEPATH
fi
fi
case $APP in
*/overlay/*)
CFG=$(echo $APP | grep -oE '.*/overlay')/config/config.xml
if [ -f "$CFG" ]; then
if [ -d "$APP" ]; then
APK=$(readlink -f $APP/*.apk);
elif [[ "$APP" = *".apk" ]]; then
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)
if [ "$PKGNAME" ] && grep -q "overlay package=\"$PKGNAME" $CFG; then
HIDECFG=$MODPATH$PREFIX$CFG
if [ ! -f "$HIDECFG" ]; then
mkdir -p $(dirname $HIDECFG)
cp -af $CFG $HIDECFG
fi
sed -i 's;<overlay \(package="'"$PKGNAME"'".*\) />;<!-- overlay \1 -->;' $HIDECFG
fi
fi
fi
;;
esac
if [[ -d "$APP" || "$APP" = *".apk" ]]; then
ui_print "! $(basename $APP .apk) ROM app disabled, please uninstall any user app versions/updates after next reboot"
[ "$HIDECFG" ] && ui_print "! + $PKGNAME entry commented out in copied overlay config"
fi
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 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
fi

View File

@@ -1,22 +1,36 @@
# Error on < Android 8
if [ "$API" -lt 26 ]; then
abort "! You can't use this module on Android < 8.0"
# Allow a scripts-only mode for older Android (<10) which may not require the Zygisk components
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 \
$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
fi
# Remove/warn if conflicting modules are installed
if [ -d /data/adb/modules/safetynet-fix ]; then
touch /data/adb/modules/safetynet-fix/remove
ui_print "! Universal SafetyNet Fix (USNF) module will be removed on next reboot"
# 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
fi
# Copy any supported custom files to updated module
for FILE in custom.app_replace.list custom.pif.json; do
if [ -f "/data/adb/modules/playintegrityfix/$FILE" ]; then
ui_print "- Restoring $FILE"
cp -af /data/adb/modules/playintegrityfix/$FILE $MODPATH/$FILE
fi
done
# Warn if potentially conflicting modules are installed
if [ -d /data/adb/modules/MagiskHidePropsConf ]; then
ui_print "! MagiskHidePropsConfig (MHPC) module may cause issues with PIF"
fi
# Copy any custom.pif.json to updated module
if [ -f /data/adb/modules/playintegrityfix/custom.pif.json ]; then
ui_print "- Restoring custom.pif.json"
cp -af /data/adb/modules/playintegrityfix/custom.pif.json $MODPATH/custom.pif.json
fi
# Run common tasks for installation and boot-time
[ -d "$MODPATH/zygisk" ] && . $MODPATH/common_setup.sh
# Migrate custom.pif.json to latest defaults if needed
if [ -f "$MODPATH/custom.pif.json" ] && ! grep -q "api_level" $MODPATH/custom.pif.json; then
@@ -28,5 +42,5 @@ if [ -f "$MODPATH/custom.pif.json" ] && ! grep -q "api_level" $MODPATH/custom.pi
fi
# Clean up any leftover files from previous deprecated methods
rm -f /data/data/com.google.android.gms/cache/pif.prop /data/data/com.google.android.gms/pif.prop
rm -f /data/data/com.google.android.gms/cache/pif.json /data/data/com.google.android.gms/pif.json
rm -f /data/data/com.google.android.gms/cache/pif.prop /data/data/com.google.android.gms/pif.prop \
/data/data/com.google.android.gms/cache/pif.json /data/data/com.google.android.gms/pif.json

View File

@@ -0,0 +1,21 @@
# Rename to custom.app_replace.list once customized
#
# Add conflicting custom ROM injection app folder/file paths to this list
# and they will be replaced/hidden systemlessly to disable them
# Xiaomi.eu
/product/app/XiaomiEUInject
/product/app/XiaomiEUInject-Stub
# EliteRoms
/system/app/EliteDevelopmentModule
/system/app/XInjectModule
# hentaiOS
/system_ext/app/hentaiLewdbSVTDummy
# Evolution X
/system_ext/app/PifPrebuilt
# PixelOS
/system_ext/overlay/CertifiedPropsOverlay.apk

View File

@@ -1,6 +1,8 @@
// Rename to custom.pif.json once completed
//
// See android.os.Build source for field value corresponding properties:
// These are the current suggested defaults but you may add as many other fields/properties as needed
//
// 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
{
@@ -22,5 +24,5 @@
// System Properties
"*.build.id": "", // for ro.build.id
"*.security_patch": "", // for ro.build.version.security_patch
"*api_level": "" // for 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
}

12
module/killgms.sh Normal file
View File

@@ -0,0 +1,12 @@
#!/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;

View File

@@ -1,30 +1,56 @@
#!/bin/sh
N="
";
case "$1" in
install) INSTALL=1; shift;;
-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";;
$N by osm0sis @ xda-developers $N";;
esac;
item() { echo "- $@"; }
die() { [ "$INSTALL" ] || echo "\n\n! $@"; exit 1; }
grep_get_json() { grep "$1" "$DIR/custom.pif.json" | cut -d\" -f4; }
grep_check_json() { grep -q "$1" "$DIR/custom.pif.json" && [ "$(grep_get_json "$1")" ]; }
die() { [ "$INSTALL" ] || echo "$N$N! $@"; exit 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-)";
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")" ];
}
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";
DIR="$1";
shift;
else
case "$0" in
*.sh) DIR="$0";;
*) DIR="$(lsof -p $$ 2>/dev/null | grep -o '/.*migrate.sh$')";;
*) DIR="$(lsof -p $$ 2>/dev/null | grep -o '/.*migrate.sh$')";;
esac;
fi;
DIR=$(dirname "$(readlink -f "$DIR")");
[ -z "$FILE" ] && FILE="$DIR/custom.pif.json";
[ -f "$DIR/custom.pif.json" ] || die "No custom.pif.json found";
OUT="$2";
[ -z "$OUT" ] && OUT="$DIR/custom.pif.json";
grep_check_json api_level && die "No migration required";
[ -f "$FILE" ] || die "No json file found";
grep_check_json api_level && [ ! "$FORCE" ] && die "No migration required";
[ "$INSTALL" ] || item "Parsing fields ...";
@@ -32,9 +58,13 @@ FPFIELDS="BRAND PRODUCT DEVICE RELEASE ID INCREMENTAL TYPE TAGS";
ALLFIELDS="MANUFACTURER MODEL FINGERPRINT $FPFIELDS SECURITY_PATCH DEVICE_INITIAL_SDK_INT";
for FIELD in $ALLFIELDS; do
eval $FIELD=\"$(grep_get_json \"$FIELD\")\";
eval $FIELD=\"$(grep_get_json $FIELD)\";
done;
if [ -n "$ID" ] && ! grep_check_json build.id; then
item 'Simple entry ID found, changing to ID field and "*.build.id" property ...';
fi;
if [ -z "$ID" ] && grep_check_json BUILD_ID; then
item 'Deprecated entry BUILD_ID found, changing to ID field and "*.build.id" property ...';
ID="$(grep_get_json BUILD_ID)";
@@ -45,34 +75,65 @@ if [ -n "$SECURITY_PATCH" ] && ! grep_check_json security_patch; then
fi;
if grep_check_json VNDK_VERSION; then
item 'Deprecated entry VNDK_VERSION found, changing to "*.vndk_version" property ...';
item 'Deprecated entry VNDK_VERSION found, changing to "*.vndk.version" property ...';
VNDK_VERSION="$(grep_get_json VNDK_VERSION)";
fi;
if [ -n "$DEVICE_INITIAL_SDK_INT" ] && ! grep_check_json api_level; then
item 'Simple entry DEVICE_INITIAL_SDK_INT found, changing to DEVICE_INITIAL_SDK_INT field and "*api_level" property ...';
fi;
if [ -z "$DEVICE_INITIAL_SDK_INT" ] && grep_check_json FIRST_API_LEVEL; then
item 'Deprecated entry FIRST_API_LEVEL found, changing to DEVICE_INITIAL_SDK_INT field and "*api_level" property ...';
DEVICE_INITIAL_SDK_INT="$(grep_get_json FIRST_API_LEVEL)";
fi;
if [ -z "$RELEASE" -o -z "$INCREMENTAL" -o -z "$TYPE" -o -z "$TAGS" ]; then
item "Missing default fields found, deriving from FINGERPRINT ...";
if [ -z "$RELEASE" -o -z "$INCREMENTAL" -o -z "$TYPE" -o -z "$TAGS" -o "$OVERRIDE" ]; then
if [ "$OVERRIDE" ]; then
item "Overriding values for fields derivable from FINGERPRINT ...";
else
item "Missing default fields found, deriving from FINGERPRINT ...";
fi;
IFS='/:' read F1 F2 F3 F4 F5 F6 F7 F8 <<EOF
$(grep_get_json FINGERPRINT)
EOF
i=1;
for FIELD in $FPFIELDS; do
eval [ -z "\$$FIELD" ] \&\& $FIELD=\"\$F$i\";
eval [ -z \"\$$FIELD\" -o \"$OVERRIDE\" ] \&\& $FIELD=\"\$F$i\";
i=$((i+1));
done;
fi;
if [ -z "$SECURITY_PATCH" -o "$SECURITY_PATCH" = "null" ]; then
item 'Missing required SECURITY_PATCH field and "*.security_patch" property value found, leaving empty ...';
unset SECURITY_PATCH;
fi;
if [ -z "$DEVICE_INITIAL_SDK_INT" -o "$DEVICE_INITIAL_SDK_INT" = "null" ]; then
item 'Missing required DEVICE_INITIAL_SDK_INT field and "*api_level" property value found, setting to 25 ...';
DEVICE_INITIAL_SDK_INT=25;
fi;
item "Renaming old file to custom.pif.json.bak ...";
mv -f "$DIR/custom.pif.json" "$DIR/custom.pif.json.bak";
ADVSETTINGS="spoofBuild spoofProps spoofProvider spoofSignature verboseLogs";
spoofBuild=1;
spoofProps=1;
spoofProvider=1;
spoofSignature=0;
verboseLogs=0;
if [ -f "$OUT" ]; then
item "Renaming old file to $(basename "$OUT").bak ...";
mv -f "$OUT" "$OUT.bak";
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 ...";
@@ -81,12 +142,16 @@ echo " // Build Fields";
for FIELD in $ALLFIELDS; do
eval echo '\ \ \ \ \"$FIELD\": \"'\$$FIELD'\",';
done;
echo -e "\n // System Properties";
echo "$N // System Properties";
echo ' "*.build.id": "'$ID'",';
echo ' "*.security_patch": "'$SECURITY_PATCH'",';
[ -z "$VNDK_VERSION" ] || echo ' "*.vndk_version": "'$VNDK_VERSION'",';
echo ' "*api_level": "'$DEVICE_INITIAL_SDK_INT'"';
echo "}") > "$DIR/custom.pif.json";
[ "$INSTALL" ] || cat "$DIR/custom.pif.json";
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";
for SETTING in $ADVSETTINGS; do
eval echo '\ \ \ \ \"$SETTING\": \"'\$$SETTING'\",';
done;
fi) | sed '$s/,/\n}/' > "$OUT";
[ "$INSTALL" ] || cat "$OUT";

View File

@@ -1,7 +1,7 @@
id=playintegrityfix
name=Play Integrity Fork
version=v5
versionCode=5000
version=v11
versionCode=110000
author=osm0sis & chiteroman @ xda-developers
description=Fix CTS profile (SafetyNet) and DEVICE verdict (Play Integrity)
description=Fix ctsProfile (SafetyNet) and DEVICE (Play Integrity) verdicts
updateJson=https://raw.githubusercontent.com/osm0sis/PlayIntegrityFork/main/update.json

View File

@@ -1,43 +1,42 @@
# Remove Play Services from Magisk Denylist when set to enforcing
if magisk --denylist status; then
magisk --denylist rm com.google.android.gms
fi
MODPATH="${0%/*}"
. $MODPATH/common_func.sh
# Remove conflicting modules if installed
if [ -d /data/adb/modules/safetynet-fix ]; then
touch /data/adb/modules/safetynet-fix/remove
if [ -d "$MODPATH/zygisk" ]; then
# Remove Play Services from Magisk DenyList when set to Enforce in normal mode
if magisk --denylist status; then
magisk --denylist rm com.google.android.gms
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
magisk --denylist add com.google.android.gms com.google.android.gms.unstable
fi
# Conditional early sensitive properties
resetprop_if_diff() {
local NAME=$1
local EXPECTED=$2
local CURRENT=$(resetprop $NAME)
[ -z "$CURRENT" ] || [ "$CURRENT" == "$EXPECTED" ] || resetprop $NAME $EXPECTED
}
resetprop_if_match() {
local NAME=$1
local CONTAINS=$2
local VALUE=$3
[[ "$(resetprop $NAME)" == *"$CONTAINS"* ]] && resetprop $NAME $VALUE
}
# RootBeer, Microsoft
resetprop_if_diff ro.build.tags release-keys
# Samsung
resetprop_if_diff ro.boot.warranty_bit 0
resetprop_if_diff ro.vendor.boot.warranty_bit 0
resetprop_if_diff ro.vendor.warranty_bit 0
resetprop_if_diff ro.warranty_bit 0
# Realme
resetprop_if_diff ro.boot.realmebootstate green
# OnePlus
resetprop_if_diff ro.is_ever_orange 0
# Microsoft
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
resetprop_if_diff ro.debuggable 0
resetprop_if_diff ro.force.debuggable 0
resetprop_if_diff ro.secure 1

View File

@@ -1,53 +1,49 @@
MODPATH="${0%/*}"
. $MODPATH/common_func.sh
# Conditional sensitive properties
resetprop_if_diff() {
local NAME=$1
local EXPECTED=$2
local CURRENT=$(resetprop $NAME)
[ -z "$CURRENT" ] || [ "$CURRENT" == "$EXPECTED" ] || resetprop $NAME $EXPECTED
}
resetprop_if_match() {
local NAME=$1
local CONTAINS=$2
local VALUE=$3
[[ "$(resetprop $NAME)" == *"$CONTAINS"* ]] && resetprop $NAME $VALUE
}
# 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
fi
# use toybox to protect *stat* access time reading
if [ "$(toybox cat /sys/fs/selinux/enforce)" == "0" ]; then
# use toybox to protect stat access time reading
if [ "$(toybox cat /sys/fs/selinux/enforce)" = "0" ]; then
chmod 640 /sys/fs/selinux/enforce
chmod 440 /sys/fs/selinux/policy
fi
# SafetyNet/Play Integrity
# Conditional late sensitive properties
# must be set after boot_completed for various OEMs
{
# late props which 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
# 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 display 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
}&

View File

@@ -1,6 +1,6 @@
{
"version": "v5",
"versionCode": 5000,
"zipUrl": "https://github.com/osm0sis/PlayIntegrityFork/releases/download/v5/PlayIntegrityFork-v5.zip",
"version": "v11",
"versionCode": 110000,
"zipUrl": "https://github.com/osm0sis/PlayIntegrityFork/releases/download/v11/PlayIntegrityFork-v11.zip",
"changelog": "https://raw.githubusercontent.com/osm0sis/PlayIntegrityFork/main/CHANGELOG.md"
}