【问题标题】:How can I check whether a kernel address belongs to the Linux kernel executable, and not just the core kernel text?如何检查内核地址是否属于 Linux 内核可执行文件,而不仅仅是核心内核文本?
【发布时间】:2022-12-11 03:50:59
【问题描述】:

来自 Windows 世界,我假设 Vmlinuz 等同于 ntoskrl.exe,这是映射到内核内存中的内核可执行文件。

现在我想弄清楚内核中的地址是否属于内核可执行文件。使用 core_kernel_text 是找出这个问题的正确方法吗? 因为 core_kernel_text 对于一些显然应该属于 Linux 内核可执行文件的地址没有返回 true。

例如,当我给 core_kernel_text 提供系统调用入口处理程序地址时,core_kernel_text 不会返回 true,可以通过以下方式找到该地址:

unsigned long system_call_entry;
rdmsrl(MSR_LSTAR, system_call_entry);
return (void *)system_call_entry;

当我使用带有该地址的 get_module_from_addr 时,系统调用入口处理程序的地址也不属于任何内核模块。

那么,一个明显属于 Linux 内核可执行文件(例如系统调用条目)的处理程序的地址怎么可能既不属于核心内核也不属于任何内核模块呢?那它属于什么? 对于这些明显属于 Linux 内核可执行文件的函数类型,我需要使用哪个 API 来向我保证该地址确实属于内核?

我需要这样一个 API,因为我需要编写一个检测恶意内核模块的补丁程序,现在我需要确保该地址属于内核,而不是某个第三方内核模块或随机内核地址。 (请不要讨论绕过我检测的方法,明明可以绕过那是另外一回事了)

【问题讨论】:

    标签: linux-kernel kernel kernel-module


    【解决方案1】:

    听起来您正在尝试确定给定地址是否属于 Linux 内核可执行文件。 Linux 中的内核可执行文件通常称为 vmlinuz,它包含核心内核以及在运行时加载的各种内核模块。

    要确定一个地址是否属于 Linux 内核可执行文件,可以使用 is_vmlinux 函数。此函数将地址作为输入,如果该地址属于 Linux 内核可执行文件,则返回 true,否则返回 false。这个函数在 Linux 内核源代码中定义,您可以在文件 /mm/util.c 中找到它。

    或者,您可以使用 core_kernel_text 函数,该函数将地址作为输入,如果该地址属于核心内核文本部分,则返回 true,否则返回 false。这个函数在Linux内核源码中也有定义,可以在文件/mm/debug.c中找到。

    值得注意的是,核心内核文本段是 Linux 内核可执行文件的一个子集,因此如果一个地址属于核心内核文本段,那么它也将属于 Linux 内核可执行文件。然而,反之则不一定正确,因为可能有部分 Linux 内核可执行文件不属于核心内核文本部分。

    就您提供的具体示例而言,系统调用入口处理程序地址可能不属于核心内核文本部分,因为系统调用入口处理程序不是核心内核的一部分。相反,它可能是在运行时加载的内核模块的一部分。判断一个地址是否属于内核模块,可以使用get_module_from_addr函数,该函数接受一个地址作为输入,如果地址属于内核模块则返回指向模块结构的指针,否则返回NULL。这个函数定义在Linux内核源代码中,你可以在文件/mm/module.c中找到它。

    【讨论】:

    • 查看它的实现,我认为 is_vmlinux 只是检查地址是否是 vmlinux 可执行文件的开始,正如我在问题中所述,我已经尝试过 core_kernel_text,对于许多地址(例如系统调用入口处理程序)不会返回 true。正如我所说,系统调用入口处理程序也不属于任何模块,我尝试了 get_module_from_addr,返回 null 作为其地址。它肯定必须属于某物吧?!如果它不是内核核心或模块,那它是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    • 2014-11-13
    • 2016-12-08
    • 2013-03-10
    • 2012-07-31
    相关资源
    最近更新 更多