High CPU from a cryptominer: find and remove it

Updated November 2026

A server that suddenly runs at full CPU with a process you do not recognise is very often mining cryptocurrency for someone else (cryptojacking). The miner itself is easy to kill; the real work is removing the persistence (the hidden tricks that restart it within a minute) and closing the hole the attacker used to get in.

Do this first.

  1. Do not reboot and do not delete files yet: the miner usually restarts itself, and you lose the clues that show how it got in.
  2. Note the process ID, user, command line and network connections of the busy process (commands below).
  3. If the server holds sensitive data or the miner runs as root, isolate it from the network and plan a rebuild rather than a clean-up.

How to recognise it

Find the miner

These commands are the same on Debian, Ubuntu and RHEL-family systems.

# Top CPU users with full command lines
ps -eo pid,ppid,user,%cpu,etime,cmd --sort=-%cpu | head -15

# For a suspicious PID (replace 1234):
sudo ls -l /proc/1234/exe          # real binary path; "(deleted)" means it was removed from disk
sudo ls -l /proc/1234/cwd          # working directory, often /tmp, /var/tmp or /dev/shm
sudo cat /proc/1234/cmdline | tr '\0' ' '; echo
sudo ss -tnp | grep 'pid=1234,'     # its network connections

Save a copy of the binary for analysis before you kill it. This works even when the file has been deleted from disk, because the kernel keeps it open:

sudo mkdir -p /root/evidence
sudo cp /proc/1234/exe /root/evidence/miner-1234.bin
sudo sha256sum /root/evidence/miner-1234.bin

When the process is hidden

Some miners hide themselves. Trend Micro’s analysis of Kinsing found a rootkit at /etc/libsystem.so loaded through /etc/ld.so.preload. Every program then loads it, and it hides the kinsing and kdevtmpfsi processes, its own files and its network connections from tools like ps, ls and netstat. The ld.so.preload file normally does not exist, so its presence is a strong warning sign.

# Normally: "No such file or directory"
ls -l /etc/ld.so.preload
cat /etc/ld.so.preload
lsattr /etc/ld.so.preload      # an "i" flag means it was made immutable

# Debian/Ubuntu: a statically linked toolset ignores ld.so.preload
sudo apt install busybox-static
busybox ps
busybox cat /etc/ld.so.preload

# Debian/Ubuntu: compare /proc, ps and system calls to find hidden PIDs
sudo apt install unhide
sudo unhide quick

On RHEL-family systems without a static toolset, check from rescue media that mounts the disk read-only. Static binaries are not fooled by ld.so.preload, but a kernel-module rootkit can still hide from them. If you find a rootkit of any kind, rebuilding the server is the safe choice.

Find the persistence

Miner campaigns usually use more than one way to restart. Kinsing, for example, adds a cron job that downloads and runs its script every minute, and Trend Micro also saw it register a system service called bot. Check all of these before you kill anything:

# Crontabs of every user
for u in $(cut -d: -f1 /etc/passwd); do sudo crontab -l -u "$u" 2>/dev/null | sed "s/^/$u: /"; done
ls -la /etc/crontab /etc/cron.d/ /etc/cron.hourly/ /etc/cron.daily/
sudo ls -la /var/spool/cron/ /var/spool/cron/crontabs/ 2>/dev/null

# systemd services and timers, newest unit files first
systemctl list-timers --all
sudo find /etc/systemd /usr/lib/systemd /run/systemd -name '*.service' -mtime -30 -ls

# SSH keys the attacker may have added
sudo find / -xdev -name 'authorized_keys*' -exec ls -l {} \; -exec cat {} \;

Look for lines that pipe curl or wget into sh or bash, base64-encoded commands, and files in /tmp, /var/tmp or /dev/shm. Our backdoor checklist covers the less common places.

Remove it

Work in this order, so nothing restarts the miner while you clean up. Copy each file to /root/evidence before you remove it.

  1. Freeze the processes so watchdog scripts do not notice: sudo kill -STOP 1234 for each miner PID and any malicious parent script (never PID 1, cron or sshd).
  2. Remove persistence: delete the malicious crontab lines (sudo crontab -e -u USER), disable and remove rogue units, and remove attacker SSH keys.
  3. Remove the preload rootkit if present (see the commands below).
  4. Kill the processes: sudo kill -9 1234.
  5. Delete the binaries and scripts you found, after copying them.
  6. Watch for a few minutes with top to confirm nothing comes back.
# Rogue systemd unit (example name "bot")
sudo systemctl disable --now bot.service
sudo mv /etc/systemd/system/bot.service /root/evidence/
sudo systemctl daemon-reload

# Preload rootkit: check nothing legitimate uses it first
#   Debian/Ubuntu: dpkg -S /etc/libsystem.so    RHEL: rpm -qf /etc/libsystem.so
sudo chattr -i /etc/ld.so.preload
sudo mv /etc/ld.so.preload /root/evidence/
sudo mv /etc/libsystem.so /root/evidence/

Cleaning versus rebuilding. If the miner ran as an unprivileged user (for example redis or www-data) and you found the entry point, cleaning in place is a reasonable risk. If it ran as root, installed a rootkit, or you cannot explain how it got in, rebuild from a fresh install and restore data only.

Close the way in

Miners are spread by automated scanners that try the same few doors on every internet address. Check which services listen publicly:

sudo ss -tlnp

Confirm it is fixed

When to call a professional

Get help from your host or an incident responder if the miner ran as root, you found a rootkit, the server stores customer or payment data, or the miner keeps returning after you removed everything you could find. A miner shows that someone could run code on your server; they may have done more than mine.

Sources