【问题标题】:Replacing static function in kernel module替换内核模块中的静态函数
【发布时间】:2013-06-02 05:07:37
【问题描述】:

伙计们,

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

文件名: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。谁能给我一些建议?

谢谢, 威廉

【问题讨论】:

    标签: static kernel static-methods static-linking


    【解决方案1】:

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


    加长版

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

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

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

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

    1. 它的本地链接已经完成
    2. 可能有更多名为“fun”的符号,动态链接器无法判断您指的是哪一个

    【讨论】:

    • 感谢您的解释!对我帮助很大!
    猜你喜欢
    • 1970-01-01
    • 2011-11-13
    • 2018-12-24
    • 2016-07-13
    • 2015-12-16
    • 1970-01-01
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    相关资源
    最近更新 更多