CTF Write-Up
Kimetsu-CTF I Official Walkthrough
The official writeup for Kimetsu-No-Yaiba CTF
[A1] The Demon
The first thing I did was treat the target as a deliberately minimal service rather than immediately assuming there was an obvious foothold.
A quick service sweep returned an unusual result:
$ phantomscan --profile cautious 10.31.44.77PhantomScan 3.8
-------------------------
Target: 10.31.44.77[+] beacon 4512/tcp open
[+] archivex 7821/tcp open
[+] unknown 9107/tcp filteredScan completed in 18.42s
Neither of the exposed services looked particularly interesting. beacon appeared to return a static banner, while archivex disconnected whenever malformed input was supplied.
I initially suspected the filtered service was the important one.
[A2] Lost In The Mountains
I tried several packet-level probes against the higher port:
$ netprobe --syn --fragment 10.31.44.77:91079107/tcp
state: filtered
ttl: 61
response-pattern: inconsistentThe inconsistent TTL values initially appeared promising. It suggested there might be some kind of application-layer filtering rather than a conventional firewall.
After a few retries, however, the behavior stopped being reproducible.
$ netprobe --syn --fragment --repeat 12 10.31.44.77:9107responses: 3/12
classification: ambiguousThis turned out to be a false lead.
[A3] The Final Test
The second service was more interesting.
Connecting manually produced:
$ telnet 10.31.44.77 7821220 ARCHIVEX/0.9
READYTyping arbitrary commands resulted in:
ERR UNKNOWN DIRECTIVEThere was no obvious help command, so I started testing possible administrative verbs:
LIST
INDEX
STATUS
CATALOG
VERIFY
REBUILDEventually:
STATUSNODE=GREEN
INDEX=DEGRADED
CACHE=DISABLEDThe INDEX=DEGRADED message seemed significant.
I spent some time trying to determine whether this represented a corrupted search index that could expose internal records.
[A4] The First Mission
The service accepted a command resembling an index rebuild operation:
$ archivectl --host 10.31.44.77 --rebuild-index[+] connecting
[+] requesting metadata
[+] remote index version: 17
[+] local compatibility: unknown
[-] rebuild refusedAdding the --legacy switch changed the response:
[-] legacy index format unavailableThis initially appeared promising because the target clearly differentiated between index formats.
Unfortunately, none of the available options resulted in additional information.
[A5] The Demon King
While experimenting with malformed requests, I noticed that the service occasionally returned a diagnostic identifier:
TRACE-ID: AX-19C4Repeating the exact request produced different identifiers:
AX-7D31
AX-03F2
AX-B812I assumed these might correspond to internal object identifiers.
A small script was used to generate sequential requests:
$ traceharvest --target 10.31.44.77 --count 250requests sent: 250
unique trace IDs: 250
correlated records: 0No useful relationship emerged.
At this point it became clear that the identifiers were probably request-local rather than persistent.
Another dead end.
[B1] The Wrong Direction
The ARCHIVEX banner reminded me of an old backup protocol, so I searched the service for references to snapshots and archives.
Several guessed requests produced slightly different responses:
SNAPSHOT LISTERR 421and:
ARCHIVE STATUSSTATE=IDLE
JOBS=0I then tried querying an assumed administrative namespace:
META /system/archive404 OBJECT NOT FOUNDNothing indicated that such an endpoint actually existed.
Still, the presence of the word ARCHIVE made me suspect there might be an undocumented maintenance interface.
[B2] Strike with Nezuko
I constructed a request using a fictional maintenance header:
X-Archive-Maintenance: enabledThe response changed from:
ERR UNKNOWN DIRECTIVEto:
ERR MAINTENANCE DISABLEDThat was enough to justify testing a few variations:
X-Archive-Maintenance: 1
X-Archive-Debug: true
X-Archive-Repair: yes
X-Node-Override: localAll produced either the normal response or an immediate disconnect.
Get Ondutygrandma’s stories in your inbox
Join Medium for free to get updates from this writer.
The apparent maintenance interface was therefore another false lead.
[B3] The Cry Baby
I returned to the smaller service and tried querying it without sending any application data.
$ beaconprobe 10.31.44.77 4512BEACON/2.4
ROLE=EDGE
MODE=PASSIVE
CLOCK=UNSYNCThe unsynchronized clock was unusual.
I wondered whether the challenge depended on timestamp manipulation.
Sending artificially old timestamps produced:
ERR CLOCK WINDOWFuture timestamps produced:
ERR CLOCK WINDOWThe acceptable window appeared to be approximately 30 seconds, but manipulating it did not expose anything new.
[B4] Kyogai’s Drum Game
I wrote a small test harness to compare response latency:
$ beaconbench --samples 100 10.31.44.77:4512baseline:
min 21ms
avg 24ms
max 31mstimestamp-offset:
min 21ms
avg 25ms
max 34ms
There was no meaningful timing difference.
The minor variation looked interesting initially, but it was consistent with normal network jitter.
[C1] Lord Inosuke
At this stage I started considering whether the exposed services were merely decoys and the intended route involved some local configuration artifact.
I attempted several completely speculative resource names:
/.node-state
/.edge-cache
/.archive-map
/.maintenance
/.bootstrap-infoThe results were uniformly unhelpful:
403
404
404
403
404The 403 responses were interesting enough to investigate, but changing headers and request methods did not alter them.
For example:
GET -> 403
HEAD -> 403
OPTIONS -> 403
POST -> 403There was no observable difference in the response body.
[C2] Lord Inosuke II
I then compared a collection of fabricated client identities:
X-Client-Role: operator
X-Client-Role: archive
X-Client-Role: monitor
X-Client-Role: maintenanceEvery request produced:
403 ACCESS POLICYAdding a fake internal-network header:
X-Origin-Network: trustedchanged nothing.
This initially appeared promising because the application clearly contained access-control logic, but there was no practical way to influence it.
[C3] Zentisu’s Love
I eventually checked whether the target exposed any unusual DNS metadata.
$ resolverprobe 10.31.44.77resolver state:
primary: unavailable
secondary: configured
search-domain: edge.localThe edge.local suffix seemed potentially useful.
I tested several fabricated hostnames:
archive.edge.local
admin.edge.local
sync.edge.local
backup.edge.local
node01.edge.localOnly the first two resolved, and both pointed to the same address.
Connecting to them produced exactly the same service behavior.
So this was another dead end.
[C4] Dead Calm
Because admin.edge.local resolved successfully, I tried a browser-compatible request:
$ curl -H "Host: admin.edge.local" http://10.31.44.77/ADMIN CONSOLE
----------------
STATUS: OFFLINE
SESSION: NONEThat looked much more significant than it actually was.
The page contained a single diagnostic reference:
console-build: 4.11.0-rSearching for related endpoints gave:
/console/status -> 200
/console/health -> 200
/console/tasks -> 403
/console/users -> 403
/console/debug -> 404The accessible endpoints contained nothing beyond basic service health information.
[C5] The Siblings Bond
The /console/tasks response was the next thing I focused on.
A deliberately malformed request resulted in:
403
reason=operator-requiredI assumed an operator token might be generated by the beacon service.
I tried combining the previously observed trace identifiers with the console hostname:
AX-19C4
AX-7D31
AX-03F2
AX-B812None were accepted.
I also tried constructing tokens from the console build string and timestamps, but every attempt resulted in:
INVALID SESSIONNo authentication material was recovered.
[C6] Shinobu’s Wrath
At this point I ran another broad sweep, mostly to ensure nothing obvious had been overlooked:
$ phantomscan --deep 10.31.44.774512/tcp open
7821/tcp open
9107/tcp filteredUDP:
32000 no-response
40123 no-response
49811 no-response
Nothing new appeared.
A UDP probe against the highest candidate produced a single delayed response, but repeating the test never reproduced it.
That made it impossible to establish whether the packet came from the target at all.
[D1] The Hashiras
The remaining theory was that the machine required some environmental condition before the interesting functionality became available.
I tested several combinations:
Host header
Client role
Timestamp
Trace identifier
Archive mode
Maintenance header
Resolver hostnameNone produced a meaningful state transition.
The closest result was:
ARCHIVEX
STATE=READY
INDEX=DEGRADED
CACHE=DISABLEDwhich had already been observed earlier.
There was no corresponding administrative operation that could change the state.



