Linux 挖矿病毒深度排查与修复实录
记录时间: 2026-02-12环境: Ubuntu事件概述: 服务器异常卡顿,遭遇挖矿病毒入侵,创建大量挖矿进程,系统核心命令 (ps, ls, chattr, apt) 被篡改以隐藏行踪。
第一阶段:发现异常
1.1 服务器卡顿
服务器 CPU 占用率持续飙高,SSH 连接响应极其缓慢。第一反应是查看进程:
topps -ef
然而出现了异常情况——所有进程的 CPU 占用率加起来不到 20%。
这明显不对。系统监控显示 CPU 使用率在 90% 以上,但进程列表里却找不到对应的高占用进程。这种现象通常意味着存在隐藏进程,系统监控命令可能已被篡改。
1.2 尝试安装检测工具
既然常规手段看不到,准备安装 unhide 工具进行暴力枚举检测:
apt-get install unhide
然而 apt 报错了:
dpkg: error processing archive ...unable to make backup link of './usr/bin/chattr' before installing new version: Operation not permitted
Operation not permitted?
这个错误通常意味着文件被加了不可变属性(+i)。
第二阶段:发现 chattr 被篡改
2.1 尝试解锁 chattr
查看文件属性:
lsattr /usr/bin/chattr
显示 ----i---------e-----,文件被锁死了。
尝试解锁:
chattr -i /usr/bin/chattr
命令执行后,屏幕上出现了一堆乱码,然后显示:
Usage: vmlinux1 ...
vmlinux1? 这个名字引起了注意。vmlinux 通常是 Linux 内核的可执行文件名,但它不应该出现在 chattr 的输出里。
chattr 命令本身也被病毒替换了。 病毒把自己伪装成 vmlinux1(模仿内核文件名),然后替换了系统的 chattr 命令。
病毒的防御策略非常完善——不仅用 +i 属性锁定了文件,还把解锁工具 chattr 也替换成了假的。
2.2 Python 强制解锁
既然系统工具已经不可信,直接用 Python 调用 Linux 内核接口(ioctl)修改文件属性,绕过被篡改的 chattr 命令。
编写代码(fix_chattr.py):
import os, fcntl, struct# 直接操作文件描述符,绕过坏掉的 chattr 命令fd = os.open('/usr/bin/chattr', os.O_RDONLY)op = 0x40086602 # FS_IOC_SETFLAGS 魔数val = struct.pack('L', 0) # 清除所有标志fcntl.ioctl(fd, op, val)os.close(fd)
运行:
python3 fix_chattr.py
成功。
2.3 删除被篡改的 chattr 和vmlinux1
删除被篡改的 chattr:
rm -f /usr/bin/chattr
重新安装:
apt --fix-broken install
删除 vmlinux1:
rm -f /usr/bin/vmlinux1
第三阶段:发现隐藏进程
3.1 使用 unhide 检测
现在 apt 可以正常工作了,安装并运行 unhide:
apt-get install unhideunhide proc
果然,扫出了隐藏进程 PID 1954(以及 1949 等子进程)。
这下确认了——这是一个典型的 Rootkit 行为,它不仅在挖矿,还把自己从进程列表里隐藏了。
3.2 尝试查看进程信息
想查看进程的可执行文件信息,但发现文件已经被删除(显示 (deleted))。
那就查看 /proc 下的进程信息:
ls -ld /proc/1954
结果:
ls: cannot access '/proc/1954': No such file or directory
unhide 刚扫出来的进程,/proc 目录却不存在。再次尝试:
ls -l /proc/ | grep 1954
仍然没有。
这不可能——进程确实存在,但 ls 看不到。这引发了一个疑问:ls 命令本身是否也被篡改了?
第四阶段:发现系统命令被劫持
4.1 使用 busybox 验证
使用 busybox(一个静态编译的工具集,不依赖系统库)进行验证:
busybox ls -ld /proc/1954
结果:
dr-xr-xr-x 9 root root 0 Feb 12 10:23 /proc/1954
目录确实存在。这证实了猜测——系统自带的 ls 命令已被篡改。
这不是普通的挖矿病毒,而是一个精心设计的 Rootkit。它不仅隐藏了进程,还修改了系统最基础的查看命令,在输出时自动过滤掉特定 PID 的目录。
4.2 查看进程详细信息
使用 busybox 查看进程信息:
busybox cat /proc/1954/status | grep PPidbusybox ls -l /proc/1954/exe
发现:
- • 父进程是 1 (init/systemd):病毒已经完全"守护进程化",或者是由系统服务直接启动的。
- • 进程名是随机字符串:
/usr/bin/a9213172,每次重启都会变。 - • 执行文件显示
(deleted):病毒启动后立即删除了自身文件,只驻留在内存中。
这是典型的"无文件攻击"(Fileless Attack)。
4.3 怀疑整个核心包被污染
既然 ls 被篡改了,那么其他核心命令很可能也被污染了。运行 dpkg --verify 进行全面检查:
dpkg --verify coreutils systemd init procps bash
结果显示大量核心工具的 MD5 校验失败:
- •
/bin/ls, /bin/dir (文件查看命令被篡改) - •
/bin/systemctl (服务管理命令被篡改) - •
/usr/bin/uptime, /usr/bin/w (负载查看命令被篡改,用于伪造低 CPU 占用) - •
/etc/sysctl.conf (系统参数配置被修改)
这解释了为什么 top 和 ps 看不到高 CPU 进程——这些监控命令都被修改了,在输出时会自动隐藏病毒进程的资源占用。
结论:必须先修复系统命令,否则后面即使找到了病毒位置也看不到,无法删除。
第五阶段:修复系统命令
5.1 尝试重装核心包
试图重装这些核心工具:
apt-get install --reinstall coreutils systemd procps
又报错了:
unable to make backup link of './bin/dir' ... Operation not permitted
病毒极其狡猾,它不仅篡改了这些核心文件,还给它们也加了 +i 锁。
5.2 Python 批量解锁失败
尝试用之前成功的 Python 脚本方法批量解锁:
import os, fcntl, structfiles = ['/bin/dir', '/bin/ls', '/bin/systemctl', '/usr/bin/uptime', '/usr/bin/w']for f in files: try: fd = os.open(f, os.O_RDONLY) op = 0x40086602 # FS_IOC_SETFLAGS val = struct.pack('L', 0) fcntl.ioctl(fd, op, val) os.close(fd) print(f"Unlocked {f}") except Exception as e: print(f"Failed {f}: {e}")
运行后发现部分文件报错:
Failed /bin/dir: [Errno 95] Operation not supportedFailed /bin/ls: [Errno 95] Operation not supported
分析原因:
- •
[Errno 95] Operation not supported 通常出现在对软链接或特殊文件类型执行 ioctl 操作时。 - • 检查文件类型:
busybox ls -l /bin/dir /bin/ls
发现这些文件可能是软链接,或者病毒使用了特殊的文件系统属性,导致 ioctl 调用失败。
这意味着之前的 Python 内核调用方法在这些文件上失效了。
5.3 文件重命名破局
既然无法原位解锁,采用了另一个方案:直接把被篡改的文件重命名,为新文件腾出位置。
编写脚本(fix_core.py):
import os, fcntl, struct# 目标文件列表 (包含 /bin 和 /usr/bin 两种可能)targets = [ '/bin/dir', '/usr/bin/dir', '/bin/ls', '/usr/bin/ls', '/bin/systemctl', '/usr/bin/systemctl', '/usr/bin/uptime', '/usr/bin/w']# 解锁指令op = 0x40086602val = struct.pack('L', 0)for f in targets: if not os.path.exists(f): continue print(f"Processing: {f}") # 1. 尝试解锁 (忽略不支持的错误) try: fd = os.open(f, os.O_RDONLY) fcntl.ioctl(fd, op, val) os.close(fd) print(" Unlock: OK") except Exception as e: print(f" Unlock: {e}") # 2. 尝试改名 (备份移走) try: os.rename(f, f + ".virus") print(" Rename: OK") except Exception as e: print(f" Rename: {e}") # 3. 如果改名失败,尝试删除 try: os.unlink(f) print(" Delete: OK") except Exception as e: print(f" Delete: {e}")print("Done. Now try apt-get install again.")
运行后,成功将所有被锁定的病毒文件移走。
5.4 重新安装核心包
然后重新安装:
apt-get install --reinstall coreutils systemd procps
这次安装成功了。通过文件重命名绕过了 +i 属性的限制,因为重命名操作不需要修改文件内容,只需要修改目录项。
5.5 补救遗漏的配置文件
校验:
dpkg --verify coreutils systemd init procps bash
发现遗漏:提示 missing c /etc/sysctl.conf。
强制恢复缺失的配置文件:
apt-get -o Dpkg::Options::="--force-confmiss" install --reinstall procps
最终确认:
此时以为修复完成。
第六阶段:发现持久化机制
6.1 重启后病毒重生
重启机器后,运行 unhide 进行验证:
unhide proc
结果显示大量隐藏进程再次出现(PID 1489 等)。
执行文件名变为随机 8 位 16 进制字符串(如 /ebc626c2),文件位于根目录 / 且处于 (deleted) 状态。
/etc/sysctl.conf 再次被篡改。
分析:
- • 之前的修复清除了"驻留内存的进程"和"被篡改的命令",但没有找到真正的启动源(Loader/Dropper)。
- • 病毒利用某种持久化机制在系统启动时再次释放并运行。
结论:问题不光在系统命令,还有定时任务或服务在自动启动病毒。
6.2 排查持久化机制
开始系统性地排查所有可能的持久化机制:
- 1. 动态链接库劫持:
cat /etc/ld.so.preload
不存在(干净)✓
- 2. 配置文件分析:
tail -n 20 /etc/sysctl.conf
发现异常配置 fs.file-max = 2097152。
将文件描述符限制调至 200 万,这是典型的挖矿/僵尸网络特征。
- 3. Cron 的漏网之鱼:
ls -la /etc/cron.d/ls -la /var/spool/cron/crontabs/
目录正常,无明显恶意任务 ✓
6.3 检查最近改动的服务
既然 Cron 和动态库劫持都没问题,病毒极有可能注册了一个伪装的 Systemd 服务。
查找最近 7 天内被修改过的服务文件:
find /etc/systemd/system /lib/systemd/system -name "*.service" -mtime -7
找到了可疑文件:
/etc/systemd/system/multi-user.target.wants/tmuxinfo2d09ef78.service
查看内容:
[Service]ExecStart=/usr/bin/tmuxinfo2d09ef78c6c1c63c tmuxinfo2d09ef78Restart=always
这就是持久化的源头。
一个伪装成 tmux 相关服务的病毒守护进程,配置为 Restart=always,这解释了为什么杀掉进程后它会立即重启,以及为什么重启后病毒会再次出现。
第七阶段:彻底清除
7.1 清除持久化服务
停止并禁用服务:
systemctl stop tmuxinfo2d09ef78.servicesystemctl disable tmuxinfo2d09ef78.service
删除服务文件:
rm /etc/systemd/system/multi-user.target.wants/tmuxinfo2d09ef78.servicesystemctl daemon-reload
查找并删除残留的 service 文件:
find /etc/systemd /lib/systemd -name "tmuxinfo2d09ef78.service" -deletesystemctl daemon-reload
7.2 清除病毒主程序
检查是否有锁:
lsattr /usr/bin/tmuxinfo2d09ef78c6c1c63c
解锁并删除:
chattr -i /usr/bin/tmuxinfo2d09ef78c6c1c63crm -f /usr/bin/tmuxinfo2d09ef78c6c1c63c
杀掉残留进程:
killall -9 tmuxinfo2d09ef78c6c1c63ckill -9 1489 1490 1491
7.3 清理其他后门
删除 SSH 后门:
cat /root/.ssh/authorized_keys# 删除其中被添加的恶意公钥
7.4 最终核查
确保万无一失:
- 1. 服务文件确认:
find /etc/systemd /lib/systemd -name "*tmuxinfo*"
应无输出 ✓
- 2. SSH 后门确认:
cat /root/.ssh/authorized_keys
确保只包含你自己的公钥 ✓
- 3. 传统启动目录:
ls -lt /etc/init.d/ | head
未发现最近生成的异常脚本 ✓
第八阶段:最终验证
8.1 重启验证
重启系统:
reboot
验证清除结果:
- •
/etc/sysctl.conf: 未被篡改 ✓
至此,病毒已被彻底清除。
经验总结
核心难点与对策
- • 对策: 使用
busybox, unhide 等独立工具
- • 对策: Python
ioctl 内核调用 + 文件重命名
- • 对策: 深度排查 Systemd 服务,找到伪装的
.service 文件
总结: 这是一次典型的 Rootkit 对抗。病毒通过替换 ps/top 隐藏 CPU 占用,替换 ls 隐藏文件,替换 chattr 防止被删,并利用 +i 属性构筑防御工事,最后通过 Systemd 服务实现持久化。破局的关键在于不信任系统命令,使用 busybox 和原生语言(Python)直接调用内核接口,以及深度排查 Systemd 服务。