On November 8, the University of Delaware, in partnership with BSides Delaware, hosted a 36-hour CTF competition. Open to all-levels teams, the event challenged participants across categories like cryptography, reverse engineering and web exploitation. In this write-up, we’ll explore one of the standout challenges from the competition: The Immortal Game. This 500-point forensics challenge saw only three successful solves.
Category: Forensics
Points: 500
Solves: 3 out of 498 teams
Author: riiyak
Challenge:
184.60.121.146:53
make your move.
Initial recon
We begin with the IP address of a DNS server operating on the standard port 53. Using the dig command, we can gather additional information. Our first step is to perform a reverse lookup to find the domain name associated with this IP:
dig @184.60.121.146 -x 184.60.121.146
This command asks the specific DNS server (@184.60.121.146
) to return the domain name assigned to the IP. In this case, we get:
146.121.60.184.in-addr.arpa. 604800 IN PTR yatznetlab.ctf.
If you omit the @
part, the request will be handled by your network’s DNS, which might return a different result, such as:
146.121.60.184.in-addr.arpa. 43200 IN PTR h184-60-121-146.clevwi.dedicated.static.tds.net.
One more thing: If you’re not getting responses, your requests may be blocked by a firewall. In that case, try an online dig tool like diggui.com or digwebinterface.com, which work well for this purpose.
Discovering the Domain Records
With the domain name in hand, we can query the server for more information:
dig @184.60.121.146 yatznetlab.ctf ANY +multiline
I used the +multiline
option for a clearer, formatted view of the certificate.
Note: The ANY
query type is deprecated as per RFC8482, which limits the usefulness of ANY
queries. See RFC8482 – Saying goodbye to ANY for further disscusion. If you encounter issues, make individual requests for A
, CNAME
, MX
, TXT
, CERT
, and other record types. Here’s the server’s response:
yatznetlab.ctf. 604800 IN SOA localhost. root.localhost. (
2 ; serial
604800 ; refresh (1 week)
86400 ; retry (1 day)
2419200 ; expire (4 weeks)
604800 ; minimum (1 week)
)
yatznetlab.ctf. 604800 IN NS localhost.
yatznetlab.ctf. 300 IN A 184.60.121.146
yatznetlab.ctf. 604800 IN CERT PKIX 0 0 (
MIIEODCCAyCgAwIBAgIUcMHAP9GAMSHIbzpJwOBwGc8b
jq4wDQYJKoZIhvcNAQELBQAwgaYxCzAJBgNVBAYTAlVT
(...)
)
Pretty standard reply and, unfortunatelly, there’s no TXT entry with a flag here.
Playing chess with a DNS server
At this point we have to think what this task is all about. The name is The Immortal Game, and the description says “make your move”. If you look up the name in Google, the first result points to online chess platform immortal.game. But the server doesn’t return anything interesting about this domain.
The second one is Wikipedia page for Immortal Game, a classic 1851 chess match between Adolf Anderssen and Lionel Kieseritzky. It is well-known among chess fans for its brilliant strategy and sacrifices. There are annotated moves of this game, and if we have to make our move, we play White and start with pawn to e4.
We send our first query to see the response:
dig @184.60.121.146 e4.yatznetlab.ctf ANY
The server responds with:
e4.yatznetlab.ctf. 300 IN CNAME e5.133f595e-bcdb-a407-74d2a95.yatznetlab.ctf.
The CNAME
(Canonical Name) record indicates that e4.yatznetlab.ctf
is an alias for another domain, e5.133f595e-bcdb-a407-74d2a95.yatznetlab.ctf
. The server is responding with the Black move e5.
Checking this domain for clues:
dig @184.60.121.146 133f595e-bcdb-a407-74d2a95.yatznetlab.ctf ANY
We receive a TXT
entry:
133f595e-bcdb-a407-74d2a95.yatznetlab.ctf. 300 IN TXT "cJr7g<g45}?vj{_w*ut6Ge}"
After analyzing this string in many ways as various ciphers, I was unable to convert it to a proper flag in udctf{} format.
We must continue following the chess game’s moves. According to the game’s record, Anderssen proposes his pawn in exchange for faster development, f4. This is called the King’s Gambit.
We query the next move:
dig @184.60.121.146 f4.133f595e-bcdb-a407-74d2a95.yatznetlab.ctf ANY
The server’s response shows the gambit is accepted with exf4:
f4.133f595e-bcdb-a407-74d2a95.yatznetlab.ctf. 300 IN CNAME exf4.07cb4fe8-459c-8d80-2b21535.yatznetlab.ctf.
Is there something in TXT
record for us?
dig @184.60.121.146 07cb4fe8-459c-8d80-2b21535.yatznetlab.ctf ANY
Yes, another cryptic string:
07cb4fe8-459c-8d80-2b21535.yatznetlab.ctf. 300 IN TXT "h4dJsB>zR-6wph_a`RCf$CC"
You have to repeat these steps using 23 moves from the Immortal Game and collect all TXT
entries.
Try harder
After check-mating opponent’s king with Be7# move:
dig @184.60.121.146 Be7#.6f159061-42f5-9124-8c46dfb.yatznetlab.ctf ANY
the server doesn’t really want to give up and sends us a classic “try harder” instead of the flag:
Be7#.6f159061-42f5-9124-8c46dfb.yatznetlab.ctf. 300 IN CNAME tryharder.f0c89234-46de-8f0d-8efdfb4.yatznetlab.ctf.
Apparently this in not the end, so let’s analyze what we have. Each query gave us one string:
cJr7g<g45}?vj{_w*ut6Ge}
h4dJsB>zR-6wph_a`RCf$CC
e}<NqRWq-WBm^3b.$c3zw#,
c72a$%t,uc@hkQxrX4gSc>'
k9PxK?.f7&U%$Ydu'6,&d*c
_Q~d@Q=,W{Q>ch5eU$Cqmxb
ck7F$9cW4h>4V/##ed5fn.a
e@5nA!xY8mWx5fa_{s>k4QP
r#CaRDCQy<S$Aa@_.?&n}pV
tgJ~#m%%GUc}m}BRQy6w&@A
_&axv2jMR3HK!FZ=5{}-h8#
r4}eU6<#Y_HpBh4*b%&sGxP
eN.7F>V{Ng-Rst2wRHHD^qg
c=s4JmagD*q<r?rv5QFBps@
o@S%D=UD=FD=_-wQm#BrHa-
r@6F<7-3FYU@XW1FvqE9E@1
dPs>E-<=#jm$91k8-_!`-UV
_c@?x}-nV-xjk@gb*T_2N?y
@z-a2e_UW@BasPjju,&@-k-
rX6-y3XV~FDYTn`,Q-{s-H~
ora7f}q6UuV8m^h}~QWgYp.
o7Kq@vq@T!r#hnjaQkGTdw#
tsmy5%vy~}?,y7>bK7g#Qmd
This isn’t base64 encoded string, decoding from standard ciphers with various parameters also doesn’t reveal anything meaningful. However, there’s a hint: reading the first letter of each string yields: check_cert_record_@root
. As this is our only remaining unanalyzed artefact, it might be worth investigating further.
After saving it to a file and decoding from base64 as ctf.cer:
openssl x509 -noout -text -in ctf.cer
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
70:c1:c0:3f:d1:80:31:21:c8:6f:3a:49:c0:e0:70:19:cf:1b:8e:ae
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = US, ST = DC, L = Newark, O = University of Delaware, OU = Computer Sciences, CN = dns.yatznetlab.ctf, emailAddress = noreply@udel.edu
Validity
Not Before: Jun 23 03:00:15 2024 GMT
Not After : Apr 13 03:00:15 2027 GMT
Subject: C = US, ST = DC, L = Newark, O = University of Delaware, OU = Computer Sciences, CN = dns.yatznetlab.ctf, emailAddress = noreply@udel.edu
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:dc:ad:00:27:6c:22:e1:75:3d:ce:b0:c8:fd:d9:
f1:6b:d1:04:a9:16:f7:bf:36:dd:fb:b8:86:81:59:
(...)
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:1803180708100206200917102304170314180710042210
X509v3 Subject Key Identifier:
70:BF:8D:43:E2:EE:F7:BD:E7:B3:44:8B:31:83:7E:57:74:96:03:21
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
7a:fe:6c:88:2e:fb:06:57:e5:55:3d:62:c4:71:12:c0:d3:66:
7d:bc:14:2f:1c:38:83:b5:01:f7:35:77:fe:32:23:4c:98:f1:
(...)
Notice a strange Subject Alternative Name: 1803180708100206200917102304170314180710042210
. It doesn’t look like a typical hex byte string, but it has 46 digits, twice the number of chess moves and random strings.
If you extract every n’th letter from each string:
18 cJr7g<g45}?vj{_w*ut6Ge}
03 h4dJsB>zR-6wph_a`RCf$CC
18 e}<NqRWq-WBm^3b.$c3zw#,
07 c72a$%t,uc@hkQxrX4gSc>'
08 k9PxK?.f7&U%$Ydu'6,&d*c
10 _Q~d@Q=,W{Q>ch5eU$Cqmxb
02 ck7F$9cW4h>4V/##ed5fn.a
06 e@5nA!xY8mWx5fa_{s>k4QP
20 r#CaRDCQy<S$Aa@_.?&n}pV
09 tgJ~#m%%GUc}m}BRQy6w&@A
17 _&axv2jMR3HK!FZ=5{}-h8#
10 r4}eU6<#Y_HpBh4*b%&sGxP
23 eN.7F>V{Ng-Rst2wRHHD^qg
04 c=s4JmagD*q<r?rv5QFBps@
17 o@S%D=UD=FD=_-wQm#BrHa-
03 r@6F<7-3FYU@XW1FvqE9E@1
14 dPs>E-<=#jm$91k8-_!`-UV
18 _c@?x}-nV-xjk@gb*T_2N?y
07 @z-a2e_UW@BasPjju,&@-k-
10 rX6-y3XV~FDYTn`,Q-{s-H~
04 ora7f}q6UuV8m^h}~QWgYp.
22 o7Kq@vq@T!r#hnjaQkGTdw#
10 tsmy5%vy~}?,y7>bK7g#Qmd
You get the final flag: udctf{k!nG5_g4m61T_F7w}
Summary
This challenge was pretty hardcore – not quite a full chess match with the server, but still demanding in time and complexity. I would like to thank Professor Andrew Novocin aka ProfNinja and the BlueHens CTF team for not telling me “try harder” in a moment of confusion with this task.
While this particular challenge was tricky, most of the BlueHens CTF challenges were accesible and we managed to secure 5th place out of 498 teams. I’m looking forward to the next edition of this CTF!