#!/system/bin/sh # Driver Spoofing System # # Makes Android think stock drivers are loaded while custom drivers # are actually running. Uses mount namespace isolation so: # # - Verification tools see: stock file (original hash, signature, SELinux context) # - Driver loader sees: custom file (our patched/modified driver) # # How it works: # 1. Stock driver stays at /vendor/lib64/... untouched (dm-verity happy) # 2. Custom driver lives in /data/adb/modules/driver-manager/drivers/ # 3. We clone the stock file's metadata (timestamps, SELinux context, owner, perms) # onto the custom driver # 4. We bind-mount the custom driver over the stock path ONLY in the mount # namespace of the process that loads it (e.g. surfaceflinger, wpa_supplicant) # 5. All other processes (Play Integrity, banking apps, SafetyNet) see the # stock file at the original path with the original hash # # This is NOT file replacement. The stock file is never modified. # dm-verity remains intact. Verified boot passes. MODDIR="/data/adb/modules/driver-manager" CONFDIR="$MODDIR/config" LOGFILE="$MODDIR/driver-manager.log" DRIVERDIR="$MODDIR/drivers" STOCKDIR="$MODDIR/drivers/.stock_meta" mkdir -p "$DRIVERDIR" "$STOCKDIR" mlog() { STEALTH=$(cat "$CONFDIR/stealth_mode" 2>/dev/null || echo "off") [ "$STEALTH" = "full" ] && return echo "$(date '+%Y-%m-%d %H:%M:%S') [spoof] $1" >> "$LOGFILE" } # ================================================================= # Clone stock file metadata onto custom driver # ================================================================= # Copies: SELinux context, ownership, permissions, timestamps # Does NOT copy file contents — that's the whole point clone_metadata() { STOCK_PATH="$1" CUSTOM_PATH="$2" if [ ! -f "$STOCK_PATH" ] || [ ! -f "$CUSTOM_PATH" ]; then mlog "ERROR: clone_metadata missing file: $STOCK_PATH or $CUSTOM_PATH" return 1 fi # Save stock metadata for verification METAFILE="$STOCKDIR/$(echo "$STOCK_PATH" | tr '/' '_')" ls -laZ "$STOCK_PATH" > "$METAFILE" 2>/dev/null sha256sum "$STOCK_PATH" >> "$METAFILE" 2>/dev/null # Clone SELinux context CONTEXT=$(ls -Z "$STOCK_PATH" 2>/dev/null | awk '{print $1}') if [ -n "$CONTEXT" ]; then chcon "$CONTEXT" "$CUSTOM_PATH" 2>/dev/null mlog "SELinux context: $CONTEXT -> $(basename "$CUSTOM_PATH")" fi # Clone ownership OWNER=$(stat -c '%u:%g' "$STOCK_PATH" 2>/dev/null) if [ -n "$OWNER" ]; then chown "$OWNER" "$CUSTOM_PATH" 2>/dev/null fi # Clone permissions PERMS=$(stat -c '%a' "$STOCK_PATH" 2>/dev/null) if [ -n "$PERMS" ]; then chmod "$PERMS" "$CUSTOM_PATH" 2>/dev/null fi # Clone timestamps (access + modify) touch -r "$STOCK_PATH" "$CUSTOM_PATH" 2>/dev/null mlog "Metadata cloned: $STOCK_PATH -> $CUSTOM_PATH" } # ================================================================= # Bind mount custom driver over stock path in a specific process # ================================================================= # Uses nsenter to enter the target process's mount namespace # and bind-mount the custom file over the stock path. # Only that process (and its children) see the custom file. spoof_for_process() { PROCESS_NAME="$1" STOCK_PATH="$2" CUSTOM_PATH="$3" # Find the PID of the target process PID=$(pidof "$PROCESS_NAME" 2>/dev/null) if [ -z "$PID" ]; then mlog "Process not running: $PROCESS_NAME" return 1 fi # Clone metadata first clone_metadata "$STOCK_PATH" "$CUSTOM_PATH" # Enter the process's mount namespace and bind-mount nsenter -t "$PID" -m -- mount --bind "$CUSTOM_PATH" "$STOCK_PATH" 2>/dev/null RET=$? if [ $RET -eq 0 ]; then mlog "Spoofed: $PROCESS_NAME (PID $PID) sees $CUSTOM_PATH at $STOCK_PATH" else mlog "nsenter failed for $PROCESS_NAME — falling back to global mount" # Fallback: global bind mount (less stealthy but works) mount --bind "$CUSTOM_PATH" "$STOCK_PATH" 2>/dev/null mlog "Global bind mount: $CUSTOM_PATH -> $STOCK_PATH" fi } # ================================================================= # Global spoof — bind mount for ALL processes # ================================================================= # Less stealthy but simpler. Use when you don't care about # hiding from verification tools (e.g. custom ROM, no banking apps) spoof_global() { STOCK_PATH="$1" CUSTOM_PATH="$2" clone_metadata "$STOCK_PATH" "$CUSTOM_PATH" mount --bind "$CUSTOM_PATH" "$STOCK_PATH" 2>/dev/null if [ $? -eq 0 ]; then mlog "Global spoof: $CUSTOM_PATH -> $STOCK_PATH" else mlog "ERROR: global mount failed for $STOCK_PATH" fi } # ================================================================= # Restore stock driver (unmount bind) # ================================================================= restore_stock() { STOCK_PATH="$1" umount "$STOCK_PATH" 2>/dev/null mlog "Restored stock: $STOCK_PATH" } # ================================================================= # Verify spoof is active # ================================================================= # Checks if the file at the stock path is actually our custom driver verify_spoof() { STOCK_PATH="$1" CUSTOM_PATH="$2" STOCK_HASH=$(sha256sum "$STOCK_PATH" 2>/dev/null | awk '{print $1}') CUSTOM_HASH=$(sha256sum "$CUSTOM_PATH" 2>/dev/null | awk '{print $1}') if [ "$STOCK_HASH" = "$CUSTOM_HASH" ]; then echo "ACTIVE — custom driver loaded at $STOCK_PATH" else echo "INACTIVE — stock driver at $STOCK_PATH" fi } # ================================================================= # Driver mapping configuration # ================================================================= # Format: stock_path|custom_filename|target_process # Custom files go in /data/adb/modules/driver-manager/drivers/ DRIVER_MAP="$CONFDIR/driver_map.conf" load_driver_map() { if [ ! -f "$DRIVER_MAP" ]; then cat > "$DRIVER_MAP" << 'MAP' # Driver Spoof Map # Format: stock_path|custom_filename|target_process|spoof_type # spoof_type: process (per-process ns) or global (all processes) # # GPU — PowerVR DXT-48-1536 # Place custom GPU driver as: drivers/libGLES_powervr_custom.so #/vendor/lib64/egl/libGLES_powervr.so|libGLES_powervr_custom.so|surfaceflinger|process #/vendor/lib64/libPVROCL.so|libPVROCL_custom.so|surfaceflinger|process # # WiFi — BCM4390 firmware # Place custom firmware as: drivers/fw_bcm4390_custom.bin #/vendor/firmware/fw_bcmdhd4390.bin|fw_bcm4390_custom.bin|wpa_supplicant|process # # Bluetooth — QCA firmware #/vendor/firmware/qca/nvm_00440200.bin|nvm_custom.bin|bluetooth|process # # Uncomment and edit lines above to activate spoofing for each driver. # The stock file is NEVER modified. Custom files must be placed in: # /data/adb/modules/driver-manager/drivers/ MAP mlog "Created default driver map at $DRIVER_MAP" fi } # ================================================================= # Apply all configured spoofs # ================================================================= apply_all() { load_driver_map while IFS='|' read -r STOCK_PATH CUSTOM_FILE TARGET_PROC SPOOF_TYPE; do # Skip comments and empty lines case "$STOCK_PATH" in \#*|"") continue ;; esac CUSTOM_PATH="$DRIVERDIR/$CUSTOM_FILE" if [ ! -f "$CUSTOM_PATH" ]; then mlog "SKIP: custom driver not found: $CUSTOM_PATH" continue fi if [ ! -f "$STOCK_PATH" ]; then mlog "SKIP: stock path not found: $STOCK_PATH" continue fi case "$SPOOF_TYPE" in process) spoof_for_process "$TARGET_PROC" "$STOCK_PATH" "$CUSTOM_PATH" ;; global) spoof_global "$STOCK_PATH" "$CUSTOM_PATH" ;; *) mlog "Unknown spoof type: $SPOOF_TYPE for $STOCK_PATH" ;; esac done < "$DRIVER_MAP" } # ================================================================= # Status — show all active spoofs # ================================================================= show_status() { load_driver_map echo "=== Driver Spoof Status ===" while IFS='|' read -r STOCK_PATH CUSTOM_FILE TARGET_PROC SPOOF_TYPE; do case "$STOCK_PATH" in \#*|"") continue ;; esac CUSTOM_PATH="$DRIVERDIR/$CUSTOM_FILE" STATUS=$(verify_spoof "$STOCK_PATH" "$CUSTOM_PATH") echo " $STOCK_PATH -> $CUSTOM_FILE [$TARGET_PROC] $STATUS" done < "$DRIVER_MAP" echo "" echo "=== Mount binds ===" mount | grep "$DRIVERDIR" 2>/dev/null || echo " (none active)" } # ================================================================= # Main # ================================================================= case "$1" in apply) apply_all ;; restore) if [ -n "$2" ]; then restore_stock "$2" else # Restore all load_driver_map while IFS='|' read -r STOCK_PATH CUSTOM_FILE TARGET_PROC SPOOF_TYPE; do case "$STOCK_PATH" in \#*|"") continue ;; esac restore_stock "$STOCK_PATH" done < "$DRIVER_MAP" fi ;; status) show_status ;; clone) # Clone metadata only: driver_spoof.sh clone /vendor/path /custom/path clone_metadata "$2" "$3" ;; verify) verify_spoof "$2" "$3" ;; *) echo "Usage: driver_spoof.sh {apply|restore|status|clone|verify}" echo "" echo " apply Apply all driver spoofs from driver_map.conf" echo " restore [path] Restore stock driver(s)" echo " status Show active spoofs" echo " clone src dst Clone file metadata (SELinux, perms, timestamps)" echo " verify stock cust Check if spoof is active" echo "" echo "Driver map: $DRIVER_MAP" echo "Custom drivers: $DRIVERDIR/" ;; esac