lsmod显示模块但/lib/modules/$(uname -r)/下无对应.ko文件,是恶意内核模块典型痕迹;需结合modinfo验证author/license/vermagic字段异常、size过小及dmesg警告综合研判。

lsmod 输出里有模块,但 /lib/modules/$(uname -r)/ 下找不到对应 .ko 文件
这是恶意模块最典型的痕迹之一。正常模块由 modprobe 加载时,会从 /lib/modules/$(uname -r)/ 下按 modules.dep.bin 查找依赖并加载;而攻击者常绕过这套机制,用 insmod 直接加载自编译、未签名、甚至内存中构造的模块。
验证方法很简单:
- 先用
lsmod | awk '{print $1}' | head -5拿几个模块名(比如看到一个叫hidekmod的) - 再查它在标准路径下是否存在:
find /lib/modules/$(uname -r)/ -name "hidekmod.ko" 2>/dev/null - 如果返回空,但
lsmod里确实列出来了,就要立刻怀疑——它不是通过常规流程加载的
注意:有些合法模块(如某些厂商闭源驱动)也可能不放在这里,但通常会在 modinfo hidekmod 的 filename 字段给出明确路径。如果 modinfo -F filename hidekmod 报错或输出为空,基本可以坐实异常。
modinfo 显示 author 为空或 license 非 GPL/BSD
内核要求绝大多数可合并进主线的模块必须声明作者和许可证,且 license 字段直接影响内核是否允许调用某些符号(比如 GPL-only 符号)。所以攻击者常清空这些字段来规避检测。
执行:modinfo suspicious_module | grep -E '^(author|license|description)'
- 若
author:后面是空行、unknown、乱码,或压根没这行,高度可疑 - 若
license:是Proprietary、Unspecified、None,而不是GPL v2、MIT等常见开源协议,需进一步比对来源 -
description如果是空、过于宽泛(如Kernel module),或含拼写错误(如netwrok driver),也值得标记
别只信 modinfo 输出——用 strings suspicious_module.ko | grep -i "author\|license" 直接扫二进制,看元数据是否被刻意抹除。
modinfo -F vermagic 和 uname -r 不匹配,但模块仍能加载
正常情况下,vermagic 字段包含内核版本、GCC 版本、配置标志等,modprobe 会严格校验。但如果模块被强制加载(比如用 insmod --force),或内核启用了 CONFIG_MODULE_FORCE_LOAD=y,就可能跳过验证。
检查步骤:
- 运行
modinfo -F vermagic suspicious_module,记下输出(例如6.8.0-45-generic SMP mod_unload) - 对比
uname -r输出(应为6.8.0-45-generic) - 如果不一致(比如模块声称来自
6.6.0),而lsmod里又确实存在,说明加载过程绕过了版本检查
此时要立刻查 dmesg | tail -20,找类似 module: suspicious_module: version magic '6.6.0' should be '6.8.0-45-generic' 的警告——这种日志往往被忽略,但它就是关键证据。
模块 Size 异常小,且 Used by 列为 0 或 “-”
lsmod 第二列是模块占用内存大小(字节)。一个功能完整的驱动模块很少小于 16KB;而很多 rootkit loader 模块为了隐蔽,会压缩到 4–8KB,甚至更小。
快速筛查命令:lsmod | awk '$2
- 结果里出现模块名 + 小于 8KB 的数字,优先拉出来查
- 同时满足
Used by是-(表示无其他模块引用它),说明它可能是独立注入的“入口点”,而非被系统正常调用的驱动 - 这种模块往往不响应
rmmod(因为没走标准卸载路径),强行卸载可能触发 panic
真正难搞的不是大模块,而是这种轻量级、无依赖、无 author、无 license、路径找不到的小东西——它们像钉子一样扎在内核里,不动声色地劫持系统调用或隐藏进程。


















