【问题标题】:Is it possible to overwrite kernel code by replacing the page tables?是否可以通过替换页表来覆盖内核代码?
【发布时间】:2020-09-09 01:26:06
【问题描述】:

因此,您似乎无法修改内核代码,因为指向它的 PTE 被标记为可执行而不是可写。我想知道您是否可以使用以下方法覆盖内核代码? (这仅适用于 x86 并假设我们具有 root 访问权限,因此我们将以下步骤作为内核模块运行)

  1. 读入CR3寄存器的内容
  2. 使用 kmalloc 分配足够大的内存以复制所有 PTE 和 PDE
  3. 使用从 CR3 寄存器获得的值将所有分页数据复制到新分配的内存中
  4. 将相关页面标记为可执行和可写
  5. 用指向我们在步骤 2 中分配的内存的指针覆盖 CR3 寄存器

在这一点上,假设这一切正常,你不能覆盖返回地址和内核代码的其他部分吗?而在这样做之前,我们会被分页机制保护所阻止?

【问题讨论】:

  • 您已经在通过加载模块来编写和执行内核代码。您打算通过这些额外步骤实现什么目标?
  • 这个想法是覆盖未标记为可写的代码。重点是将代码隐藏在内核中以透明地运行某些进程

标签: linux linux-kernel


【解决方案1】:

3 .使用从CR3寄存器获得的值将所有分页数据复制到新分配的内存中

5 .用指向我们在步骤 2 中 kmalloc 的内存的指针覆盖 CR3 寄存器

这两个步骤可能不起作用:

CR3 给你一个物理地址;但是,要读取页面数据,您需要一个虚拟地址。甚至不能保证 PTD 当前已映射(因此可访问)。

要覆盖 CR3 寄存器,您需要知道使用 kmalloc 分配的内存的物理地址;但是,您只知道虚拟地址。

但是,您可以使用 virt_to_physphys_to_virt 将物理地址转换为虚拟地址。

是否可以覆盖内核代码...?

我不确定,但以下尝试应该有效:

页表本身应该是可读写的 - 至少是 kmalloc 使用的页表。

您可以使用kmalloc 分配一些内存,而不是复制 PTD 和页表,它有 2 个页面大小(如果使用“传统”4 KiB 内存页面,则为 8 KiB)。这意味着“你的”内存块在所有情况下都包含一个完整的内存页。

当您拥有 PTD 的虚拟地址和页表时,您可以重新映射“您的”内存页,使其不再指向您的“kmalloc 内存”,而是指向您要修改的内核代码...

此时,假设这一切正常,您不能覆盖返回地址和内核代码的其他部分吗?

我不确定我是否正确理解了您的问题。

但是内核模块内核的一部分 - 所以没有什么能阻止内核模块做一些完全愚蠢的事情(故意或由于错误)。

因此,在编写内核模块时必须非常小心。

而且由于“root”具有加载内核模块的能力,因此黑客或恶意软件永远不会获得“root”访问权限,这一点很重要。否则可能会使用insmod 将恶意软件注入内核。

【讨论】:

    猜你喜欢
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-12
    相关资源
    最近更新 更多