伙计们,
我正在尝试通过修改其符号来破解内核模块。基本思想是通过覆盖符号表中的地址来用新函数替换原来的函数。但是,我发现在将函数声明为静态时,黑客攻击失败了。但它适用于非静态函数。我的示例代码如下:
文件名: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 或对其的引用(特别是:调用),因为:
关于static - 替换内核模块中的静态函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16957892/