Skip to main content

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.txt was 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_123 from the reconstructed header fragments, not the decoy random_key_456 from hehe.h.
  • Decrypt.jar showed 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