← Back to Writeups
CUSTOMMediumHardware

Температурный саботаж (Temperature Sabotage)

XESXOR9/2/20263 min read
#hardware#custom#medium#hex_file_parsing#xor_bruteforce#zip_extraction#string_extraction

Температурный саботаж (Temperature Sabotage)

Platform: duckerz | Category: Hardware | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-01-09 | Status: Solved Techniques: hex_file_parsing, xor_bruteforce, zip_extraction, string_extraction

Summary

Files: - Температурный_саботаж.zip contains: - code.hex — Intel HEX firmware for ATmega32 - scada.pdsprj — Proteus project

Температурный саботаж (Temperature Sabotage) — duckerz

Description

Начальник цеха Алексей Петрович считает вашу работу 'смотрителя датчиков' бесполезной. "Современные сенсоры не врут!", — заявил он, хлопая толстым пальцем по вашему монитору. Сегодня у вас есть шанс доказать, что даже в идеальной системе найдётся место... творческому подходу.

(Схема создана в Proteus 8 Professional 8.17 SP4. HEX в архиве необходим для работы проекта. Его анализ не влияет на решение задания)

Files:

  • Температурный_саботаж.zip contains:
    • code.hex — Intel HEX firmware for ATmega32
    • scada.pdsprj — Proteus project ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Analysis

File Structure

  1. code.hex — standard Intel HEX format, contains microcontroller firmware
  2. scada.pdsprj — Proteus project (actually a ZIP archive)

Investigating the Proteus Project

The Proteus project is a ZIP archive. Upon extraction:

  • FIRMWARE/ATmega32/main.asm — assembly source code
  • ROOT.DSN — schematic with 4 LM75AD temperature sensors
  • Sensor values: 25.00, 79.00, 41.00, 18.00°C

HEX File Analysis

Despite the hint "HEX analysis doesn't affect the solution", interesting strings were found at the end of the file:

  • "Sensor : no response."
  • "ALERT! Error code: "
  • ". Temperature out of range."
  • Encoded bytes: 0617010907101839713471303b362a732c251d73311d172c2607301d21722c3630722e3f ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Decryption

The encoded bytes are XOR encrypted with a single-byte key.

Brute-forcing all possible keys (0x00-0xFF) revealed:

  • Key 0x42 (ASCII 'B') produces readable output
  • Decrypted text: DUCKERZ{REDACTED}

Solution

python
#!/usr/bin/env python3
"""
Temperature Sabotage - XOR decryption
duckerz CTF 2026
"""

# Encoded bytes from HEX file
encoded_hex = "0617010907101839713471303b362a732c251d73311d172c2607301d21722c3630722e3f"
encoded = bytes.fromhex(encoded_hex)

# Brute-force XOR with single byte
def xor_bruteforce(data):
    for key in range(256):
        decoded = bytes([b ^ key for b in data])
        try:
            text = decoded.decode('ascii')
            # Check for flag format
            if 'DUCKERZ{' in text or text.isprintable():
                print(f"Key 0x{key:02X} ({chr(key) if 32 <= key < 127 else '?'}): {text}")
        except:
            pass
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Known key
key = 0x42  # 'B'
decoded = bytes([b ^ key for b in encoded])
print(f"Flag: {decoded.decode()}")

Alternative Method — Extraction from HEX

python
#!/usr/bin/env python3
"""
Intel HEX parsing and hidden data extraction
"""

def parse_intel_hex(filename):
    """Extract data from Intel HEX file"""
    data = bytearray()
    
    with open(filename, 'r') as f:
        for line in f:
            line = line.strip()
            if not line.startswith(':'):
                continue
            
            byte_count = int(line[1:3], 16)
            record_type = int(line[7:9], 16)
            
            # Type 00 = data
            if record_type == 0x00:
                hex_data = line[9:9 + byte_count * 2]
                data.extend(bytes.fromhex(hex_data))
    
    return bytes(data)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

def find_strings(data, min_length=4):
    """Find ASCII strings in binary data"""
    strings = []
    current = ""
    
    for byte in data:
        if 32 <= byte < 127:
            current += chr(byte)
        else:
            if len(current) >= min_length:
                strings.append(current)
            current = ""
    
    if len(current) >= min_length:
        strings.append(current)
    
    return strings

# Usage
firmware = parse_intel_hex('code.hex')
strings = find_strings(firmware)
for s in strings:
    print(s)

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Notes

  • The flag text "REDACTED" (Everything is under control) — ironic reference to the workshop manager's claim that "modern sensors don't lie"
  • The hint about the HEX file was a misdirection — the flag was actually there
  • Temperature sensor values (25, 79, 41, 18) — a red herring
  • XOR key 0x42 = 'B' — possibly a reference to "Boss" or just a convenient value

References

  • Intel HEX format
  • Proteus Design Suite
  • XOR cipher ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍