From d0061b82bb3c93f2d276ad6e0aa64e121b49a708 Mon Sep 17 00:00:00 2001 From: sssnake Date: Tue, 31 Mar 2026 10:01:31 -0700 Subject: [PATCH] Add boot timing and AVB/Play Integrity evasion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Boot timing system defers all modifications until after Play Integrity first attestation completes. Monitors DroidGuard (com.google.android.gms.unstable) CPU activity to detect attestation window. PI watcher daemon auto-hides mods during periodic re-checks — unmounts spoofs, removes non-stock props, ensures boot state reads green/locked/enforcing, then re-applies after check finishes. post-fs-data.sh cleaned to only set stock-safe props during early boot. KernelSU version props hidden. WebUI boot timing panel with hide/unhide controls. --- customize.sh | 1 + driver-manager-v1.0.0.zip | Bin 39009 -> 43672 bytes post-fs-data.sh | 36 +++-- scripts/boot_timing.sh | 295 ++++++++++++++++++++++++++++++++++++++ service.sh | 31 +++- webroot/index.html | 66 +++++++++ 6 files changed, 418 insertions(+), 11 deletions(-) create mode 100755 scripts/boot_timing.sh diff --git a/customize.sh b/customize.sh index af7cde5..d6e1b72 100644 --- a/customize.sh +++ b/customize.sh @@ -41,6 +41,7 @@ echo "auto" > "$MODPATH/config/gamepad_mode" echo "off" > "$MODPATH/config/decoder_mode" echo "off" > "$MODPATH/config/stealth_mode" echo "0" > "$MODPATH/config/spoof_enabled" +echo "0" > "$MODPATH/config/boot_timing" echo "100.0M" > "$MODPATH/config/fm_freq" echo "24M:1800M" > "$MODPATH/config/spectrum_range" diff --git a/driver-manager-v1.0.0.zip b/driver-manager-v1.0.0.zip index cc6b8867a2440322843e083bbc1adfb4a506259d..6036a643715517277f48c2246db2d41349d9c4ce 100644 GIT binary patch delta 18712 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 ofuc?)%s#uBhpLU-?!| zn?pGUWWDL$?{$=Lf73)M?HeP9j>UUNlnot6pR|v|uP=c^3!lB=36hT-Igij^ABkNK z(BqrbG2kq`w2}Q4hBe90n5I%&Fd5UqdhhG5WR(aNkAma-JMh)l#~n^b;lYe;OXfbF zhPu28gu6AE!i{fCk87UvcyZci$i)n^40Su>t58_01@5yj!?v7$_AqVZ!OiE4D;F18 zD916+TfC&p>gus2JM;bD1_IX0)Bdel!;i@<0s^RUHjhLciJ&={N6?qSULKC97iLmte+av|16S9 zsxG7eLcaY|Ate5v)d~OrGT}2WS;{1PHJijIxmXjvgmf->Uc#|T^)PU_0Nqc45KtJUq zfpR@yoK8|sxhnXh8zAX2oG=N!LI_+f5RfGI3oFT{f(Qu%fB`uC2bX!me?b2)w9AQ- diff --git a/post-fs-data.sh b/post-fs-data.sh index 5eaa9e9..546a281 100755 --- a/post-fs-data.sh +++ b/post-fs-data.sh @@ -1,17 +1,37 @@ #!/system/bin/sh # Driver Manager - post-fs-data -# Early boot: set core driver properties before services start +# EARLY BOOT — runs before verification checks +# +# IMPORTANT: Keep this CLEAN. Only set props that already exist +# on stock or that won't trigger root/mod detection. +# All custom/non-stock props are deferred to service.sh (after PI). MODDIR=${0%/*} +CONFDIR="$MODDIR/config" -# GPU — PowerVR latest driver hints +# GPU — these are stock props, safe to set early resetprop ro.hardware.egl powervr resetprop ro.hardware.vulkan powervr -resetprop graphics.gpu.profiler.support true -# OpenCL compute -resetprop vendor.powervr.opencl.allowfp16 1 -resetprop vendor.powervr.opencl.profiling 1 +# Boot state — ensure these look locked/verified from the start +# These are checked by early-running verification services +BOOT_TIMING=$(cat "$CONFDIR/boot_timing" 2>/dev/null || echo "0") +if [ "$BOOT_TIMING" = "1" ]; then + resetprop ro.boot.verifiedbootstate green + resetprop ro.boot.flash.locked 1 + resetprop ro.boot.vbmeta.device_state locked + resetprop ro.boot.veritymode enforcing + resetprop ro.build.selinux 1 -# USB OTG — required for SDR dongles, HackRF, game controllers -resetprop persist.sys.usb.otg 1 + # Hide KernelSU props if they exist + resetprop --delete ro.kernelsu.version 2>/dev/null + resetprop --delete ro.kernelsu.versionCode 2>/dev/null +fi + +# DO NOT set these during early boot — they're non-stock: +# vendor.powervr.opencl.allowfp16 +# vendor.powervr.opencl.profiling +# persist.sys.usb.otg +# input.gamepad.enabled +# bluetooth.le.no_location_permission_scan +# These are applied later by service.sh or boot_timing.sh diff --git a/scripts/boot_timing.sh b/scripts/boot_timing.sh new file mode 100755 index 0000000..73b6b89 --- /dev/null +++ b/scripts/boot_timing.sh @@ -0,0 +1,295 @@ +#!/system/bin/sh +# Boot Timing & Verification Evasion +# +# Controls WHEN custom drivers and modifications are applied relative +# to Android's verification checkpoints: +# +# 1. AVB (Android Verified Boot) — bootloader, before kernel +# KernelSU handles this. We don't touch partitions. PASS. +# +# 2. dm-verity — block-level hash verification +# KernelSU overlays are above dm-verity. Stock blocks untouched. PASS. +# +# 3. Play Integrity / SafetyNet — after boot, runs in GMS process +# This is what we need to time around. First check is ~10-30s +# after boot_completed. Periodic re-checks every few hours. +# +# 4. Banking apps / root detectors — check on app launch +# These read props, scan /proc, check mount points. +# +# Strategy: +# - post-fs-data: ONLY stock-safe props. No mods. No spoofs. +# - boot_completed: Wait for first PI attestation to finish +# - Apply mods AFTER attestation window closes +# - Run a watcher that detects PI re-checks and temporarily +# unmounts spoofs + restores stock props during the check + +MODDIR="/data/adb/modules/driver-manager" +CONFDIR="$MODDIR/config" +LOGFILE="$MODDIR/driver-manager.log" + +mlog() { + STEALTH=$(cat "$CONFDIR/stealth_mode" 2>/dev/null || echo "off") + [ "$STEALTH" = "full" ] && return + echo "$(date '+%Y-%m-%d %H:%M:%S') [boot_timing] $1" >> "$LOGFILE" +} + +# ================================================================= +# Phase 1: Detect when Play Integrity has completed first check +# ================================================================= +# GMS runs attestation via com.google.android.gms.unstable +# DroidGuard collects device state in this window +# We watch for this process to start and finish + +wait_for_pi_pass() { + mlog "Waiting for Play Integrity first attestation..." + + # Wait for GMS to be fully running + TIMEOUT=120 + ELAPSED=0 + while [ $ELAPSED -lt $TIMEOUT ]; do + # Check if GMS unstable (DroidGuard) has started + GMS_PID=$(pidof com.google.android.gms.unstable 2>/dev/null) + if [ -n "$GMS_PID" ]; then + mlog "DroidGuard detected (PID $GMS_PID), waiting for completion..." + + # Wait for the DroidGuard process to finish its attestation + # It typically runs for 5-15 seconds during initial check + DROID_WAIT=0 + while [ $DROID_WAIT -lt 30 ]; do + sleep 1 + DROID_WAIT=$((DROID_WAIT + 1)) + + # Check if it's still actively doing attestation + # DroidGuard CPU usage drops after attestation completes + if [ -d "/proc/$GMS_PID" ]; then + CPU=$(cat /proc/$GMS_PID/stat 2>/dev/null | awk '{print $14+$15}') + if [ -n "$CPU" ] && [ "$CPU" -lt 5 ] && [ $DROID_WAIT -gt 10 ]; then + mlog "DroidGuard idle after ${DROID_WAIT}s — attestation likely complete" + break + fi + else + mlog "DroidGuard process exited after ${DROID_WAIT}s" + break + fi + done + + # Extra safety margin + sleep 5 + mlog "PI attestation window closed" + return 0 + fi + + sleep 2 + ELAPSED=$((ELAPSED + 2)) + done + + # If GMS never started (unlikely), just wait a safe fixed time + mlog "GMS not detected after ${TIMEOUT}s — using fixed delay" + sleep 30 + return 0 +} + +# ================================================================= +# Phase 2: Apply modifications after PI passes +# ================================================================= +apply_after_pi() { + mlog "Applying modifications..." + + # Apply driver spoofs + SPOOF_ENABLED=$(cat "$CONFDIR/spoof_enabled" 2>/dev/null || echo "0") + if [ "$SPOOF_ENABLED" = "1" ]; then + sh "$MODDIR/scripts/driver_spoof.sh" apply + mlog "Driver spoofs applied" + fi + + # Apply stealth + STEALTH_MODE=$(cat "$CONFDIR/stealth_mode" 2>/dev/null || echo "off") + if [ "$STEALTH_MODE" != "off" ]; then + mlog "Stealth mode active: $STEALTH_MODE" + fi + + # Set non-stock props that we held back during PI window + # These are the props that root detectors look for + resetprop input.gamepad.enabled true + resetprop persist.sys.usb.otg 1 + + mlog "All modifications applied" +} + +# ================================================================= +# Phase 3: PI Watcher — monitor for re-attestation and hide +# ================================================================= +# Play Integrity can re-check periodically (every few hours) or +# when an app requests it (banking app launch, Google Pay, etc.) +# We watch for DroidGuard activity and temporarily go clean. + +PI_WATCHER_PID="" + +start_pi_watcher() { + mlog "Starting PI watcher daemon..." + + ( + while true; do + sleep 10 + + # Check if DroidGuard is doing a new attestation + GMS_PID=$(pidof com.google.android.gms.unstable 2>/dev/null) + if [ -z "$GMS_PID" ]; then + continue + fi + + # Check if it's actively using CPU (attestation in progress) + CPU=$(cat /proc/$GMS_PID/stat 2>/dev/null | awk '{print $14+$15}') + PREV_CPU="$CPU" + sleep 2 + CPU2=$(cat /proc/$GMS_PID/stat 2>/dev/null | awk '{print $14+$15}') + + if [ -n "$CPU" ] && [ -n "$CPU2" ]; then + DELTA=$((CPU2 - CPU)) + if [ "$DELTA" -gt 10 ]; then + # DroidGuard is active — temporarily hide + mlog "PI re-check detected! Temporarily restoring stock..." + hide_for_pi + fi + fi + done + ) & + PI_WATCHER_PID=$! + echo "$PI_WATCHER_PID" > "$MODDIR/run/pi_watcher.pid" + mlog "PI watcher started (PID $PI_WATCHER_PID)" +} + +hide_for_pi() { + # Temporarily unmount all driver spoofs + sh "$MODDIR/scripts/driver_spoof.sh" restore 2>/dev/null + + # Remove non-stock props + resetprop --delete input.gamepad.enabled 2>/dev/null + resetprop --delete persist.sys.usb.otg 2>/dev/null + resetprop --delete vendor.powervr.opencl.allowfp16 2>/dev/null + resetprop --delete vendor.powervr.opencl.profiling 2>/dev/null + resetprop --delete bluetooth.le.no_location_permission_scan 2>/dev/null + + # Ensure boot state looks clean + resetprop ro.boot.verifiedbootstate green 2>/dev/null + resetprop ro.boot.flash.locked 1 2>/dev/null + resetprop ro.boot.vbmeta.device_state locked 2>/dev/null + + mlog "Hiding for PI check..." + + # Wait for DroidGuard to finish + WAIT=0 + while [ $WAIT -lt 60 ]; do + sleep 2 + WAIT=$((WAIT + 2)) + + GMS_PID=$(pidof com.google.android.gms.unstable 2>/dev/null) + if [ -z "$GMS_PID" ]; then + break + fi + + CPU=$(cat /proc/$GMS_PID/stat 2>/dev/null | awk '{print $14+$15}') + sleep 1 + CPU2=$(cat /proc/$GMS_PID/stat 2>/dev/null | awk '{print $14+$15}') + DELTA=$((CPU2 - CPU)) + + if [ "$DELTA" -lt 5 ]; then + break + fi + done + + # Extra safety margin + sleep 5 + + mlog "PI check finished, re-applying modifications..." + apply_after_pi +} + +# ================================================================= +# Boot prop spoofing — make boot state look locked/verified +# ================================================================= +spoof_boot_props() { + # These props are checked by Play Integrity and root detectors + # They should reflect a locked, verified device + + # Verified boot state + resetprop ro.boot.verifiedbootstate green + resetprop ro.boot.flash.locked 1 + resetprop ro.boot.vbmeta.device_state locked + resetprop ro.boot.veritymode enforcing + + # Remove KernelSU traces from props + resetprop --delete ro.kernelsu.version 2>/dev/null + resetprop --delete ro.kernelsu.versionCode 2>/dev/null + + # Stock build fingerprint (don't modify — just ensure it's not overridden) + # resetprop ro.build.fingerprint should already be stock + + # Ensure SELinux appears enforcing + resetprop ro.build.selinux 1 + + mlog "Boot props spoofed (green/locked/enforcing)" +} + +# ================================================================= +# Main entry point — called from service.sh +# ================================================================= +case "$1" in + run) + # Full boot timing sequence + spoof_boot_props + wait_for_pi_pass + apply_after_pi + start_pi_watcher + mlog "Boot timing sequence complete" + ;; + hide) + # Manual hide trigger + hide_for_pi + ;; + unhide) + # Manual re-apply + apply_after_pi + ;; + stop) + # Stop PI watcher + PID=$(cat "$MODDIR/run/pi_watcher.pid" 2>/dev/null) + if [ -n "$PID" ]; then + kill "$PID" 2>/dev/null + rm -f "$MODDIR/run/pi_watcher.pid" + mlog "PI watcher stopped" + fi + ;; + status) + PID=$(cat "$MODDIR/run/pi_watcher.pid" 2>/dev/null) + if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then + echo "PI watcher: running (PID $PID)" + else + echo "PI watcher: not running" + fi + + # Check boot props + echo "Boot state: $(getprop ro.boot.verifiedbootstate)" + echo "Flash lock: $(getprop ro.boot.flash.locked)" + echo "VBMeta: $(getprop ro.boot.vbmeta.device_state)" + echo "SELinux: $(getenforce 2>/dev/null || echo unknown)" + + # Check for KSU prop leaks + KSU_VER=$(getprop ro.kernelsu.version 2>/dev/null) + if [ -n "$KSU_VER" ]; then + echo "WARNING: KernelSU version visible: $KSU_VER" + else + echo "KernelSU props: hidden" + fi + ;; + *) + echo "Usage: boot_timing.sh {run|hide|unhide|stop|status}" + echo "" + echo " run Full boot sequence (wait for PI, apply mods, start watcher)" + echo " hide Temporarily hide all mods (for manual PI trigger)" + echo " unhide Re-apply all mods" + echo " stop Stop PI watcher daemon" + echo " status Show current state" + ;; +esac diff --git a/service.sh b/service.sh index 1404c3f..fb3de02 100755 --- a/service.sh +++ b/service.sh @@ -39,6 +39,30 @@ GPU=$(getprop ro.hardware.egl) mlog "Boot complete. Device=$DEVICE SoC=$SOC Platform=$PLATFORM API=$API GPU=$GPU" +# ================================================================= +# BOOT TIMING — Wait for Play Integrity before applying mods +# ================================================================= +# If boot timing is enabled, we hand off to boot_timing.sh which: +# 1. Spoofs boot props (green/locked/enforcing) +# 2. Waits for first Play Integrity attestation to finish +# 3. THEN applies all our modifications +# 4. Starts a watcher that hides mods during future PI checks +# +# If disabled, mods apply immediately (faster but less stealthy) + +BOOT_TIMING=$(cat "$CONFDIR/boot_timing" 2>/dev/null || echo "0") + +if [ "$BOOT_TIMING" = "1" ]; then + mlog "Boot timing enabled — deferring mods until after PI attestation" + # Spoof boot props NOW (safe, just props) + sh "$MODDIR/scripts/boot_timing.sh" run & + TIMING_PID=$! + echo "$TIMING_PID" > "$MODDIR/run/boot_timing.pid" + mlog "Boot timing daemon started (PID $TIMING_PID)" + # The rest of this script still runs to set up configs, + # but the actual driver spoofs are deferred to boot_timing.sh +fi + # ============================================================ # GPU — PowerVR DXT-48-1536 (pvrsrvkm, native) # ============================================================ @@ -334,11 +358,12 @@ esac SPOOF_ENABLED=$(cat "$CONFDIR/spoof_enabled" 2>/dev/null || echo "0") -if [ "$SPOOF_ENABLED" = "1" ]; then - # Wait for target processes to be running +if [ "$SPOOF_ENABLED" = "1" ] && [ "$BOOT_TIMING" != "1" ]; then + # Apply immediately if boot timing is NOT handling it + # (boot_timing.sh applies spoofs after PI passes) sleep 5 sh "$MODDIR/scripts/driver_spoof.sh" apply - mlog "Driver spoofing applied" + mlog "Driver spoofing applied (immediate mode)" fi # ============================================================ diff --git a/webroot/index.html b/webroot/index.html index 743fde1..d1a6067 100644 --- a/webroot/index.html +++ b/webroot/index.html @@ -357,6 +357,40 @@ + +
+
Boot Timing / AVB Evasion
+
+
+
Boot Timing
+
Defer mods until after Play Integrity passes
+
+ +
+
+
+
PI Watcher
+
Auto-hide during re-attestation checks
+
+
+
+
+
+
Boot State
+
Verified boot props
+
+
+
+
+ + + +
+
+
Driver Spoofing
@@ -493,6 +527,37 @@ if (fmFreq) document.getElementById('fmFreq').value = fmFreq; } + async function bootAction(action) { + log('Boot timing: ' + action); + const r = await exec('sh ' + MODDIR + '/scripts/boot_timing.sh ' + action); + log(r.stdout.trim() || action + ' done'); + await loadBootStatus(); + } + + async function loadBootStatus() { + const timing = (await exec('cat ' + MODDIR + '/config/boot_timing 2>/dev/null')).stdout.trim(); + document.getElementById('bootTiming').value = timing || '0'; + + const dot = document.getElementById('bootDot'); + dot.className = 'dot' + (timing === '1' ? '' : ' off'); + + // PI watcher + const watcherPid = (await exec('cat ' + MODDIR + '/run/pi_watcher.pid 2>/dev/null')).stdout.trim(); + if (watcherPid) { + const alive = (await exec('kill -0 ' + watcherPid + ' 2>/dev/null && echo running || echo dead')).stdout.trim(); + document.getElementById('piWatcherStatus').textContent = alive === 'running' ? 'Active (PID ' + watcherPid + ')' : 'Dead'; + } else { + document.getElementById('piWatcherStatus').textContent = timing === '1' ? 'Will start on boot' : 'Disabled'; + } + + // Boot state + const vb = await gp('ro.boot.verifiedbootstate'); + const fl = await gp('ro.boot.flash.locked'); + const vbm = await gp('ro.boot.vbmeta.device_state'); + document.getElementById('bootState').textContent = + 'vboot=' + (vb || '?') + ' flash=' + (fl || '?') + ' vbmeta=' + (vbm || '?'); + } + async function spoofAction(action) { log('Spoof: ' + action); const r = await exec('sh ' + MODDIR + '/scripts/driver_spoof.sh ' + action); @@ -676,6 +741,7 @@ await loadSdrInfo(); await loadControllerInfo(); await loadRtlStatus(); + await loadBootStatus(); await loadSpoofStatus(); await loadStealthStatus(); log('Done');