Sequence of work¶
Phase 1: Design the attack story¶
Anchor it in an ICS narrative, even if slightly theatrical ;-)
Design a linear but not obvious path:
discovery
protocol interaction
manipulation
consequence
Define flags early, not at the end when everything is glued together
A common failure mode is building a lab first and trying to retrofit a story later. That tends to produce confusion dressed as difficulty.
Phase 2: Reduce the simulation¶
Identify the minimum viable system:
one PLC equivalent
one control interface or service
one observable physical effect
Remove everything that does not contribute to the attack path
Hard-code or simplify physics where needed
If a component does not create or support a question, it is clutter.
Phase 3: Build the VM¶
Create VMware VM:
Debian 8 compatible base
BIOS boot
DHCP networking
Install only what is needed:
Python environment or Docker
Networking tools such as
nmap,netcat,tcpdumpProtocol tools if relevant
Avoid runtime downloads:
Clone repos during build
Vendor dependencies locally if possible
This avoids the silent failure when the VM wakes up in a network-less void.
Phase 4: implement the simulation¶
Install and configure chosen simulation:
Option A: Run
power-and-light-simas a background serviceOption B: Deploy minimal Docker compose
Make startup deterministic:
systemdservice orinitscriptNo manual steps required by the user
Expose only necessary ports:
Modbus 502, or equivalent
Avoid noise
Introduce controlled weaknesses:
Predictable register values
Writable coils
Weak service configs
Phase 5: design the challenge layer¶
Place flags logically:
Inside protocol data
In filesystem
Tied to physical outcome
Ensure each task teaches something:
Scanning
Protocol interaction
Manipulation
Escalation
Avoid accidental shortcuts:
Remove unnecessary SUID binaries
Close unrelated services
Otherwise, someone solves it in three commands and learns nothing except disappointment.
Phase 6: test under constraint¶
Throttle the VM:
1 CPU
1 GB RAM, then try 0.5 GB
Run full attack path:
From zero knowledge
No assumptions
If it only works when everything behaves perfectly, it will fail in production. Everything fails in production. Test failure modes:
Restart VM
Partial service startup
Slow responses
Phase 7: optimise¶
Reduce footprint:
Remove build tools
Clean package cache
Compress logs
Stabilise timing:
Avoid race conditions on startup
Delay services if needed
Consistency beats realism here:
Same results after reboot
Same flag paths
Phase 8: export and validate¶
Shutdown cleanly
Export to OVF via VMware
Convert to OVA via VirtualBox
Re-import and test
The VirtualBox hop is not elegance, it is survival.
Phase 9: integrate with TryHackMe¶
Upload VM
Create room
Map tasks to attack stages
Attach VM
Use platform variables where possible:
machine_ipDynamic hints
Phase 10: write the solution¶
Document the intended path
Include commands, reasoning, and expected outputs
Keep it aligned with the design, not with whatever accidental path worked during testing (I know myself)