⚠️ If XMRig is running on your server, assume it was placed there by an attacker. Complete this entire guide, not just the "kill the process" step. Attackers almost always install persistence mechanisms so it restarts automatically.
Step 01: Kill the Running Process
The first thing to do is stop XMRig immediately. Your CPU is being drained right now and every second it runs costs you money while degrading your server's reliability.
Run the commands below as your regular user, adding sudo if needed.
Find the process:
ps aux | grep -i xmrig
pgrep -af xmrigKill it:
kill -9 <PID>
ps aux | grep -i xmrigDon't stop here. Killing the process is temporary. If an autostart is in place, XMRig will respawn on the next reboot or after a delay.
Step 02: Find and Delete the Binary
Attackers typically drop the XMRig binary into world-writable directories like /tmp, /var/tmp, or /dev/shm. Resolve the exact binary path from the process's file descriptor.
Find via PID (if it was running):
sudo ls -l /proc/<PID>/exeSearch the filesystem:
sudo find / -name "xmrig" -type f 2>/dev/nullDelete it:
sudo rm -f /full/path/to/xmrigNote: Attackers sometimes rename the binary (e.g.kworker,sshd2) to blend in with legitimate system processes. If your CPU remains elevated, check for impostor process names.
Step 03: Remove Every Autostart Mechanism
This is the most critical step. Attackers know you'll kill the process, so they always pair XMRig with a persistence mechanism. Check all of the following:
- Systemd: Common service names include
xmrig.service,moneroocean_miner.service, or something innocuous-sounding - Cron: Check root crontab, all user crontabs,
/etc/crontab, and every file in/etc/cron.* - Init scripts:
rc.localandinit.dare less common but used by some exploit kits
Check systemd services:
systemctl list-units --type=service | grep -i xmrig
systemctl list-unit-files | grep -i xmrigDisable and remove a service:
sudo systemctl disable --now xmrig.service
sudo rm -f /etc/systemd/system/xmrig.service
sudo systemctl daemon-reloadCheck crontabs:
crontab -l
sudo crontab -l
grep -r xmrig /etc/crontab /etc/cron.*Check startup scripts:
grep -i xmrig /etc/rc.local
grep -rli xmrig /etc/init.d/Step 04: Extra Sanity Checks
XMRig got on your server somehow. Take 60 seconds to check for signs of broader compromise before marking this resolved.
- Check recent logins for unexpected IPs or times:
last -a - Look for outbound mining pool connections on port 443:
ss -tupn | grep 443 - Review authorized SSH keys:
cat ~/.ssh/authorized_keysand remove any you don't recognize - Check for new user accounts:
cat /etc/passwdand look for anything unfamiliar - Rotate all credentials: SSH keys, API tokens, database passwords
Mining malware is often a secondary payload. The attacker's primary goal may have been data exfiltration or a persistent backdoor. Don't assume the miner was the whole story.
Automate It: The Cleanup Script
Rather than running each command manually, use a companion shell script that automates all four steps, including a scheduled cron job that re-checks every 30 minutes.
#!/bin/bash
# =============================================================
# xmrig_cleanup.sh - Kill, remove, and block XMRig on a VPS
# Run as root or with sudo.
# Schedule: add to root crontab to re-run periodically.
# =============================================================
LOG="/var/log/xmrig_cleanup.log"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
log() {
echo "[$TIMESTAMP] $*" | tee -a "$LOG"
}
log "====== XMRig cleanup started ======"
# 1. Kill any running xmrig processes
log "--- Checking for running xmrig processes ---"
PIDS=$(pgrep -f xmrig 2>/dev/null)
if [ -n "$PIDS" ]; then
log "Found xmrig PIDs: $PIDS - killing them..."
for PID in $PIDS; do
BIN_PATH=$(readlink -f /proc/"$PID"/exe 2>/dev/null)
log " PID $PID -> binary: ${BIN_PATH:-unknown}"
kill -9 "$PID" 2>/dev/null && log " Killed PID $PID" || log " Could not kill PID $PID"
done
else
log "No running xmrig processes found."
fi
# 2. Find and delete xmrig binaries
log "--- Searching for xmrig binaries on disk ---"
SEARCH_PATHS=("/tmp" "/var/tmp" "/dev/shm" "/root" "/home" "/opt" "/usr/local/bin" "/usr/bin")
for DIR in "${SEARCH_PATHS[@]}"; do
while IFS= read -r -d '' FILE; do
rm -f "$FILE" && log " Deleted: $FILE" || log " Failed to delete: $FILE"
done < <(find "$DIR" -maxdepth 5 -name "xmrig" -o -name "xmrig*" -type f -print0 2>/dev/null)
done
# 3. Disable and remove systemd services
log "--- Checking systemd services ---"
SUSPICIOUS_PATTERNS=("xmrig" "monero" "miner" "stratum" "moneroocean")
for PATTERN in "${SUSPICIOUS_PATTERNS[@]}"; do
while IFS= read -r SERVICE; do
SERVICE=$(echo "$SERVICE" | awk '{print $1}')
[ -z "$SERVICE" ] && continue
systemctl disable --now "$SERVICE" 2>/dev/null
UNIT_FILE=$(systemctl show -p FragmentPath "$SERVICE" 2>/dev/null | cut -d= -f2)
[ -f "$UNIT_FILE" ] && rm -f "$UNIT_FILE" && log " Deleted unit file: $UNIT_FILE"
done < <(systemctl list-unit-files --type=service 2>/dev/null | grep -i "$PATTERN")
done
systemctl daemon-reload 2>/dev/null
# 4. Clean crontabs
log "--- Scanning crontabs ---"
if crontab -l 2>/dev/null | grep -qi "xmrig"; then
crontab -l 2>/dev/null | grep -vi "xmrig" | crontab -
log " Root crontab cleaned."
fi
for USER_HOME in /home/*; do
USERNAME=$(basename "$USER_HOME")
if crontab -l -u "$USERNAME" 2>/dev/null | grep -qi "xmrig"; then
crontab -l -u "$USERNAME" 2>/dev/null | grep -vi "xmrig" | crontab -u "$USERNAME" -
log " Crontab for '$USERNAME' cleaned."
fi
done
for CRON_FILE in /etc/crontab /etc/cron.d/* /etc/cron.daily/* /etc/cron.hourly/*; do
[ -f "$CRON_FILE" ] && grep -qi "xmrig" "$CRON_FILE" 2>/dev/null && sed -i '/xmrig/Id' "$CRON_FILE"
done
# 5. Clean rc.local and init.d
[ -f /etc/rc.local ] && grep -qi "xmrig" /etc/rc.local && sed -i '/xmrig/Id' /etc/rc.local
for INIT_SCRIPT in /etc/init.d/*; do
[ -f "$INIT_SCRIPT" ] && grep -qi "xmrig" "$INIT_SCRIPT" && rm -f "$INIT_SCRIPT"
done
# 6. Check for suspicious connections to mining ports
log "--- Checking for suspicious network connections ---"
MINING_PORTS="3333|4444|5555|7777|8888|14444|45560|3256"
SUSPICIOUS=$(ss -tupn 2>/dev/null | grep -E "$MINING_PORTS")
if [ -n "$SUSPICIOUS" ]; then
log " WARNING: Suspicious mining connections found:"
echo "$SUSPICIOUS" | while IFS= read -r LINE; do log " $LINE"; done
else
log " No suspicious mining connections detected."
fi
# 7. Final check
REMAINING=$(pgrep -af xmrig 2>/dev/null)
if [ -n "$REMAINING" ]; then
log " WARNING: xmrig may still be running: $REMAINING"
else
log " Confirmed: no xmrig processes running."
fi
log "====== XMRig cleanup complete. Log: $LOG ======"To deploy it on your server:
chmod +x xmrig_cleanup.sh && sudo mv xmrig_cleanup.sh /usr/local/sbin/
sudo /usr/local/sbin/xmrig_cleanup.sh
echo "*/30 * * * * /usr/local/sbin/xmrig_cleanup.sh" | sudo crontab -The script logs every action to /var/log/xmrig_cleanup.log for auditing.