隐藏进程怎么查
用户态 rootkit 常用 LD_PRELOAD 劫持 readdir,或直接 hook 系统调用,让进程在 /proc 里存在却不出现在 ps、top 的输出中。核查思路是用两条互不依赖的路径各取一份 PID 集合做差集:一条直接读 /proc 目录,另一条调用进程枚举接口。
基本信息
| 适用平台 | Linux |
|---|---|
| 数据来源 | /proc 下每个纯数字目录对应一个 PID |
| 对照命令 | ps -eo pid、top、pgrep -a、pstree |
| 辅助工具 | unhide(unhide-linux,部分发行版仓库未收录) |
| 权限 | root(部分 /proc 节点仅 root 或属主可读) |
| 前提 | 两侧比对必须在同一 PID 命名空间内 |
典型使用场景
- 怀疑主机被植入用户态 rootkit 时做快速交叉验证
- 应急响应开始时确认 ps 输出是否可信
- 与 /proc/<pid>/cmdline、exe、maps 串联做进程取证
- 内核模块与用户态两层同时排查,避免只查一层
- 对比业务主机与同版本干净主机的进程集合差异
最小示例
最小示例
ls -d /proc/[0-9]* | sed 's#/proc/##' | sort -n > /tmp/proc_ids.txt # 直接读 /proc 目录取 PID
ps -eo pid --no-headers | sort -n > /tmp/ps_ids.txt # 走进程枚举接口取 PID
comm -23 /tmp/proc_ids.txt /tmp/ps_ids.txt # 只在 /proc 出现说明枚举被欺骗
ls -l /proc/1234/exe /proc/1234/cwd # 核对可执行文件与工作目录
cat /proc/1234/cmdline | tr '\0' ' '; echo # cmdline 为空也要如实记录
unhide proc 2>/dev/null | head -20 # 有该工具时做第三次交叉验证差异项排查方向
| 现象 | 可能原因 | 下一步 |
|---|---|---|
| 只在 /proc 出现 | 用户态 rootkit 或枚举被劫持 | 看 exe、maps 指向与内核模块 |
| 只在 ps 出现 | 进程刚退出,/proc 尚未同步 | 重跑一轮确认是否为瞬时差异 |
| 两边都在但 cmdline 为空 | 内核线程或改写了自身命令名 | 用 exe、cwd 与父子关系判断 |
| 两侧数量差距很大 | 容器与宿主处于不同命名空间 | 先对齐命名空间再比对 |
容器、PID 命名空间与 chroot 会让宿主与容器内的进程清单天然不一致;比对前确认执行环境,必要时用 nsenter 进入目标命名空间。
unhide 依赖系统调用与目录读取的差异,存在误报;任何差异都要落到具体的 exe、maps、模块证据上再下结论。
采集时把 PID、执行命令与时刻一并记录:进程清单随时间变化,缺少时间锚点的差异无法复核。