never_gonna_give_you_flag
Challenge
Imported from local notes.md.
Solution
Original Notes
never_gonna_give_you_flag
Challenge Summary
Given: A polyglot attachment chall.txt and a companion site at https://rick-roll-0k02.onrender.com/.
Goal: Recover the hidden URL/input chain and obtain the final flag.
Constraints: The attachment mixes visible source, binary junk, and an embedded ZIP archive; the web endpoint response is noisy unless the exact input is used.
Initial Recon / Triage
Observations: - chall.txt is a zip archive with extra data prepended. - The visible pre-ZIP text is fake C/C++-style code that computes a hidden URL character by character. - The embedded ZIP contains a, b, c, hehe.h, and i. - i is a JPEG with embedded data extractable via steghide. - The site front-end posts user input to /x7a9kq and displays three encoded parts.
File identification: - starting_files/chall.txt: source-looking polyglot with embedded ZIP. - artifacts/extracted/x/hehe.h: decoy header with wrong macro values and wrong IMG_KEY. - artifacts/extracted/x/a, b, c: split header fragments used to reconstruct the real header. - artifacts/extracted/x/i: JPEG carrying Decrypt.jar via steghide. - artifacts/stego/Decrypt.jar: decoder logic for the site’s three-part response.
Entry points: - The attachment. - The hidden site endpoint at https://rick-roll-0k02.onrender.com/x7a9kq.
Hypotheses & Approach
Hypothesis 1: The visible code emits a URL that is needed later. Hypothesis 2: The ZIP and image carry the real decoder needed to interpret or validate the website response.
Outcome: Both were true. The visible code emitted a TinyURL and the embedded JAR explained the web decoder pipeline.
Execution Steps (Reproducible)
Stage 1
Commands:
cd /root/incognito2026CTF/never_gonna_give_you_flag
file starting_files/chall.txt
binwalk starting_files/chall.txt
python3 - <<'PY'
from pathlib import Path
import zipfile, io
p = Path('starting_files/chall.txt').read_bytes()
offset = p.find(b'PK\x03\x04')
with zipfile.ZipFile(io.BytesIO(p[offset:])) as zf:
zf.extractall('artifacts/extracted')
print(zf.namelist())
PY
Results:
chall.txtwas confirmed as a polyglot with an embedded ZIP archive.- The ZIP yielded split header fragments plus a JPEG
i.
Stage 2
Commands:
cd /root/incognito2026CTF/never_gonna_give_you_flag
python3 - <<'PY'
from pathlib import Path
import re
raw = Path('starting_files/chall.txt').read_bytes()
offset = raw.find(b'PK\x03\x04')
prefix = raw[:offset].decode('utf-8', 'ignore')
expr = re.findall(r'hehe_append\([^,]+, \(char\)\(haha \* haha ([+-]) (\d+)\)\)', prefix)
vals = []
for sign, num in expr:
n = int(num)
vals.append(100 + n if sign == '+' else 100 - n)
print(''.join(map(chr, vals)))
PY
Results:
- The visible code decoded to the real short URL:
https://tinyurl.com/g0t-y0u4-ur1
Stage 3
Commands:
cd /root/incognito2026CTF/never_gonna_give_you_flag
steghide info artifacts/extracted/x/i -p rickroll_key_123
steghide extract -sf artifacts/extracted/x/i -p rickroll_key_123 -xf artifacts/stego/Decrypt.jar -f
javap -classpath artifacts/stego/Decrypt.jar -c -p Decrypt
Results:
- The correct stego passphrase was
rickroll_key_123from the reconstructed header fragments, not the decoyrandom_key_456fromhehe.h. Decrypt.jarshowed the site decoder logic:- part 1: Caesar unshift by 17
- part 2: hex -> XOR with
secret-> Base64 decode - part 3: ROT13 then reverse
Stage 4
Commands:
cd /root/incognito2026CTF/never_gonna_give_you_flag
python3 artifacts/probe_endpoint.py 'https://tinyurl.com/g0t-y0u4-ur1'
- Sending the reconstructed TinyURL to the hidden endpoint returned `status=correct`.
- Decoding the three returned parts produced the final flag:
```text
IIITL{r1ck_45t13y_15_l3g3nd}
-
artifacts/prezip_source.cpp -
artifacts/extracted/ -
artifacts/stego/Decrypt.jar -
artifacts/probe_endpoint.py -
artifacts/decode_correct_input.py -
artifacts/
Flag
IIITL{r1ck_45t13y_15_l3g3nd}
flag_here