malware · cryptomining · rootkit · linux · kernel · monero · privilege-escalation · cve-2026-31431 · container-escape

Rootpacket: A Linux Cryptojacking Toolkit That Hides in the Kernel

Kinryū Labs analysed Rootpacket, a Linux cryptojacking toolkit that ships a kernel rootkit to fake CPU and memory usage, escalates to root through CVE-2026-31431 (an AF_ALG page-cache flaw that also escapes containers to the host), masquerades as an Intel driver, and disables the same exposed services rival miners use to get in.

By Davis Zheng·

CVE
CVE-2026-31431
CVSS
7.8 (CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

TLP:CLEAR. Cleared for public release. Captured by the Kinryū Labs honeypot sensor network. Indicators below are defanged.

Executive summary

  • ~45%CPU top shows while it runs near 100%
  • 3persistence mechanisms
  • 7.8CVSS, CVE-2026-31431 (AF_ALG page-cache LPE)
  • hostroot from an unprivileged container

Rootpacket is a multi-component cryptojacking toolkit for Linux. It bundles a kernel-level rootkit for stealth, a privilege-escalation exploit for CVE-2026-31431 in the Linux AF_ALG crypto interface, a UPX-packed XMRig 6.26.0 Monero miner renamed xrandom, and a competitor-elimination script. The code is written largely in Turkish (variable names, comments, status strings), which points to a Turkish-speaking operator.

The toolkit runs in one of two modes. In root mode it loads a loadable kernel module (LKM) rootkit disguised as intel_uncore_freq_aux, installs it through DKMS so it survives kernel upgrades, registers a systemd service, and clears the box of rivals. When it cannot get root, it falls back to a userland mode that persists through crontab and runs the miner as a daemon. The miner connects to pool.supportxmr.com:443 over stratum+ssl and mines Monero with RandomX.

The component worth dwelling on is the rootkit. While the miner pins the processor near 100 percent, the rootkit rewrites /proc/stat so that top and htop report a calm 40 to 50 percent, and it oscillates that figure using jiffies so the load looks real rather than pegged at a constant. It does the same to /proc/meminfo, and it filters directory listings to hide its own processes and files.

Key findings
  • The objective is cryptojacking (high confidence). The toolkit ships XMRig 6.26.0, a hardcoded Monero wallet, and a pool.supportxmr.com mining configuration, with the XMRig developer donation turned off so all proceeds go to the operator.
  • The privilege escalation is CVE-2026-31431 ("Copy Fail"), a deterministic page-cache write in the Linux AF_ALG algif_aead path (CVSS 7.8, disclosed April 2026). Because the page cache is shared host-wide, the same write escapes a container to root the host, so an infected container is a compromised host (high confidence).
  • The operator is well above the typical drop-and-mine crew (high confidence). A custom LKM rootkit with ftrace hooks, DKMS persistence that auto-rebuilds for new kernels, a working CVE-2026-31431 page-cache exploit, and layered systemd/DKMS/cron persistence are a level of engineering most cryptojackers never reach.
  • The operator is likely Turkish-speaking (moderate confidence). Turkish variable names, comments, and status messages such as ROOT ele gecirildi! run through the toolkit.
  • Rootpacket is built to own a host exclusively and keep it. Its killservice.sh removes rival miners and then disables the externally exposed services that cryptojackers use for initial access, including the Docker API on 2375/2376, the same vector we documented in our RedTail writeup. These crews are fighting over the same misconfigured boxes.

Toolkit architecture

Rootpacket is a modular dropper. The pieces:

setup.sh         Entry point. Checks privilege level, picks a deployment mode.
getroot          Privilege escalation. Exploits CVE-2026-31431 (AF_ALG) for local root.
xrandom          UPX-packed XMRig 6.26.0, renamed to dodge name-based detection.
kernel/
  stealth.c      LKM rootkit, compiled via DKMS, disguised as an Intel driver.
  install.sh     DKMS persistence engine.
killservice.sh   Competitor elimination and "hardening".
rootpacket.tar.gz  An inner copy of the whole toolkit, packaged for redistribution.

Root mode. setup.sh runs getroot if it is not already root, copies xrandom to /opt/kernel-kd/, creates a systemd service, runs kernel/install.sh to compile and load the rootkit through DKMS, runs killservice.sh to clear the competition, and starts the miner as a persistent service.

Userland fallback. When root is out of reach, setup.sh copies xrandom to ~/.xrandom/, writes a launcher with a PID lock, installs a crontab entry that fires at reboot and every minute, and launches the miner with setsid so it survives the parent shell.

FeatureRoot modeUserland mode
Miner location/opt/kernel-kd/xrandom~/.xrandom/xrandom
Persistencesystemd (kernel-kd.service)crontab (@reboot + */1 * * * *)
RootkitYes (LKM via DKMS)No
Competitor killYes (killservice.sh)No
Runs asroot (systemd)current user (setsid daemon)

getroot: CVE-2026-31431, root by page-cache corruption

getroot is a statically linked, unstripped ELF64 x86-64 binary built from getroot.c. It exploits CVE-2026-31431 (“Copy Fail”), a logic flaw in the Linux kernel’s AF_ALG algif_aead interface disclosed on 29 April 2026 (CVSS 7.8). The bug gives a deterministic, attacker-controlled 4-byte write into the kernel page cache, and getroot uses it to patch a SUID binary in memory and walk out as root.

PropertyValue
TypeELF 64-bit LSB executable, x86-64, statically linked, not stripped
CVECVE-2026-31431 “Copy Fail” (CVSS 7.8, AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
SubsystemAF_ALG algif_aead, AEAD template authencesn(hmac(sha256),cbc(aes))
AffectedLinux 4.14 to 6.19.11 (the flaw shipped in 2017, commit 72548b093ee3); fixed in 6.18.22, 6.19.12, 7.0+
Target/usr/bin/su — its in-memory .text is patched in the page cache
ReliabilityDeterministic, no race condition
Usage / fallback./getroot <cmd> [args...]; if the exploit does not land, it runs the command with current privileges anyway

The mechanism. A 2017 in-place optimisation in the AEAD code left the splice’d page-cache pages sitting in both the source and the destination scatterlist. When the authencesn template writes its 4-byte ESN scratch value at the attacker-chosen offset assoclen + cryptlen, that write lands inside the page-cache page of a user-readable file. The HMAC check then fails and recvmsg() returns EBADMSG, but the kernel never rolls the write back. getroot parses the ELF headers of /usr/bin/su to compute the file offset of its entry point, then loops splicesendmsg (carrying the 4 bytes to write in the AAD) → recvmsg, once per 4-byte chunk of shellcode, patching /usr/bin/su in the page cache. It then execves /usr/bin/su: the kernel loads the now-corrupted page, the shellcode runs SUID-root, and getroot confirms getuid() == 0 before running the operator’s command (printing the Turkish [+] ROOT ele gecirildi!). The on-disk file is never touched, so file-integrity monitoring sees nothing.

Container escape to the host. The Linux page cache is host-global; containers do not get their own. A process inside an unprivileged container that splices the host’s /usr/bin/su corrupts the host’s cached copy, so the execve yields root on the host, not just in the container. An infected container is therefore a compromised host, and setup.sh goes on to load the kernel rootkit into the host. Stopping and removing the container is not enough; the host has to be rebuilt.

We ran getroot once in an isolated VM (Kali, kernel 6.6.15). It executed the full AF_ALG sequence but did not obtain root on that build and fell back to running the command unprivileged, which fits an exploit that targets specific kernel layouts. We did not run the miner.

xrandom: the miner

xrandom is a renamed, UPX-packed copy of XMRig 6.26.0, the open-source Monero miner.

PropertyValue
Real identityXMRig 6.26.0
PackingUPX 4.2.4 (2.8 MB packed, 10.1 MB unpacked)
AlgorithmRandomX (rx/0)
Poolpool.supportxmr.com:443 over stratum+ssl
Wallet46NVDFL6v5STw5Qw4j77PoBSHRTYnHZGZ8WRoGvHmpaMX7ZyhNUP2u24TLV9pNgncz1bZF2Vm8KkaNTzU7SXqrnFUx5zgHQ
Donate level0 (XMRig developer donation disabled)

Mining over port 443 with TLS lets the traffic blend in with ordinary HTTPS at a glance, though the stratum handshake has a different TLS fingerprint to anyone looking closely.

stealth.c: the kernel rootkit

This is the most developed part of the toolkit. It is an LKM rootkit that uses ftrace function hooking to intercept kernel functions and erase the malware’s footprint, and it masquerades as an Intel hardware driver throughout.

PropertyValue
Module nameintel_uncore_freq_aux
Fake metadataMODULE_AUTHOR("Intel Corporation"), MODULE_DESCRIPTION("Intel Uncore Frequency Control Driver"), MODULE_VERSION("1.2.0")
Hookingftrace via kallsyms_lookup_name (resolved through a kprobe on kernels 5.7 and later)
Controlsysfs at /sys/kernel/intel_uncore_freq/ (enabled, cpu_lo, cpu_hi, mem_lo, mem_hi, hide_tag)

What it hooks and why:

  • CPU masking. It hooks show_stat to rewrite /proc/stat, faking utilisation between configurable bounds (40 to 50 percent by default) and oscillating with jiffies so the number moves like a real load instead of sitting flat.
  • Memory masking. It hooks meminfo_proc_show to rewrite /proc/meminfo, faking MemFree, MemAvailable, Buffers, Cached, Active, and Inactive.
  • Process hiding. It hooks iterate_dir to filter /proc listings, hiding PIDs whose names match a hardcoded set: stealth, masscan, sshruns, ransomx, cpumask, xrandom, cpm_, kcpm, mask_helper, ftrhook, kintel_aux. An operator can add more names at runtime through /sys/kernel/intel_uncore_freq/hide_tag.
  • File hiding. It hides paths matching stealth, cpumask, kintel_aux, intel_uncore_freq_aux, and the sysfs directory itself.
  • Self-hiding. On load it removes itself from /proc/modules and /sys/module/ with list_del_init, deletes its sysfs kobject, and increments its own refcount with try_module_get so rmmod will not unload it.

That hide-list is also a tell: alongside the miner it conceals masscan, sshruns, and ransomx, so the operator is likely running a scanner and may have more than a miner in the kit.

The practical effect is that an administrator watching top sees a busy-but-normal machine, finds no rogue process, and cannot see the kernel module that is doing the lying. The tells are physical and out-of-band: the box runs hot, the fans spin up, and power draw climbs, none of which the rootkit can fake.

Persistence: three mechanisms, split by mode

Rootpacket’s persistence depends on the mode it lands in. In root mode it layers two mechanisms that reinforce each other; in userland mode it falls back to a third.

#MechanismModeDetail
1systemd servicerootkernel-kd.service, Type=simple, Restart=always, RestartSec=3
2DKMS modulerootInstalls the rootkit under /lib/modules/$(uname -r)/extra/; survives kernel upgrades
3crontabuser@reboot plus every minute (* * * * *), with a PID lock and setsid

The DKMS entry is the stubborn one: it installs the rootkit through the kernel’s own module-build system, so a routine kernel upgrade rebuilds and re-arms it rather than removing it.

killservice.sh: clearing and closing the box

The script calls itself “cryptojacker hardening” in its banner, and that description is accurate from the operator’s point of view. It runs in three phases.

Phase 1: shut down exposed services. It targets services listening on 0.0.0.0 that are common cryptojacking entry points, stopping, disabling, and masking each one, setting chmod 000 on the binaries, and adding iptables DROP rules:

ServicePort
Redis6379
Docker2375/2376
PostgreSQL5432
MongoDB27017
Elasticsearch9200/9300
Memcached11211
Hadoop YARN8088
Jenkins8080
Confluence8090

The Docker line is the connective tissue to our RedTail report: Rootpacket closes the exact 2375/2376 door that RedTail walks through. An operator who lands first mines the host and then locks out the next crew, hardening the box against the techniques they would have used.

Phase 2: remove rival miners. It kills processes, deletes files, cleans cron jobs, and purges SSH keys tied to known cryptojacking families, including XMRig, Kinsing (kdevtmpfsi), TeamTNT (tntrecht, mdrfckr), sustes, watchdogs, and minerd, along with scanners like masscan, pnscan, and zgrab.

Phase 3: remove userland rootkits. It strips known malicious LD_PRELOAD entries (libprocesshider.so, libjdk.so, libpamx.so, a fake libselinux.so.3, and xhide) from /etc/ld.so.preload and deletes the libraries, clearing out competitors’ userland rootkits that might interfere with its own.

Attribution

The toolkit’s Turkish-language variable names, comments, and status strings (for example ROOT ele gecirildi!, “root obtained”) point to a Turkish-speaking operator with moderate confidence. We found a distribution or staging URL at linuxutil5.pages[.]dev, hosted on Cloudflare Pages, which fits the pattern of staging payloads on free, reputable infrastructure to blend in. The inner rootpacket.tar.gz, a self-contained copy of the whole toolkit, gives the operator a ready package to push to the next host.

Indicators of compromise

Network

IndicatorContext
pool.supportxmr.com / pool.supportxmr.com:443Primary Monero mining pool, stratum+ssl
linuxutil5.pages[.]devDistribution / staging (Cloudflare Pages)
api.xmrig.com, randomx.xmrig.com:443XMRig API and benchmark endpoints
donate.v2.xmrig.com, donate.ssl.xmrig.comXMRig developer-donation pools (present, donation disabled)
stratum+ssl:// to port 443Outbound TLS mining traffic

Monero wallet: 46NVDFL6v5STw5Qw4j77PoBSHRTYnHZGZ8WRoGvHmpaMX7ZyhNUP2u24TLV9pNgncz1bZF2Vm8KkaNTzU7SXqrnFUx5zgHQ

Files (SHA-256)

FileSHA-256MD5
rootpacket.tar.gz (outer)e2d0dab6b29df89d123fe8581047a03ac9b89ae8fa0d1f334b5aefbb93152857
getrootdda96d8a4bcc39dc7679347a4386bf1024152d2ccc46d333725ad0cda855d952
xrandom (packed)ec3ef3dce99fa6cbc480f0f0b0c292676afed68704c44396271c7dc6afea2937

Build IDs: getroot 148d8d902efd93ed892a541972fbcea3a99d05a3, xrandom d7a91225bdd2e3ab67cabded9d7809bcc724401f.

Host artifacts

PathContext
/opt/kernel-kd/xrandomMiner binary (root mode)
~/.xrandom/xrandom, ~/.xrandom/run.shMiner and launcher (userland mode)
/tmp/.xrandom.lockPID lock (userland mode)
/etc/systemd/system/kernel-kd.serviceMalicious systemd unit
/usr/src/intel_uncore_freq_aux-1.2.0/DKMS source for the rootkit
/sys/kernel/intel_uncore_freq/Rootkit sysfs control interface
/lib/modules/*/extra/intel_uncore_freq_aux.koCompiled rootkit module

Behavioural

  • A process named xrandom running as root or the current user.
  • /proc/stat CPU figures that disagree with hardware performance counters (perf stat), or with fan speed and power draw.
  • A systemd service kernel-kd (enabled, Type=simple, Restart=always).
  • A cron entry tagged # xrandom-userland-autostart.
  • A kernel module intel_uncore_freq_aux that loads at boot but is absent from lsmod.

Detection

If the rootkit is not loaded

systemctl status kernel-kd.service
ls -la /opt/kernel-kd/ ~/.xrandom/
dkms status | grep intel_uncore_freq
crontab -l | grep xrandom
lsmod | grep intel_uncore

If the rootkit is loaded

The userland views are compromised, so detection has to come from below or beside the rootkit:

  • Compare /proc/stat CPU against hardware counters with perf stat. A large gap is the tell.
  • Watch for ftrace hooks on show_stat, meminfo_proc_show, and iterate_dir.
  • Treat a discrepancy between reported CPU and real power, heat, or fan speed as a strong signal.

Catching the privilege escalation

  • An AF_ALG, SOCK_SEQPACKET socket opened by a process that is not a known crypto tool (cryptsetup, openssl, gpg, systemd-cryptsetup) is the core tell. The full order is socket(AF_ALG)bindsetsockopt(SOL_ALG)acceptpipesplicesendmsgsplicerecvmsg (repeated), then execve(/usr/bin/su).
  • Compare each SUID binary’s on-disk bytes against its page-cache view. sha256sum reads through the cache and shows the corrupted copy, so read the disk directly with dd if=<file> iflag=direct and hash that, then diff. A mismatch on a SUID binary is page-cache corruption.

Candidate YARA

rule Rootpacket_Cryptojacker
{
    meta:
        description = "Rootpacket Linux cryptojacking toolkit"
        reference   = "Kinryu Labs CTI 2026-06-16"
    strings:
        $wallet = "46NVDFL6v5STw5Qw4j77PoBSHRTYnHZGZ8WRoGvHmpaMX7ZyhNUP2u24TLV9pNgncz1bZF2Vm8KkaNTzU7SXqrnFUx5zgHQ" ascii
        $svc    = "kernel-kd" ascii
        $cron   = "xrandom-userland-autostart" ascii
        $mod    = "intel_uncore_freq_aux" ascii
    condition:
        $wallet or 2 of ($svc, $cron, $mod)
}

Remediation

  1. Remove the rootkit from a known-clean state. Boot from live or recovery media. Delete /lib/modules/*/extra/intel_uncore_freq_aux.ko* and run dkms remove intel_uncore_freq_aux/1.2.0 --all, then delete /usr/src/intel_uncore_freq_aux-1.2.0/ and rebuild the initramfs (update-initramfs -u, dracut -f, or mkinitcpio -P). The DKMS entry must go or it rebuilds.
  2. Remove the service: systemctl stop kernel-kd; systemctl disable kernel-kd; rm /etc/systemd/system/kernel-kd.service; systemctl daemon-reload.
  3. Remove the miner: rm -rf /opt/kernel-kd/ ~/.xrandom/ /tmp/.xrandom.lock, then pkill -9 -f xrandom.
  4. Clean cron of the # xrandom-userland-autostart lines.
  5. Restore what killservice.sh broke. It sets chmod 000 on Redis, Docker, PostgreSQL, MongoDB, and other binaries and adds iptables DROP rules. Reinstall the affected packages and review the firewall.
  6. Hunt laterally. The inner rootpacket.tar.gz is built for redistribution, so check other hosts for the same indicators, and review logs for exploitation of the services in killservice.sh to find the way in.
  7. Close CVE-2026-31431. Patch to a fixed kernel (6.18.22, 6.19.12, 7.0+, or your distro’s backport). Where you cannot patch at once, disable the vulnerable interface: echo 'install algif_aead /bin/false' > /etc/modprobe.d/disable-algif-aead.conf then rmmod algif_aead. For containers, block AF_ALG (family 38) in the seccomp profile.
  8. Assume host compromise from a container. Because the page-cache write crosses the container boundary, treat any host that ran setup.sh, even from inside a container, as fully compromised. Rebuild the host rather than just removing the container.

MITRE ATT&CK mapping

TacticTechnique
Initial AccessT1190 Exploit Public-Facing Application (Redis, Docker, MongoDB, Elasticsearch, Jenkins, Hadoop YARN, implied)
ExecutionT1059.004 Unix Shell
Privilege EscalationT1068 Exploitation for Privilege Escalation (CVE-2026-31431, AF_ALG algif_aead); T1611 Escape to Host (shared page cache)
PersistenceT1543.002 Systemd Service; T1053.003 Cron; T1547.006 Kernel Modules (DKMS)
Defense EvasionT1014 Rootkit; T1036.005 Masquerading: Match Legitimate Name; T1027.002 Software Packing (UPX); T1070.004 File Deletion; T1564.001 Hidden Files
DiscoveryT1057 Process Discovery (rival hunting)
Lateral MovementT1570 Lateral Tool Transfer (inner redistribution package)
ImpactT1496 Resource Hijacking (Monero mining)

Methodology and analyst notes

  • Analysis was primarily static (string extraction, disassembly, source review, structural analysis) on Kali Linux x86-64. We also ran getroot once in an isolated VM (kernel 6.6.15) to watch its behaviour: it attempted the AF_ALG sequence, did not obtain root on that build, and fell back to running the command unprivileged. The miner was not run, and nothing was uploaded.
  • The privilege-escalation component is CVE-2026-31431, identified from the authencesn(hmac(sha256),cbc(aes)) template bound to the AF_ALG socket, the /usr/bin/su page-cache target, and the splice/sendmsg/recvmsg write loop in the binary.
  • Samples (the toolkit and its components) are available to other researchers and defenders on request. Email [email protected] with a short note on who you are and what you need them for.
How to cite
Kinryū Labs (2026). Rootpacket: A Linux Cryptojacking Toolkit That Hides in the Kernel. https://kinryu.sh/reports/rootpacket-linux-cryptojacking-rootkit/