【问题标题】:Reading kernel memory using a module使用模块读取内核内存
【发布时间】:2011-07-07 12:38:59
【问题描述】:

作为我项目的一部分,我需要读取内核以获取系统调用表的内存地址和系统调用地址。或者实际上我需要提取系统调用表和所有系统调用的内容。

到目前为止,我为此使用 GDB。有什么办法可以让我使用内核模块来做到这一点。我是新的内核模块编程。在这里寻求专家的建议。

【问题讨论】:

  • 在gdb中是怎么做的?
  • @Fredrik,您可以使用以下示例:gdb vmlinux /proc/kcore

标签: linux linux-kernel kernel-module


【解决方案1】:

首先让我说读取任意内核内存是一件棘手的事情!并且有很多方法可以做到这一点,它们的复杂程度和灵活性各不相同。

1) 硬编码地址。

在您的内核版本的 System.map 文件中搜索它:

# grep sys_call_table /boot/System.map-2.6.18-238.12.1.el5
c06254e0 R sys_call_table

这样,硬编码地址:

unsigned long *syscall_table = (unsigned long *)0xc06254e0;

然后,假设您是#include <linux/syscalls.h>,您可以使用__NR_syscall 定义来获取代码中这些系统调用的地址:

syscall_table[__NR_close]

这是最简单的方法,但迄今为止最不灵活。这个模块只能在那个确切的内核上工作。如果您将其安装到不同的内核中,您很可能会获得内核 OOP。

2) 对表进行暴力扫描

看看这个:

http://memset.wordpress.com/2011/03/18/syscall-hijacking-dynamically-obtain-syscall-table-address-kernel-2-6-x-2/

他使用一种方法来暴力破解内核内存地址范围以找到sys_call_stable。照原样,它仅适用于 32 位(64 位与内核的内存地址范围不同)。

这种方法有些灵活,但可能会随着内核语义的变化而崩溃。

3) 动态搜索 System.map 加载时间

您可以在加载模块时读取内核的 System.map 文件。我在我编写的 tpe-lkm 模块中演示了这一点。该项目托管在github上。

查看此文件中的 find_symbol_address_from_file():

https://github.com/cormander/tpe-lkm/blob/master/symbols.c

非常灵活,你可以找到任何你想要的符号,但是从内核空间读取文件是一个很大的“不”。不要问我为什么,但人们总是这样告诉我。您还冒着它查看的 System.map 无效的风险,并可能导致内核 OOP。另外,代码……乱七八糟。

4) 使用 kallsyms_on_each_symbol()

从内核版本 2.6.30 开始,内核导出 kallsyms_on_each_symbol()。我们要感谢 ksplice 的人。这样你就找不到 sys_call_table(由于某种原因它不在其中),但你可以找到大多数其他符号。

非常灵活、非常稳定的符号地址查找方法,但理解起来有些复杂;)

我在我的 tpe-lkm 项目中演示了这一点。看看这个文件中的 find_symbol_callback() 和 find_symbol_address() 函数:

https://github.com/cormander/tpe-lkm/blob/master/symbols.c

【讨论】:

    猜你喜欢
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 2012-05-02
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多