一直有人说,在 Linux 上禁用动态内核模块加载会提高安全性。我理解人们为什么给出这个建议,但我一直认为如果模块接口不可用,坏人可以直接修改内存。(毕竟可加载模块接口是为好人准备的。)
所以我的问题是:是否有人知道任何循环的根工具包直接修改内核内存,而不是使用模块接口?
一直有人说,在 Linux 上禁用动态内核模块加载会提高安全性。我理解人们为什么给出这个建议,但我一直认为如果模块接口不可用,坏人可以直接修改内存。(毕竟可加载模块接口是为好人准备的。)
所以我的问题是:是否有人知道任何循环的根工具包直接修改内核内存,而不是使用模块接口?
是的,Phrack 中的Suckit rootkit就是这样一个例子,它通过/dev/kmem
. 本质上,目标保持不变 - 替换系统调用表中的条目以执行我们希望它们执行的操作。这里的区别在于修改是通过/dev/kmem
.
内核的 grsecurity/PaX 补丁包括用于禁用访问的支持/配置/dev/kmem
,/dev/mem
并且/dev/port
- 请参阅此处的条目。
/dev/mem
和之间的区别在/dev/kmem
这里解释。
以这种方式修改内存与在内核模块中加载之间的显着区别在于符号的暴露。大多数内核模块 rootkit 都是用static
函数编译的,因此这些函数不会从代码中导出;但是,还有其他技术可能会暴露内核模块的存在(例如,init 函数需要是可导出的)。直接修改内核内存的 rootkit 在扫描内核地址空间时将不可见,除非它已更改(即,如果您知道系统调用表应该指向哪里以及它指向什么,您可能会检测到它,除非作者足够聪明,可以确保进一步阅读/dev/kmem
给出正确的地址)。
至于坏人是否可以直接修改内存——根进程在技术上仍然在用户空间;也就是说它仍然是 ring 3 的一部分,不具备逃离其虚拟内存沙箱的能力。任何 ring 3 进程唯一可以修改的内存是它自己的虚拟地址空间,就它而言,这就是内存的样子。一个环 3 进程必须遵守标记内存的所有规则;例如,如果一个页面被标记为只读,它不能被进程修改(CPU 拒绝并告诉操作系统)。但是,ring 0 进程(cpu 管理员模式)可以修改它喜欢的任何内存,甚至可以要求 CPU 忽略内存页面的状态(即,您可以忽略页面是只读的事实)。
所以我想要得到的是,一个根进程作为一个根进程并没有隐式访问内存 - 它仍然必须通过内核询问并获得这种访问权限。只是内核会盲目服从。所以一种解决方案是使用 PaX 补丁,让内核拒绝此类请求。