static - 替换内核模块中的静态函数

标签 static kernel static-methods static-linking

伙计们,

我正在尝试通过修改其符号来破解内核模块。基本思想是通过覆盖符号表中的地址来用新函数替换原来的函数。但是,我发现在将函数声明为静态时,黑客攻击失败了。但它适用于非静态函数。我的示例代码如下:

文件名:orig.c

int fun(void) {
    printk(KERN_ALERT "calling fun!\n");
    return 0;
}
int evil(void) {
    printk(KERN_ALERT "===== EVIL ====\n");
    return 0;
}
static int init(void) {
    printk(KERN_ALERT "Init Original!");
    fun();
    return 0;
}
void clean(void) {
    printk(KERN_ALERT "Exit Original!");
    return;
}
module_init(init);
module_exit(clean);

然后我按照styx的文章把symtab中原来的函数“fun”替换为调用函数“evil”,http://www.phrack.org/issues.html?issue=68&id=11
>objdump -t orig.ko
...
000000000000001b g     F .text  000000000000001b evil
0000000000000056 g     F .text  0000000000000019 cleanup_module
0000000000000036 g     F .text  0000000000000020 init_module
0000000000000000 g     F .text  000000000000001b fun
...

通过执行 elfchger
>./elfchger -s fun -v 1b orig.ko
[+] Opening orig.ko file...
[+] Reading Elf header...
    >> Done!
[+] Finding ".symtab" section...
    >> Found at 0xc630
[+] Finding ".strtab" section...
    >> Found at 0xc670
[+] Getting symbol' infos:
>> Symbol found at 0x159f8
>> Index in symbol table: 0x1d
[+] Replacing 0x00000000 with 0x0000001b... done!

我可以成功地将 fun 的符号表更改为 evil 并插入模块查看效果:
000000000000001b g     F .text  000000000000001b evil
...
000000000000001b g     F .text  000000000000001b fun
> insmod ./orig.ko
> dmesg
[ 7687.797211] Init Original!
[ 7687.797215] ===== EVIL ====

虽然这工作正常。当我将 fun 的声明更改为“static int fun(void)”并按照上面提到的相同步骤进行时,我发现没有调用 evil。谁能给我一些建议?

谢谢,
威廉

最佳答案

短版 : 将函数声明为“静态”使其成为本地函数并防止符号被导出。因此,调用是静态链接的,动态链接器在加载时不会以任何方式影响调用。

长版

将符号声明为“静态”可防止编译器导出符号,使其成为本地而不是全局的。您可以通过在 objdump 输出中查找(缺失的)“g”或在“nm”的输出中查找小写的“t”(而不是“T”)来验证这一点。编译器也可能内联本地函数,在这种情况下,符号表根本不包含它。

局部符号必须仅对于定义它们的翻译单元是唯一的。如果您的模块由多个翻译单元组成,您可以在每个翻译单元中有一个静态的 fun()。然后,完成的 .ko 的 nm 或 objdump 可能包含多个称为 fun 的本地符号。

这也意味着本地符号仅在其各自的翻译单元中有效,并且也只能从该单元内部引用(在您的情况下:调用)。否则,链接器现在不会,你的意思是哪个。因此,在加载模块之前,对静态 fun() 的调用已经在编译时链接。

在加载时,动态链接器不会篡改本地符号 fun 或对其的引用(特别是:调用),因为:

  • 它的本地链接已经完成
  • 整个过程中可能有更多名为“fun”的符号,动态链接器无法分辨,您指的是哪个
  • 关于static - 替换内核模块中的静态函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16957892/

    相关文章:

    c# - 为什么我们需要静态构造函数?

    java - 何时使用静态方法

    java - 关于 Java 新手的递归

    静态方法的 C++ 链接器问题

    c - 如何在 C 中引用出现在需要它的函数之后的静态数据?

    c++ - 为什么这个代码片段有效?如何取消引用 nullptr?

    C++调用静态函数指针

    android - 如何为android添加语言支持

    Windows 中的 Linux 内核检查

    linux - 在 Linux 内核中找不到方法 __kernel_vsyscall