data_split
Challenge
Imported from local notes.md.
Solution
Original Notes
data_split
Challenge Summary
- Given: A single hostname,
data-needs-splitting.umbccd.net, with the hint that the real program had to be found first. - Goal: Recover the hidden reverse-engineering target, analyze it, and determine the correct flag.
- Constraints: No starting files were provided locally; the only entry point was the domain name.
Initial Recon / Triage
- Observations:
Arecords fordata-needs-splitting.umbccd.netdid not resolve.- A
TXTquery on that hostname returned multiple numbered strings. - The TXT chunks began with
PK, which is the ZIP/JAR magic once base64-decoded.
- File identification:
- The numbered TXT records were ordered base64 fragments of a Java archive.
- Reconstructed archive contents:
Main.class,Loader.class, andassets/file.dat. assets/file.datwas itself a Java class file loaded reflectively.
- Entry points:
- DNS TXT records on
data-needs-splitting.umbccd.net - Java entry class
Main
- DNS TXT records on
Hypotheses & Approach
- Hypothesis 1: The challenge data was intentionally split across DNS TXT records and needed to be reassembled.
- Hypothesis 2: The visible JAR was only a loader, and the actual validation logic lived in the embedded
assets/file.datclass.
Execution Steps (Reproducible)
Stage 1
Commands:
cd /root/dawg2026CTF/data_split
dig TXT data-needs-splitting.umbccd.net +short | tr -d '"' | sort | sed 's/^[0-9][0-9]//' | tr -d '\n' > artifacts/payload.b64
base64 -d artifacts/payload.b64 > artifacts/payload.jar
file artifacts/payload.jar
unzip -l artifacts/payload.jar
Results:
- The TXT records reconstructed into
artifacts/payload.jar. - The JAR contained
Main.class,Loader.class, andassets/file.dat.
Stage 2
Commands:
cd /root/dawg2026CTF/data_split
javap -classpath artifacts/payload.jar -c -p Main
javap -classpath artifacts/payload.jar -c -p Loader
unzip -p artifacts/payload.jar assets/file.dat > artifacts/hidden.class
javap -c -p artifacts/hidden.class
Results:
MaininstantiatedLoader, which loaded/assets/file.datas a class and invokedvalidate().- The hidden class was
Validator. Validator.validate()read stdin, XORed each character with two repeating 16-bit masks, appended the resulting integers as decimal text, and compared that against a hard-coded numeric string.
Stage 3
Commands:
cd /root/dawg2026CTF/data_split
python3 - <<'PY'
target = '145511939249997195145441944550467175145531942549987228145401943650017203145451934650207244145651934650127169'
key1 = 2194307438957234483
key2 = 148527584754938272
mask = [((key1 >> (16 * i)) & 0xffff) ^ ((key2 >> (16 * i)) & 0xffff) for i in range(4)]
lengths = [5, 5, 4, 4]
out = []
pos = 0
idx = 0
while pos < len(target):
chunk = int(target[pos:pos + lengths[idx % 4]])
out.append(chr(chunk ^ mask[idx % 4]))
pos += lengths[idx % 4]
idx += 1
print(''.join(out))
PY
printf 'DawgCTF{J@v@_My_B3l0v3d}\n' | java -jar artifacts/payload.jar
Results:
- The decoded candidate flag was
DawgCTF{J@v@_My_B3l0v3d}. - Running the JAR with that input printed
Correct!, confirming the solution.
Artifacts Produced
artifacts/payload.b64- concatenated base64 recovered from DNS TXT records.artifacts/payload.jar- reconstructed Java archive.artifacts/hidden.class- extracted validator class fromassets/file.dat.
Flag
DawgCTF{J@v@_My_B3l0v3d}