Newer
Older
Hardware / FaultInjection / examples / CuriousBolt / Level-1 / glitch-o-matic.py
  1. import serial
  2. import time
  3. import sys
  4. import os
  5. from tabulate import tabulate
  6. from scope import Scope
  7. from collections import deque
  8.  
  9. # Serial port settings
  10. SERIAL_PORT = "/dev/ttyUSB0"
  11. BAUD_RATE = 115200
  12. TIMEOUT = 2
  13.  
  14. # Glitch configuration limits
  15. INCREMENT_LEN = 1
  16. LOWER_GLITCH_LEN = 41
  17. UPPER_GLITCH_LEN = 60
  18.  
  19. INCREMENT_REPEAT = 1
  20. LOWER_GLITCH_REPEAT = 1
  21. UPPER_GLITCH_REPEAT = 30
  22.  
  23. INCREMENT_DELAY = 5
  24. LOWER_DELAY_TIME = 0
  25. UPPER_DELAY_TIME = 30
  26.  
  27. message_history = deque(maxlen=20)
  28.  
  29. def restartDeviceAndChall():
  30. s.io.add(0, 0, delay=20000000)
  31. s.io.add(0, 1, delay=20000000)
  32. s.io.upload()
  33. s.trigger()
  34. time.sleep(5)
  35. s.io.add(1, 1, delay=30000000)
  36. s.io.add(1, 0, delay=30000000)
  37. s.io.upload()
  38. s.trigger()
  39. time.sleep(5)
  40.  
  41. def restartChall():
  42. s.io.add(1, 1, delay=30000000)
  43. s.io.add(1, 0, delay=30000000)
  44. s.io.upload()
  45. s.trigger()
  46. time.sleep(5)
  47.  
  48. def clear_console():
  49. os.system('cls' if os.name == 'nt' else 'clear')
  50.  
  51. def store_message(message):
  52. message_history.append(message)
  53.  
  54. def print_info(message):
  55. store_message(f"[INFO] {message}")
  56.  
  57. def print_warning(message):
  58. store_message(f"[WARNING] {message}")
  59.  
  60. def print_error(message):
  61. store_message(f"[ERROR] {message}")
  62.  
  63. def print_last_x_messages(x):
  64. # Ensure we print only the last 'x' messages, or all if less than x
  65. for msg in list(message_history)[-x:]:
  66. print(msg)
  67.  
  68. def format_elapsed_time(seconds):
  69. days = seconds // (24 * 3600)
  70. hours = (seconds % (24 * 3600)) // 3600
  71. minutes = (seconds % 3600) // 60
  72. seconds = seconds % 60
  73. return f"{int(days)}d {int(hours)}h {int(minutes)}m {int(seconds)}s"
  74.  
  75. def print_table(
  76. glitch_len, trigger_repeats, delay_time, elapsed_time):
  77. headers = ["Glitch Len", "Repeats", "Delay", "Elapsed Time"]
  78. data = [[f"{glitch_len} / {UPPER_GLITCH_LEN}",
  79. f"{trigger_repeats} / {UPPER_GLITCH_REPEAT}",
  80. f"{delay_time} / {UPPER_DELAY_TIME}",
  81. elapsed_time]]
  82.  
  83. clear_console()
  84. print_banner()
  85. print(tabulate(data, headers=headers, tablefmt="fancy_grid"))
  86.  
  87. def connect_serial():
  88. try:
  89. ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=TIMEOUT)
  90. print_info("Connected to serial port.")
  91. time.sleep(1)
  92. ser.flushInput()
  93. version_info = ser.readline().decode("utf-8", errors="ignore").strip()
  94.  
  95. if version_info:
  96. print_info(f"Connected to version: {version_info}")
  97. else:
  98. print_warning("No version information received. Device might be unresponsive.")
  99.  
  100. return ser
  101. except serial.SerialException as e:
  102. print_error(f"Could not open serial port {SERIAL_PORT}: {e}")
  103. sys.exit(1)
  104.  
  105. def read_serial():
  106. global glitch_len, trigger_repeats, delay_time
  107. global UPPER_GLITCH_LEN, LOWER_GLITCH_LEN, INCREMENT_LEN
  108. global UPPER_GLITCH_REPEAT, LOWER_GLITCH_REPEAT, INCREMENT_REPEAT
  109. global UPPER_DELAY_TIME, LOWER_DELAY_TIME, INCREMENT_DELAY
  110. glitch_len = LOWER_GLITCH_LEN
  111. trigger_repeats = LOWER_GLITCH_REPEAT
  112. delay_time = LOWER_DELAY_TIME
  113. start_time = time.time()
  114.  
  115. last_restart_time = time.time()
  116. restart_interval = 600 # 600 secs = 10 min
  117.  
  118. ser = connect_serial()
  119. print_info("Restarting device and challenge")
  120. #restartDeviceAndChall()
  121. while True:
  122. cycle_start_time = time.time()
  123. line = ""
  124.  
  125. while time.time() - cycle_start_time < TIMEOUT:
  126. if ser.in_waiting > 0:
  127. char = ser.read().decode("utf-8", errors="ignore")
  128. line += char
  129. if char == '\n':
  130. break
  131.  
  132. if line:
  133. line = line.strip()
  134. print_info(f"Received data: {line}")
  135.  
  136. line_lower = line.lower()
  137.  
  138. if "ctf" in line_lower:
  139. print_info(f"Flag: {line}")
  140. print_warning("Received 'ctf', exiting...")
  141. print_table(glitch_len, trigger_repeats, delay_time, elapsed_time)
  142. print_last_x_messages(10)
  143. sys.exit()
  144. elif "starting challenge" in line_lower:
  145. print_info("Detected 'Starting Challenge'. Resetting glitch repeat count.")
  146. if (glitch_len + trigger_repeats) % 2 == 0:
  147. #UPPER_GLITCH_REPEAT = trigger_repeats
  148. trigger_repeats -= INCREMENT_REPEAT
  149. glitch_len += INCREMENT_LEN
  150. else:
  151. UPPER_GLITCH_LEN = glitch_len
  152. glitch_len -= INCREMENT_LEN
  153. trigger_repeats += INCREMENT_REPEAT
  154.  
  155. elif "hold" in line_lower:
  156. print_info("Detected 'Hold'. Restarting Challenge.")
  157. #restartChall()
  158.  
  159. else:
  160. execute_scope_script(glitch_len, trigger_repeats, delay_time)
  161.  
  162. # 1. Increment delay time first
  163. if delay_time < UPPER_DELAY_TIME:
  164. delay_time += INCREMENT_DELAY
  165. else:
  166. delay_time = LOWER_DELAY_TIME # Reset delay time
  167.  
  168. # 2. Alternate between glitch_len and trigger_repeats when delay resets
  169. if (glitch_len + trigger_repeats) % 2 == 0:
  170. if glitch_len < UPPER_GLITCH_LEN:
  171. glitch_len += INCREMENT_LEN
  172. print_info(f"Incrementing glitch length: {glitch_len}")
  173. elif (glitch_len > UPPER_GLITCH_LEN):
  174. UPPER_GLITCH_LEN += INCREMENT_LEN
  175. else:
  176. glitch_len = LOWER_GLITCH_LEN # Reset glitch length
  177. trigger_repeats += INCREMENT_REPEAT # Increment trigger repeats
  178. print_info(f"Glitch length reset. Incrementing trigger repeats: {trigger_repeats}")
  179. else:
  180. if trigger_repeats < UPPER_GLITCH_REPEAT:
  181. trigger_repeats += INCREMENT_REPEAT
  182. print_info(f"Incrementing trigger repeats: {trigger_repeats}")
  183. else:
  184. if(glitch_len == UPPER_GLITCH_LEN):
  185. trigger_repeats = LOWER_GLITCH_REPEAT # Reset trigger repeats
  186. else:
  187. trigger_repeats = LOWER_GLITCH_REPEAT
  188. glitch_len += INCREMENT_LEN # Increment glitch length
  189. print_info(f"Trigger repeats reset. Incrementing glitch length: {glitch_len}")
  190.  
  191.  
  192. elapsed_time = format_elapsed_time(time.time() - start_time)
  193. print_table(glitch_len, trigger_repeats, delay_time, elapsed_time)
  194. # To print the last 3 messages
  195. print_last_x_messages(10)
  196.  
  197. if time.time() - last_restart_time >= restart_interval:
  198. print_info(f"10 min mark. Setting glitch length: 80 and restarting device")
  199. UPPER_GLITCH_LEN = 80
  200. #restartDeviceAndChall()
  201. last_restart_time = time.time()
  202.  
  203. def execute_scope_script(glitch_len, trigger_repeats, delay):
  204. s.glitch.repeat = glitch_len
  205. s.glitch.ext_offset = delay
  206. for _ in range(trigger_repeats):
  207. s.trigger()
  208.  
  209. def print_banner():
  210. print(" ___ _ _ _ _ _ _ ")
  211. print(" / __| (_) |_ __| |_ ___ ___ ___ _ __ __ _| |_(_)__ ")
  212. print(" | (_ | | | _/ _| ' \\___/ _ \\___| ' \\/ _` | _| / _|")
  213. print(" \\___|_|_|\\__\\__|_||_| \\___/ |_|_|_\\__,_|\\__|_\\__|")
  214.  
  215. if __name__ == "__main__":
  216. print_info("Starting Program")
  217. s = Scope()
  218. read_serial()
Buy Me A Coffee