Back to KPMG CTF 2026 Campus Edition
Baud Intentions - (OT/IOT)

Baud Intentions - (OT/IOT)

Oct 12, 2026 3 min readWriteup 17 of 22
On this page
  1. 1.Challenge Overview
  2. 2.Step 1: Orient in the Restricted Shell
  3. 3.Step 2: Map the Device and Memory
  4. 4.Step 3: Find the Service Key
  5. 5.Step 4: Authenticate, Then Unlock via Diagnostics
  6. 6.Step 5: Read the Debug Buffers and Assemble the Flag
  7. 7.Summary
  8. 8.Key Takeaways

Challenge Overview

EventKPMG CTF 2026 Campus Edition
ChallengeBaud Intentions
CategoryICS / Hardware
Points10
Target0.cloud.chals.io:33786

"A legacy industrial interface is still online, and it reveals more than it should. Explore the system, understand how it works, and see what you can recover."

Baud Intentions challenge card

The title is a pun, baud is the UART serial speed, so we're talking to a serial console on an industrial device. Connecting to the target drops us into the maintenance shell of a simulated PLC (Programmable Logic Controller), the kind of controller that runs motors, valves and sensors in a SCADA environment.

This isn't a Linux box. It's a tiny custom command interpreter with its own verbs, and the whole challenge is about enumerating that interface to find what the operators left exposed.


Step 1: Orient in the Restricted Shell

The banner tells us a lot, and ls immediately reminds us this is not bash:

SCADA-7 :: PLCTERM-4  |  UART 115200 8N1  |  ttyUSB0
[WARN] Maintenance mode: LOCKED

root@plc4:~$ ls
  command not found: ls
  type 'help' for available commands.

Banner and help listing

help gives us the full command set:

sysinfo          device & firmware info
status           PLC operational status
diag [flags]     run hardware diagnostics
mem              memory map overview
auth <key>       authenticate session
read <register>  read a register value
clear            clear screen
help             this message

Two things stand out: the system is in a LOCKED maintenance mode, and there's an auth <key> command. So the path is probably: find a key → auth → unlock something → read the flag out of a register.


Step 2: Map the Device and Memory

sysinfo and status dump the device's state:

sysinfo and status output

Key facts from sysinfo:

DEVICE : PLCTERM-4 / SCADA-7 Node
SERIAL : SN-7743-ALPHA
REGISTERS : 0x00 - 0x7F
MAINT  : LOCKED

And status shows the register map in use, ending with the interesting bit:

Reg 0x4D-0x4F : [LOCKED - maintenance/debug]

mem confirms the layout of the register space:

mem map

0x00-0x0F  System control
0x10-0x1F  Sensor inputs
0x20-0x2F  Coil outputs
0x40-0x49  Runtime telemetry
0x4A-0x4C  Reserved
0x4D-0x4F  Maintenance/debug [LOCKED]
0x50-0x7F  User config

The target is clearly the 0x4D-0x4F maintenance/debug range. It's locked, so we need to both authenticate and unlock it.


Step 3: Find the Service Key

Reading through the register space, most addresses return nothing (no data or reserved), but one is a gift:

root@plc4:~$ read 0x48
[READ] 0x48 = LEGACY_SERVICE_KEY: MAINT-<UNIT>

The key format is MAINT-<UNIT>, and <UNIT> is the device's unit number. We already have it from sysinfo: the serial is SN-7743-ALPHA. So the legacy service key is:

MAINT-7743

This is the realistic part of the challenge, legacy industrial gear routinely derives "service" or "maintenance" keys from a predictable field like the serial number, so anyone who can read the nameplate can authenticate.


Step 4: Authenticate, Then Unlock via Diagnostics

root@plc4:~$ auth MAINT-7743
[AUTH] Key accepted. Session elevated.

auth accepted and diag --help

But reading the debug register still fails:

root@plc4:~$ read 0x4d
[READ] 0x4d: LOCKED — run diag sequence first.

So auth alone isn't enough, the debug buffers only become readable after a diagnostic run. Probing diag shows it refuses to run without explicit output options:

root@plc4:~$ diag -help
[DIAG] Error: diagnostic mode requires explicit output options.
[DIAG] Try: diag --help

Giving it the verbose + raw flags runs the full sequence and flips the maintenance range open:

root@plc4:~$ diag --verbose --raw
[DIAG] Running full diagnostic...
[DIAG] 0x01 .. CPU core integrity   PASS
[DIAG] 0x4D .. Debug buffer A        UNLOCKED
[DIAG] 0x4E .. Debug buffer B        UNLOCKED
[DIAG] 0x4F .. Debug buffer C        UNLOCKED
[DIAG] Done. Maintenance/debug range accessible.

diag --verbose --raw unlocking the debug buffers

The two-step gate (authenticate and run diagnostics) mirrors how real maintenance modes work: elevating a session and actually enabling debug output are separate operations.


Step 5: Read the Debug Buffers and Assemble the Flag

With 0x4D-0x4F unlocked, read each buffer. The flag was split into three pieces, one per register:

read 0x4d → [READ] Data: KPMG_CTF{x7ucTN1rT
read 0x4e → [READ] Data: vQRq0DWtYFqBxTiA_2
read 0x4f → [READ] Data: DoRGegNJFPv-xTmAJ}

Concatenating A + B + C in register order gives the flag:

KPMG_CTF{x7ucTN1rTvQRq0DWtYFqBxTiA_2DoRGegNJFPv-xTmAJ}

Summary

StepCommandResult
1help / mem / statusFound locked 0x4D-0x4F debug range
2read 0x48LEGACY_SERVICE_KEY: MAINT-<UNIT>
3sysinfoSerial SN-7743-ALPHA → key MAINT-7743
4auth MAINT-7743Session elevated
5diag --verbose --rawDebug buffers unlocked
6read 0x4d/0x4e/0x4fThree flag fragments → full flag

Key Takeaways

  • Enumerate the custom interface first. There's no ls here; help, mem, status and sysinfo are the recon tools. On ICS/embedded gear, map the command set and the register layout before trying anything clever.
  • Secrets are derived from nameplate data. The maintenance key was just MAINT- plus the serial's unit number. Legacy industrial devices lean on predictable, field-derived credentials, which is exactly why they're a soft target in the real world.
  • Access often has multiple gates. auth elevated the session, but the debug range needed a separate diag run to unlock. Don't stop at the first "accepted", watch what each step actually enables.
  • Read the error messages literally. run diag sequence first and diagnostic mode requires explicit output options told us precisely what to do next (diag --verbose --raw). The box was guiding us; the trick was listening.
  • Flags can be fragmented across registers. Three debug buffers each held a slice; reassembling them in address order produced the flag.

Flag: KPMG_CTF{x7ucTN1rTvQRq0DWtYFqBxTiA_2DoRGegNJFPv-xTmAJ}