The full writeup behind Banking apps on stock LineageOS + microG in 2026. Internal specifics are scrubbed; this is generic enough to run on your own gear.
Complete guide: from a freshly-flashed phone to a stock LineageOS device with working microG where every app you install just works - including banking apps with Play Integrity DEVICE-grade requirements, Play-Store-DRM apps that check installer source, and apps requiring Play Services. No GApps. No manual workarounds per app.
Requires root (APatch / KernelSU / Magisk) - root is what lets you install microG as a system priv-app with the privapp permissions XML that grants signature spoofing. Without root, this guide doesn't apply.
Status of this guide#
Two different things live in here and they carry different weight:
- Verified on hardware: Galaxy S10+, stock LineageOS 23.2 (Android 16), APatch, the May 2026 stack (TEESimulator v3.2 + Tricky Addon v4.3 + a hand-installed keybox). Revolut, McDonald's, s Identity and George all worked on it.
- Reconstructed from upstream sources on 2026-09-20: everything about TEESimulator v4, TrickyStoreOSS, Specter, HMA-OSS and the current keybox feeds. Versions, paths, file formats, dead links and revocation state were each checked against the projects themselves on that date. None of it has been run on my own phone yet.
What changed since May 2026#
If you already run the old stack, read this before touching anything. Four things broke at once and they interact.
TEESimulator v4.0 (2026-08-11) is a different module. It stopped faking a hardware backend and now runs AOSP's own KeyMint reference TA (kmr-ta) in-process inside keystore2. Configuration moved from /data/adb/tricky_store/ to /data/adb/teesim/, target.txt became a JSON profile map in config.json, and the module ships its own WebUI. The old arrangement, where Tricky Addon supplied the WebUI through TEESimulator's webroot, is gone.
Tricky Addon dropped the Valid keybox button. In v4.4 (2026-06-21) the CRL-validated auto-fetch was replaced by a community repo at https://keybox.kowx712.cc plus a custom-provider mechanism. Support for TEESimulator v4's new paths was merged on 2026-08-15, which is after the newest tagged release (v5.0-beta.4, 2026-07-23) - so on a tagged build, Tricky Addon does not understand TEESimulator v4.
The KOW keybox feed is dead, not just broken. raw.githubusercontent.com/KOWX712/Tricky-Addon-Update-Target-List/keybox/.extra still answers HTTP 200 with zero bytes. The last commit on that branch is revoked: 8616ef30679ed43cc2b43e3c97a2319e, dated 2026-06-12. Every recipe built on that URL now produces an empty file in silence. This is the single most common cause of "it cannot pull or verify" - see Troubleshooting.
Enginex0/tricky-addon-enhanced is abandoned. Last commit 2026-05-01, three months before TEESimulator v4 existed, and it only knows the /data/adb/tricky_store/ layout. Its successor TEESimulator-RS last moved on 2026-07-11. The maintained automation is now dpejoh/specter.
Two smaller ones: Dr-TSNG/Hide-My-Applist is gone (the repo 404s), replaced by HMA-OSS, which is a Zygisk module and no longer needs LSPosed / Vector at all. And APatch 11219 (2026-08-01) added the WebUI package-manager API that Tricky Addon v5 requires, so the old "you need a nightly APatch" advice is obsolete - 11224 stable covers it.
What this guide produces#
- Revolut, McDonald's, s Identity, Erste George, Aurora-Store-installed apps - all work.
- Play Integrity DEVICE - achievable through microG's DroidGuard path with a live community hardware keybox.
- Installer-source checks ("must be installed from Google Play") - handled automatically by Aurora Store's Root installer.
- No GApps anywhere on the device.
Pick a track#
The attestation engine is the one component where there is a real choice. Everything else in the guide is shared.
| Track A - TEESimulator v4 | Track B - TrickyStoreOSS | |
|---|---|---|
| Project | JingMatrix/TEESimulator v4.0 (2026-08-11), canaries to 67 (2026-09-05) | beakthoven/TrickyStoreOSS v3.1.0 (2026-08-25) |
| Approach | AOSP reference KeyMint TA in-process, attestations generated the way a real TEE generates them | Certificate patch / generation on the classic Tricky Store model |
| Config | /data/adb/teesim/config.json, JSON profiles | /data/adb/tricky_store/*.txt, one file per concern |
| WebUI | Built in | None - use Tricky Addon or Specter |
| Requires | Android 10 to 17, 64-bit only (keystore2 is 64-bit) | Android 10+ |
| Keybox needs | RSA and ECDSA key, chains of at least 2 | Same shape, ? / ! / auto per package |
| Pick it when | You want the newest anti-detection work and per-app profiles | You want the classic model on paths every tool already understands |
Both are GPL-3.0, so licence is not the deciding factor between them.
Both accept the same keybox file and both are driven by Specter, so switching later costs one module flash and one config import. Track A leads here, Track B is documented to the same depth.
Do not run both at once. They fight over the same keystore2 hooks.
Prerequisites#
- An unlocked-bootloader device with LineageOS Recovery (preferred) or TWRP. LineageOS Recovery handles file-based encryption (FBE) correctly; TWRP on many modern devices either can't decrypt
/dataor breaks encryption when wiping. LineageOS Recovery ships in the LineageOS ZIP itself (theboot.imgIS the recovery on devices with no separate recovery partition; otherwise there's a separaterecovery.img). - A computer with
adbandfastboot(for ROM install and APatch boot.img patching). - Full backup of any data you can't lose.
# Install adb / fastboot
sudo pacman -S android-tools # Arch
sudo apt install android-tools-adb android-tools-fastboot # Debian/UbuntuFor Samsung devices, unlocking the bootloader trips Knox permanently.
Phase 1 - Install LineageOS#
Why not just install microG from F-Droid as a user app? Signature spoofing (which makes microG able to pretend to be Google) requires GmsCore to have FAKE_PACKAGE_SIGNATURE permission. Stock LineageOS doesn't auto-grant this; you have to install microG as a system priv-app with a privapp-permissions-org.microG.xml alongside it. Phase 4 walks through this.
Download#
- ROM:
https://download.lineageos.org/devices/- select your device codename. Download both thelineage-*.zip(ROM) and therecovery.imgif your device page lists one separately. - The LineageOS install page for your device has the exact
fastbootflash sequence - follow that. Don't use TWRP unless LineageOS Recovery isn't available for your device, because TWRP often breaks file-based encryption (/datawon't decrypt after wipe).
Flash#
The exact procedure varies by device. Generic shape (check your device's LineageOS install instructions for specifics):
adb reboot bootloader.- Flash LineageOS Recovery:
fastboot flash recovery recovery.img(orfastboot flash boot boot.imgon devices where boot IS the recovery, A/B partition layouts). - Boot into recovery:
fastboot reboot recovery(or device-specific button combo). - In LineageOS Recovery: Factory reset -> Format data. Wipes user data, preserves encryption setup.
- Apply update -> Apply from ADB -> on your computer:
adb sideload lineage-*.zip. - Reboot to System.
Post-install: install an F-Droid client + Aurora Store#
F-Droid client: pick one (they connect to the same F-Droid repositories, different UIs):
- Droidify (
com.looker.droidify) - modern, faster, cleaner UI. Recommended. Get fromhttps://github.com/Droid-ify/client/releases/latest. - F-Droid (
org.fdroid.fdroid) - the official one, slower UI. Install via APK if you prefer it.
Either works for installing FOSS apps from the F-Droid repo (and the IzzyOnDroid repo if you add it).
Aurora Store: install from your chosen F-Droid client or from https://gitlab.com/AuroraOSS/AuroraStore/-/releases. This is the Play Store anonymous-access client - your main installer for proprietary apps.
Phase 2 - Root with APatch#
Why APatch#
APatch patches the kernel via boot.img injection - works on devices where Magisk's userspace approach has issues, and gives a kernel-level SU primitive that integrates cleanly with the integrity-hiding modules below.
Install#
Download:
- APatch app:
https://github.com/bmax121/APatch/releases/latest- install the APK normally. Current stable is11224(2026-08-07). - Your device's stock boot.img: extract from the LineageOS ZIP you flashed (
payload.bininside, usepayload_dumperor similar) OR from a recovery dump.
Procedure:
- Open APatch app -> Settings -> SuperKey -> set a long random string. Write it down / store in your password manager. This SuperKey gets embedded into the patched boot.img and is the key APatch uses to verify root requests. Lose this key = lose root (would require reflashing).
- Back in APatch app -> tap "Patch boot.img" -> select your stock
boot.img-> APatch producesboot_patched.img. - Pull to PC:
adb pull /storage/emulated/0/Download/boot_patched.img. adb reboot bootloader.fastboot flash boot boot_patched.img.fastboot reboot.
After reboot, open APatch app. It should show "Working" with the KernelPatch version. If it shows "Not installed", the boot.img flash didn't take - re-verify the patch step.
Do not stay on 11142. Release 11219 (2026-08-01) added the WebUI package-manager API that Tricky Addon v5 and several WebUI modules now require, and 11224 is the current stable. On 11142 those WebUIs fail to list apps.
APatch's permission model is opt-in - apps do NOT auto-prompt#
Important difference from Magisk/KernelSU: APatch does NOT show a permission dialog when an app calls su. Apps trying to get root just get permission denied silently.
You grant root manually, per app, ahead of time:
- APatch app -> SuperUser tab.
- Find the app in the list (system + user apps shown together).
- Toggle Allow root ON.
- Optionally also toggle Umount modules ON (for apps you want to hide root modules from - banking apps etc.).
For most apps in this guide:
- Aurora Store -> grant root (it needs root to use Root installer in Phase 10).
- Banking apps (Revolut, George, McDonald's, etc.) -> enable Umount modules, leave Allow root OFF.
- Apps that need root (Termux, MMRL, Iconify, WireGuard tunnel, etc.) -> grant root, leave Umount OFF.
The "ahead of time" model means: if a new app needs root and you didn't pre-grant it, the app fails silently. Watch app behavior the first time you use it and check APatch SuperUser if it acts weird.
Phase 3 - Install the spoof + hiding stack#
Install MMRL (Magisk Modules Repository Loader) from your F-Droid client (Droidify or F-Droid). MMRL handles module installs from URL across Magisk / KernelSU / APatch.
For each module below, in MMRL: tap Install from URL and paste the GitHub release ZIP URL. Install order matters - install NeoZygisk first so dependent modules detect a zygisk implementation at install time.
| # | Module | Version as of 2026-09-20 | Source |
|---|---|---|---|
| 1 | NeoZygisk | v2.4 (2026-08-08) | github.com/JingMatrix/NeoZygisk/releases/latest |
| 2 | Attestation engine | see Pick a track | Track A or Track B, not both |
| 3 | Play Integrity Fix [INJECT] | v4.7-inject-s (2026-07-11) | github.com/KOWX712/PlayIntegrityFix/releases/latest |
| 4 | microG installer | see Phase 4 | github.com/Bakoubak/microg_installer_reborn |
| 5 | zygisk-detach | v1.23.2 (2026-07-09) | github.com/j-hc/zygisk-detach/releases/latest |
| 6 | Specter (automation) | v1.5.0 (2026-09-12) | github.com/dpejoh/specter/releases/latest - see Phase 9 |
PlayIntegrityFork (osm0sis/PlayIntegrityFork, v18, 2026-08-29) is the supported alternative to PIF inject-s. Specter detects either. Pick one.
HMA-OSS is not in that list on purpose. It is optional and nothing here depends on it - see HMA-OSS (optional).
Reboot when all modules are installed.
Modules NOT to install#
Tricky Store(5ec1cff) - dormant since Nov 2025. Track A or Track B replaces it.Enginex0/tricky-addon-enhanced- abandoned 2026-05-01, does not know the TEESimulator v4 layout. Specter treats it as a conflict and disables its scripts.Dr-TSNG/Hide-My-Applist- repo is gone (404). HMA-OSS replaces it.Vector/LSPosed- only needed if you run other Xposed modules. HMA-OSS is Zygisk now, so this stack no longer needs an Xposed framework at all.Zygisk Next- works, butNeoZygiskis the coherent pick alongside the JingMatrix modules.playcurlNEXT- obsolete since PIF inject-s v4.4 self-fetches.- Network proxy modules (
xray4magisketc.) - banking apps detect proxy via/proc/net/route. Add back later if you need them and test each affected app.
Optional, works with or without: Zygisk Assistant. Some guides claim it's required for DEVICE integrity; testing here showed it is neither required nor harmful, and Promon-protected apps dislike its companion socket.
HMA-OSS (optional)#
Skip this unless you have an app that needs it. No app in this guide requires HMA. On the S10+ none of them probed for the root manager's package, and APatch's per-app Umount modules toggle covered the hiding on its own. Everything below works with HMA absent.
If you do install it, the old procedure (install the HMA APK, scope it in LSPosed, tick System Framework) is gone. HMA-OSS-ZYGISK-oss-168-release.zip is a Zygisk module (id=hma_oss_zygisk, minSdkVersion=29) that bundles its own manager.apk and installs it during flash. Flash it, reboot, open the HMA-OSS app that appeared, configure hiding there. It needs a working Zygisk implementation, which NeoZygisk provides.
Its config lives at /data/user/0/org.frknkrc44.hma_oss/files/config.json, which is also where Specter writes when you let it manage HMA.
Phase 4 - Install microG#
Stock LineageOS has no microG. The procedure has a chicken-and-egg quirk: the microG Installer Reborn module (which sets up signature spoofing properly) only works with microG 0.3.6 already installed as a user app. So you install old microG first, then the module promotes it to system priv-app, then you update to current via Droidify.
Install old microG
0.3.6as user apps. Download both APKs via browser, then tap to install:- GmsCore:
https://github.com/microg/GmsCore/releases/download/v0.3.6.244735/com.google.android.gms-244735012.apk - Companion / Vending:
https://github.com/microg/GmsCore/releases/download/v0.3.6.244735/com.android.vending-84022612.apk
(Use the standard
.apkfiles, NOT the-hw.apkHuawei variants.)- GmsCore:
Install
microG Installer Rebornmodule via MMRL: Install from URL ->https://github.com/Bakoubak/microg_installer_reborn/releases/download/v1.0.0-0/microG_Installer_Reborn.zip. The module's install script reads your user-installed microG APKs, copies them to/system/priv-app/, and drops theprivapp-permissions-org.microG.xmlthat grants signature spoofing.Reboot.
Open Droidify -> Settings -> Repositories -> tap
+-> add:- URL:
https://microg.org/fdroid/repo - Fingerprint:
9BD06727E62796C0130EB6DAB39B73157451582CBD138E86C468ACC395D14165
- URL:
Wait for Droidify to sync the new repo, then update microG Services Core and microG Companion to current via Droidify. Current release is
v0.3.16.252432(2026-07-14). In-place upgrade works because the signing key matches.Open microG Settings -> Self-Check -> all items green except SafetyNet (Google killed that endpoint, ignore).
Enable in microG Settings: Cloud Messaging + Google device registration.
Done. Future microG updates arrive in Droidify automatically.
Note: don't try to install current microG directly first - the microG Installer Reborn module aborts if it sees anything newer than 0.3.6 already installed. The trick is start with 0.3.6, run the module, then upgrade.
Phase 5 - the load-bearing microG toggle#
This single setting is what makes DEVICE-grade Play Integrity work through microG. Default is ON (blocking); you turn it OFF.
Path: microG Settings -> Device Attestation -> Advanced -> Block hardware attestation -> uncheck.
Reboot for the toggle to take effect (microG reads the setting at DroidGuard service start, not live).
Verify (optional):
adb shell 'su -c "grep hw_attestation /data/data/com.google.android.gms/shared_prefs/com.google.android.gms_preferences.xml"'
# Expect: <boolean name="droidguard_block_hw_attestation" value="false" />Phase 6 - PIF: enable all spoof flags#
Open APatch -> Modules -> Play Integrity Fix [INJECT] -> Action / Open WebUI. Enable ALL six toggles:
- Spoof Build
- Spoof Build (Play Store)
- Spoof Signature
- Spoof Props
- Spoof Provider
- Spoof SDK (Play Store)
PIF auto-fetches a Pixel Canary fingerprint with its security patch date. That date has to match whatever your attestation engine reports - see Phase 7A / 7B. Specter (Phase 9) keeps the two aligned for you, which is most of the reason to run it.
Phase 7A - TEESimulator v4 (Track A)#
Install from https://github.com/JingMatrix/TEESimulator/releases/latest. The v4.0 tag is build 34; canaries (canary-67 = build 67, 2026-09-05) carry the RKP and detection fixes that landed after the tag. On an RKP-only device the stable tag is not enough - see RKP-only devices.
How it differs from every older Tricky Store#
It does not patch certificates after the fact. It embeds AOSP's reference KeyMint TA inside the real keystore2, harvests the device's genuine attestation parameters once (verified-boot state, patch levels, OS version) and freezes them, then signs targeted apps' attestations with your keybox. Everything not in a profile goes to the real hardware untouched.
Two consequences:
- The root of trust is not configurable. Verified-boot key, boot state and locked flag come from the harvest, deliberately. They also seed KeyMint's key-encryption-key derivation, which is what keeps stored keys decryptable across reboots.
- No keybox = no interception. With no keybox loaded the interceptor is a no-op, so a half-configured module is inert rather than dangerous.
Configure#
Everything lives in /data/adb/teesim/. The daemon owns and validates it, watches for changes and re-pushes live - no reboot after a config edit.
config.json is a schema version plus a map of named profiles. Each targeted package belongs to exactly one profile:
{
"version": 1,
"profiles": {
"default": {
"keybox": "keybox.xml",
"mode": "patch",
"patchLevel": { "system": "today", "vendor": "YYYY-MM-05", "boot": "YYYY-MM-05" },
"osVersion": "",
"brand": "", "device": "", "product": "",
"manufacturer": "", "model": "",
"serial": "", "imei": "", "meid": "", "imei2": "",
"apps": [
"com.google.android.gms",
"com.android.vending",
"com.revolut.revolut",
"com.mcdonalds.mobileapp",
"at.erstebank.george",
"at.erstebank.securityapp",
"com.aurora.store"
]
}
}
}The module ships a default profile that already targets Play services and the Play Store; you add your own packages.
Patch levels take a small mini-language: today is the current month, YYYY-MM-DD / YYYY-MM an explicit date, YYYY / MM / DD resolve against today (so YYYY-MM-05 is always the 5th of the current month), harvested reuses what the real TEE reported, system_property reads the matching build prop, no suppresses the level entirely. A source with no value reports nothing rather than inventing a default.
Device identity fields fall back to the harvested values, so an app asking the keystore to attest real IDs gets a consistent answer. Set them only if you have a reason.
Mode is patch (default - real hardware still generates the key, only the attestation is re-signed under your keybox, so the genuine hardware-backed blob survives) or generation (the module mints the key itself). Use patch unless the device cannot produce a leaf to patch.
WebUI#
On APatch and KernelSU the module ships its own WebUI: create and assign profiles, import and rename keyboxes, pick the operation mode, set patch/OS levels and identity, list and inspect the keys the simulator has stored, watch harvest and injection status and live daemon logs, and download and flash a newer canary in place.
Reach it from APatch -> Modules -> TEESimulator -> Action.
Recovery#
If something goes sideways, killing the keystore daemon gives you a clean one with no interception until the module re-injects:
adb shell 'su -c "kill $(pidof keystore2)"' # Android 12+
adb shell 'su -c "kill $(pidof keystore)"' # Android 10 / 11Tricky Addon and TEESimulator v4#
Support for the new paths was merged into Tricky Addon main on 2026-08-15, but no release carries it yet - v5.0-beta.4 predates the merge. So on any tagged Tricky Addon build, v4 will not be configured correctly. Use TEESimulator's own WebUI, or Specter, and skip Tricky Addon on this track.
Phase 7B - TrickyStoreOSS + Tricky Addon (Track B)#
Install Tricky-Store-OSS-v3.1.0-172-41383f5-Release.zip from https://github.com/beakthoven/TrickyStoreOSS/releases/latest, reboot once. Everything below applies immediately after that - no further reboots.
A clean-room GPLv3 rewrite of the proprietary Tricky Store, on the classic paths, which means every existing tool (Tricky Addon, Specter) already understands it.
target.txt#
One package per line. The module picks leaf-patching or certificate generation per device automatically; the suffix overrides it.
| Suffix | Behaviour |
|---|---|
| (none) | automatic |
? | force leaf hacking |
! | force certificate generation |
at.erstebank.george?
at.erstebank.securityapp
com.android.vending?
com.aurora.store?
com.google.android.gms?
com.google.android.gsf?
com.mcdonalds.mobileapp?
com.revolut.revolut?On a TEE-broken or RKP-only device leaf hacking cannot work, because there is no real leaf certificate to retrieve. Leave those packages on automatic or force !.
security_patch.txt#
Sets the three patch levels the spoofed attestation reports - osPatchLevel (system), vendorPatchLevel, bootPatchLevel. It changes attestation output only, never system properties.
Keys are system, vendor, boot and all. Dates accept YYYY-MM-DD, YYYYMMDD or YYYYMM, and YYYY / MM / DD work as placeholders resolved on every attestation. Three keywords matter: no omits the tag entirely, device_default keeps the device's real value, prop mirrors ro.build.version.security_patch (the older name for device_default).
Settings above any package header are global; a [package.name] header scopes everything under it to that app, inheriting whatever it does not set:
# global default for every app
system=YYYY-MM-05
vendor=device_default
boot=no
# GMS wants the older print date
[com.google.android.gms]
system=2026-08-01Tricky Addon for the WebUI#
v4.4 (2026-06-21) is the current stable and the last v4 release. v5.0-beta.4 requires KernelSU 32234+ or APatch 11159+, which stable APatch 11224 satisfies.
Install from https://github.com/KOWX712/Tricky-Addon-Update-Target-List/releases/latest, then APatch -> Modules -> Tricky Addon -> Action.
The keybox menu in v4.4 offers AOSP, Unknown, Local (a file you point at), Repo (the community repository at https://keybox.kowx712.cc) and any custom providers you define. The old Valid button - the CRL-validated auto-fetch every 2025 guide tells you to press - no longer exists.
The shipped default custom provider is called Addon and points at the dead .extra URL. Delete it or repoint it; see Phase 8.
Phase 8 - The keybox#
The keybox is a file containing a leaked per-device attestation private key and its certificate chain. It must carry both an RSA and an ECDSA (NIST P-256) key, each with its own chain of at least two certificates. Community keyboxes in circulation ship three certificates per chain, so the usual shape check is 6 BEGIN CERTIFICATE blocks.
| Track | Path |
|---|---|
| A - TEESimulator v4 | /data/adb/teesim/keybox.xml |
| B - TrickyStoreOSS | /data/adb/tricky_store/keybox.xml |
Where to get one, September 2026#
| Source | State on 2026-09-20 | How to use it |
|---|---|---|
Specter catalog (rawbin.dpejoh.com/catalog) | live, entries timestamped 2026-09-17, each carrying serial, revoked and softbanned flags | Phase 9 - Specter picks, validates and installs it for you |
Tricky Addon community repo (keybox.kowx712.cc) | live | Tricky Addon WebUI -> Keybox -> Repo |
Yurikey (Yurii0307/yurikey) | live, Yurikey58 published 2026-09-06; I decoded it and checked all 6 serials against Google's CRL - none revoked | custom provider, or the manual route below |
KOW .extra branch | dead - HTTP 200, 0 bytes, last commit revoked: on 2026-06-12 | delete it from your config |
MeowDump/Integrity-Box, Mark-Joy keybox-yurikey | mirrors, no rotation of their own | skip |
To wire Yurikey into Tricky Addon by hand: WebUI -> Keybox -> custom provider -> name Yurikey, URL https://raw.githubusercontent.com/Yurii0307/yurikey/main/key, decode script base64 -d. (The dead Addon entry uses xxd -r -p | base64 -d, which is the hex-then-base64 encoding that feed used.)
Install one by hand#
# Fetch and decode (Yurikey; adjust the decode step per source)
curl -sL https://raw.githubusercontent.com/Yurii0307/yurikey/main/key | base64 -d > keybox.xml
# Shape check - expect 6
grep -c 'BEGIN CERTIFICATE' keybox.xml
# Track A
adb push keybox.xml /sdcard/Download/keybox.xml
adb shell 'su -c "cp /sdcard/Download/keybox.xml /data/adb/teesim/keybox.xml"'
# Track B
adb shell 'su -c "cp /sdcard/Download/keybox.xml /data/adb/tricky_store/keybox.xml"'Neither track needs a reboot - both daemons watch their config directory.
Check it against Google's CRL before you trust it#
Every leaked keybox eventually lands on https://android.googleapis.com/attestation/status, and verifiers check that list. A revoked keybox is worse than none: it is a positive signal.
Two traps break the usual one-liner, and both were in the old version of this guide:
- Community keyboxes ship the base64 unwrapped - one enormous line per certificate. OpenSSL refuses to parse that, so a naive script silently checks nothing.
- Google's CRL keys carry no leading zeros.
openssl x509 -serialprints09307822e6...; the CRL entry is9307822e6.... Strip leading zeros or you get a false "live" on every serial that starts with0.
#!/bin/sh
# kbcheck.sh <keybox.xml> - exit 0 nothing revoked, 1 something revoked, 2 CRL unreachable
KB="$1"
CRL=$(curl -sf https://android.googleapis.com/attestation/status) || { echo "CRL fetch failed"; exit 2; }
rc=0; n=0
sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' "$KB" | tr -d ' \t' | grep -v '^$' | \
while IFS= read -r line; do
case "$line" in
*BEGIN*CERTIFICATE*) echo "-----BEGIN CERTIFICATE-----" ;;
*END*CERTIFICATE*) echo "-----END CERTIFICATE-----" ;;
*) printf '%s\n' "$line" | fold -w 64 ;;
esac
done > certs.pem
csplit -sz -f cert- -b '%02d.pem' certs.pem '/BEGIN CERTIFICATE/' '{*}'
for c in cert-*.pem; do
n=$((n+1))
s=$(openssl x509 -in "$c" -noout -serial | cut -d= -f2 | tr 'A-Z' 'a-z' | sed 's/^0*//')
if printf '%s' "$CRL" | grep -q "\"$s\""; then echo "REVOKED $s"; rc=1; else echo "live $s"; fi
done
[ "$n" -eq 6 ] || echo "warning: $n certificates, expected 6"
rm -f cert-*.pem certs.pem
exit $rcRun against Yurikey58 on 2026-09-20 it prints six live lines. Google's list held 1753 entries that day.
Lifetime#
A community keybox survives roughly 6 to 31 days before its leaf serial appears on the CRL.
Two ways to hear about a revocation before an app tells you:
https://keybox.tryigit.dev/status/- browser push notifications on new CRL entries. (The oldtryigit.dev/keybox/status/address now redirects here.)- Telegram
t.me/CitraIntegrityTrick- mirrors revocation events within hours.
Phase 9 - Automation with Specter#
dpejoh/specter v1.5.0 (2026-09-12) is the maintained answer to "I do not want to copy keyboxes by hand". It is the same author's rewrite of what used to be Yurikey.
What it actually does, from its own scheduler:
| Task | Default interval |
|---|---|
| keybox info refresh | 6 h |
auto-target (plus inotifyd on /data/app, so new installs are picked up immediately) | 5 min |
| PIF fingerprint refresh | 24 h |
| keybox rotation | 24 h |
Plus, on first boot: back up your existing files, build the target list, set the security patch, fetch and install a keybox.
Install#
- Have an attestation engine installed first (Track A or Track B). If Specter finds none it installs
TEESimulator-RSitself, which is not what you want on this guide - install your engine first. - Have PIF or PlayIntegrityFork installed.
- MMRL -> Install from URL ->
https://github.com/dpejoh/specter/releases/latest. - Reboot. Open the WebUI from your root manager.
What it takes over#
Specter enforces single ownership of the things that break when two tools edit them. It classifies other modules:
- Aggressive (uninstalled):
TSupport-Advance,Sensitive Props, the oldYurikeymanager,Integrity Box. - Moderate (scripts disabled, module left in place):
Tricky AddonandTricky Addon Enhanced. - Passive (you choose in the WebUI):
NoHello,TreatWheel,.BRENE, and the TEESimulator WebUI - where security patch and operation mode stay with TEESimulator while Specter keeps keybox install and auto-target.
So on Track A the sane split is: TEESimulator owns mode and patch levels, Specter owns keybox rotation and targeting. On Track B, Specter replaces Tricky Addon's automation and you keep the addon only for its UI, if at all.
Verify it works#
WebUI -> Keybox shows the selected source, its serial and revocation state. The module description line in your root manager also carries a live summary. If the keybox step logs CANNOT LINK EXECUTABLE ... libandroid-support.so, that is the Termux-on-PATH bug fixed in v1.4.5-g1dd7ba9 - update Specter.
Phase 10 - Aurora Store: the installer that just works#
Aurora Store 4.7.5+ has a Root installer mode that automatically tags every install with installerPackageName=com.android.vending. Apps that check the installer source (McDonald's, large retail apps, some games) accept this and don't show "must be installed from Google Play" warnings.
Setup:
- APatch app -> SuperUser tab -> find Aurora Store -> grant root permission (toggle on).
- Open Aurora Store -> Settings -> Installer. The Root installer option only appears after root is granted.
- Select Root installer.
Every subsequent Aurora install gets the right installer source automatically. You can stop doing per-app manual workarounds.
Caveat: Aurora always installs to user 0#
whyorean/AuroraStore RootInstaller.kt hardcodes the target user as user 0:
Shell.cmd("pm install-create -i $PLAY_PACKAGE_NAME --user 0 -r -S $totalSize")Meaning: Aurora running in a work profile (user 10) will still install apps into user 0 (primary). For the cleanest workflow, install Aurora in user 0 and use it from there. Running it from a work profile doesn't isolate the installs - they still land in user 0.
Phase 11 - Shelter (work profile)#
Shelter creates an Android Managed Profile - a separate user namespace (user 10) that's isolated from primary (user 0). Useful for:
- Apps that require work profile (George specifically; see Phase 12).
- Apps you want isolated from your main data / contacts.
- Apps you want to "freeze" individually without uninstalling.
Install Shelter from Droidify / F-Droid (net.typeblog.shelter).
Setup#
- Open Shelter -> tap Set up profile.
- Android prompts: "Set up work profile?" -> tap Set up.
- Android creates user 10. Shelter installs itself in the work profile too. You now have two Shelter app instances (one per profile).
- The work profile shows up in your launcher as a separate "Work" tab or section (launcher-dependent).
- Notifications from work profile apps are tagged with a small briefcase icon.
Day-to-day use#
Open Shelter (primary profile):
- Main profile apps tab: apps in user 0. Long-press any -> Clone to work profile copies it into user 10.
- Work profile apps tab: apps in user 10. Long-press -> Freeze to disable without uninstalling, Uninstall to remove from work profile.
To launch a work-profile app, use the launcher's Work tab OR Shelter -> Work profile apps tab -> tap.
Work-profile quirks#
- Aurora Store's Root installer always installs to user 0 (hardcoded - see Phase 10). Apps you want in work profile must be cloned via Shelter OR installed via
pm install --user 10from adb. - Each user profile has its own UID per app (e.g. George in user 0 = uid 10515, in user 10 = uid 1010515). APatch SuperUser shows per-profile entries; you toggle umount/root per profile.
- Attestation targeting is per package, not per user, so one entry in your profile or
target.txtcovers both copies.
Phase 12 - George (Erste) special case#
George (Austrian Erste Bank, package at.erstebank.george) uses Promon Shield commercial RASP and requires the work profile to run on this stack:
- In user 0: George crashes on launch. Promon's
TEETESTSUPPORTkeystore probe gets an unexpected response and Promon callsabort()(htchom.z: 16SIGABRT). - In user 10: same install runs cleanly. The reason for the user-context difference is empirical only - likely SELinux context differences for
untrusted_appbetween primary and work profile.
So you need Shelter (Phase 11) installed first to have a work profile.
Install George into work profile#
Option A - via Shelter (no adb needed):
- Install George in user 0 first - via Aurora Store with Root installer enabled (Phase 10).
- Open Shelter (primary profile) -> Main profile apps tab -> find George -> long-press -> Clone to work profile.
- Open Shelter (or launcher Work tab) -> find George in work profile -> launch to verify.
- Once you confirm the work-profile copy works, uninstall the user-0 copy: Settings -> Apps -> George (in user 0) -> Uninstall.
Option B - via adb (one-time):
- Download or grab the George APK (Aurora puts it in
/data/data/com.aurora.store/files/Downloads/). - Install into user 10:
adb shell 'su -c "pm install --user 10 -i com.android.vending /sdcard/Download/George.apk"' - If George is in user 0 too:
adb shell 'su -c "pm uninstall --user 0 at.erstebank.george"'
Configure umount in APatch#
APatch app -> SuperUser tab -> switch context to work profile (or find the user-10 entry for George in the unified list) -> enable Umount modules ON, root permission OFF.
First launch#
Launch George from the launcher's Work tab. First launch takes 10-20 seconds while Promon initializes. Should reach the login screen, accept credentials, work normally.
If it still hits the 1007 device does not meet safety requirements error: walk through the George troubleshooting checklist.
What works and what does NOT#
Verified 2026-05-19 on the Galaxy S10+ with the May 2026 stack (TEESimulator v3.2 + Tricky Addon v4.3). The app behaviours below are properties of the apps, not of the attestation engine, so they carry over to both tracks; the integrity verdict itself has to be re-earned with a live keybox.
| App | Where | Status |
|---|---|---|
| Revolut | user 0 | works |
| McDonald's | user 0 | works (Aurora Root installer handles installer-source check) |
| s Identity (Erste 2FA) | user 0 | works |
George (Erste, -google) | user 10 (work profile) | works |
| George in user 0 | n/a | crashes - don't try |
| McDonald's in user 10 | n/a | refuses non-primary - don't try |
Integrity verdicts you should see (test with a real app, NOT Play Integrity API Checker which is broken on microG):
MEETS_BASIC_INTEGRITYMEETS_DEVICE_INTEGRITY(live keybox + microG hardware-attestation toggle disabled + matching security patches)MEETS_STRONG_INTEGRITY(same conditions +ro.build.version.security_patch <= 365 days)
Configuration files reference#
For sanity checks or restoring from a backup. All require root to read.
Track A - TEESimulator v4#
| Path | Content |
|---|---|
/data/adb/teesim/config.json | schema version + named profiles (keybox, mode, patch levels, identity, apps) |
/data/adb/teesim/keybox.xml | hardware keybox; a profile may name a different file in the same directory |
Track B - TrickyStoreOSS#
| Path | Content |
|---|---|
/data/adb/tricky_store/target.txt | packages with ? / ! / bare suffixes |
/data/adb/tricky_store/security_patch.txt | global + per-[package] blocks, keys system / vendor / boot / all |
/data/adb/tricky_store/keybox.xml | hardware keybox |
Shared#
| Path | Content |
|---|---|
/data/adb/specter/ | Specter state: config/, backup/, scheduler_tasks/, log/ |
/data/user/0/org.frknkrc44.hma_oss/files/config.json | HMA-OSS hiding config |
/data/adb/zygisksu/denylist_enforce | must contain 1 |
/data/adb/ap/package_config | APatch per-app umount/root state CSV |
Banking app entry in package_config:
<pkg>,1,0,<uid>,0,u:r:untrusted_app:s0Where 1,0 = umount modules ON, grant root OFF.
Aurora Store (needs root):
com.aurora.store,0,1,<uid>,0,u:r:magisk:s0Where 0,1 = umount OFF, grant root ON.
You don't need to umount Google Play Services packages (GMS / Vending / GSF) - the hiding stack (NeoZygisk denylist + microG hardware-attestation toggle + the attestation engine) handles those.
Troubleshooting#
"Cannot pull or verify" a keybox#
The symptom is a WebUI that will not fetch a keybox, or fetches "successfully" and leaves you with nothing: Please check your internet connection with the device plainly online, Failed to fetch keybox, or a keybox that installs and changes no verdict. Four distinct causes, in the order worth checking:
- The source is empty. The KOW
.extrafeed returns HTTP 200 and zero bytes since 2026-06-12. Any tool pointed at it reports success and writes nothing. Tricky Addon still ships that URL as its default custom provider namedAddon. Fix: repoint it (Phase 8) or use Repo / Specter instead. - The button you are looking for was removed.
Validis gone as of Tricky Addonv4.4. If a guide says "tap Valid", the guide predates June 2026. Fix: use Repo, Local, or a custom provider. - The WebUI's own network path is broken. The historic failure was the WebView routing
raw.githubusercontent.comthrough thehub.gitmirror.comproxy, which resolved to nothing - GitHub threads#33,#35,#129,#134,#135. Fix: update the manager (APatch11219+added the WebUI package-manager API these UIs need), update the addon, or sidestep it entirely by installing the keybox overadbas in Phase 8. - The keybox is on the CRL. It "pulls" fine and verifies nothing. Fix: run
kbcheck.shfrom Phase 8 before trusting any keybox. Note the two traps in that section - unwrapped base64 and stripped leading zeros - both of which make a naive check report "live" for a revoked key.
If the keybox is live and still nothing changes, the problem is not the keybox. Check whether the device is RKP-only - see the next section for the one command that tells you.
RKP-only devices#
Some devices ship with no factory-provisioned attestation keys at all and source them from Google's Remote Key Provisioning service instead. There is no real leaf certificate to patch, and DroidGuard can mint fresh RKP-provisioned attest keys per integrity check - keys bound to the real, unlocked device. The result is MEETS_BASIC_INTEGRITY no matter how good your keybox is.
Check, do not guess which camp your device is in. The upstream reports are narrower than the folklore: Pixel 10 Pro and devices launching with Android 16 are the ones breaking (TEESimulator #224, TrickyStoreOSS #45), while Pixel 8 and 8a in the same threads work fine. Ask the device:
adb shell 'getprop remote_provisioning.tee.rkp_only; \
getprop remote_provisioning.strongbox.rkp_only; \
getprop persist.device_config.remote_key_provisioning_native.enable_rkpd'An empty value means the device does not define that knob at all. true or 1 on a level means that level has no batch-key fallback, and this section applies to you.
Symptoms: teeBroken=true, OUT_OF_KEYS, Failed to get rkpd key, No system services were found hosting com.android.rkpdapp.IRemoteProvisioning, or a log line saying remote provisioning was not denied because denial would fail key generation on an rkp-only level.
TEESimulator v4's hook reads the two rkp_only properties and never writes them - a global write would itself be a detection point. On a level where rkp_only is true it does not deny the app's provisioning lookup, because denying it makes generateKey fail outright rather than fall back. The real, hardware-bound attest key can still reach the app.
What it gives you instead is three switches, surfaced on the WebUI's Keyboxes screen and only on devices that actually define them:
| Property | Persistent across reboot |
|---|---|
remote_provisioning.tee.rkp_only | no |
remote_provisioning.strongbox.rkp_only | no |
persist.device_config.remote_key_provisioning_native.enable_rkpd | yes (persist. prefix) |
Users on affected devices report STRONG only after switching the two rkp_only knobs off, and having to redo it after every reboot - that is open issue #244, with #270 proposing to persist them. The maintainer's working hypothesis is that only enable_rkpd matters, and that one already survives.
The per-level gating (#231) and the RKP component matching fix (#288) landed after the v4.0 tag (build 34), so the stable tag is behind on these devices. Use a canary.
Revolut shows "device tampered with" before login#
- NeoZygisk
denylist_enforce=1. - Revolut present in your TEESimulator profile
appslist (Track A) or intarget.txtwith?(Track B). - No network proxy module active.
Revolut fails after login UI#
Play Integrity verdict failing. Check the keybox is live (Phase 8) and that PIF's SECURITY_PATCH and your engine's patch level agree.
George 1007 "device does not meet safety requirements"#
In order:
- George installed in user 10 (work profile)? If user 0, reinstall to user 10.
- microG hardware-attestation toggle OFF (Phase 5)?
- Engine patch level exactly matches PIF's
SECURITY_PATCH? - Keybox live, not revoked?
George crashes immediately on launch#
Installed in user 0 - move to user 10.
Verdict was DEVICE last week, BASIC now#
Two candidates, in this order: the keybox got revoked (check it), or PIF rotated to a fingerprint whose security patch no longer matches what your engine reports. Both are exactly what Specter's scheduler exists to prevent.
# PIF's current value
adb shell 'su -c "grep SECURITY_PATCH /data/adb/modules/playintegrityfix/pif.prop"'
# Track B's value
adb shell 'su -c "cat /data/adb/tricky_store/security_patch.txt"'
# Track A: read patchLevel out of the profile
adb shell 'su -c "cat /data/adb/teesim/config.json"'McDonald's "must be installed from Google Play"#
Aurora Store wasn't using Root installer when McDonald's was installed. Uninstall, then reinstall via Aurora with Root installer enabled.
McDonald's "can only run from primary workspace"#
You installed it in work profile. Reinstall via Aurora (which installs to user 0).
microG SafetyNet self-check fails#
Google killed the legacy endpoint. Expected, ignore. Apps that matter use Play Integrity API.
Play Integrity API Checker returns -100#
microG quirk with the checker's hardcoded cloudProjectNumber. Not a useful test on microG. Use the actual target app.
Push notifications not working#
microG Settings -> enable Cloud Messaging. If still broken, ensure microG GmsCore is up to date (Phase 4).
Apps crash asking for Google Play Services#
microG Self-Check should pass all items (except SafetyNet). Re-verify Phase 4 microG update.
Everything is wedged and I want a clean keystore#
adb shell 'su -c "kill $(pidof keystore2)"'A fresh daemon starts with no interception until the module re-injects. Cheaper than a reboot and much cheaper than a reflash.
Maintenance schedule#
- With Specter: nothing on a calendar. It rotates the keybox daily, refreshes PIF daily, and picks up new apps within minutes. You intervene when an app complains or a notification says the CRL grew.
- Without Specter: check the keybox weekly, run
kbcheck.sh, rotate when it goes red. Re-align the security patch after every PIF fingerprint rotation. - Monthly:
https://github.com/microg/GmsCore/releasesfor microG updates - Droidify handles this once the microG repo is added. - Per-module: MMRL tracks updates for installed modules. On an RKP-only device, watch TEESimulator canaries specifically.
- Per-app: nothing. Aurora's Root installer handles installer-source spoofing for new installs.