leishaoweiwu 发表于 2015-05-26 11:02

如何在64位ubuntu中截获内核模块的导出函数?

我想在64位ubuntu中截获内核模块的导出函数,求思路,最好是代码

firocu 发表于 2015-05-26 13:02

回复 1# leishaoweiwu
首先这ubuntu, 没什么关系.

模块的通过__EXPORT_SYMBOL把符号导出到

    __attribute__((section("__ksymtab_strings")

如果你只是想将模块文件中的导出函数"截获", 以auth_rpcgss为例
/lib/modules/3.19.5-200.fc21.x86_64/kernel/net/sunrpc/auth_gss/auth_rpcgss.ko.xzreadelf-s auth_rpcgss.ko | grep __ksymtab_
   220: 0000000000000020    16 OBJECTGLOBAL DEFAULT   10 __ksymtab_gss_pseudoflavo
   238: 0000000000000020    16 OBJECTGLOBAL DEFAULT   12 __ksymtab_g_verify_token_
   247: 0000000000000010    16 OBJECTGLOBAL DEFAULT   10 __ksymtab_gss_mech_put
   288: 0000000000000030    16 OBJECTGLOBAL DEFAULT   12 __ksymtab_gss_mech_regist
   303: 0000000000000000    16 OBJECTGLOBAL DEFAULT   10 __ksymtab_gss_mech_get
   365: 0000000000000010    16 OBJECTGLOBAL DEFAULT   12 __ksymtab_g_token_size
   366: 0000000000000000    16 OBJECTGLOBAL DEFAULT   12 __ksymtab_g_make_token_he
   367: 0000000000000040    16 OBJECTGLOBAL DEFAULT   12 __ksymtab_gss_mech_unregi
   379: 0000000000000050    16 OBJECTGLOBAL DEFAULT   12 __ksymtab_svcauth_gss_fla
   383: 0000000000000060    16 OBJECTGLOBAL DEFAULT   12 __ksymtab_svcauth_gss_regor 这么做readelf -p __ksymtab_strings auth_rpcgss.ko

String dump of section '__ksymtab_strings':
[   0]g_verify_token_header
[    16]g_make_token_header
[    2a]g_token_size
[    37]gss_mech_put
[    44]gss_pseudoflavor_to_service
[    60]gss_mech_get
[    6d]gss_mech_unregister
[    81]gss_mech_register
[    93]svcauth_gss_register_pseudoflavor
[    b5]svcauth_gss_flavor我觉得这应该不是你的需求, 你或许是在运行的内核中动态的检测截获加载的内核的符号导出表.
简单看了下load module的代码
你可以注册一个module 通知链
register_module_notifier
这个notifier block会在do_init_module调用, 正好是模块加载最后一步执行.
struct module的成员
const struct kernel_symbol *syms;正好指向__ksymtab这个section
你试着看看应该能找到所有export的代码

个人见解.

nswcfd 发表于 2015-05-26 13:57

学习了,不过楼主这是要解决什么问题呢?安全问题?

leishaoweiwu 发表于 2015-05-26 15:05

谢谢您,我是想在64位的ubuntu中hook某个函数,比如说钩住usb_submit_urb这个函数,在执行这个函数之前先截获这个函数所提交的urb信息,再和我的白名单中的策略作对比,要是符合的话,就允许相应的外设访问,否则就禁止。32位ubuntu下的我已经实现了,现在在64位下研究,想在64位下找到相应的hook函数,或者还有没有其他的方法?回复 2# firocu


   

leishaoweiwu 发表于 2015-05-26 15:08

在64位的ubuntu中hook某个函数,比如说钩住usb_submit_urb这个函数,在执行这个函数之前先截获这个函数所提交的urb信息,再和我的白名单中的策略作对比,要是符合的话,就允许相应的外设访问,否则就禁止。回复 3# nswcfd


   

leishaoweiwu 发表于 2015-05-26 15:33

请问有什么好的思路吗?回复 5# leishaoweiwu


   

nswcfd 发表于 2015-05-26 15:52

不好意思,不明白为什么32位跟64位有区别?跟hook机制有关系吗?

如果性能不是特别concern的话,可以使用kprobe/jprobe/kretprobe之类的。
* jprobe可以查看入口的参数值,但是怎么影响原始的控制流还有待研究(比如修改urb的某个字段为非法值?)。
* kretprobe在函数返回的时候起作用,作为访问控制的时机有些晚。
* 最强大的是kprobe,不过这就跟反汇编紧密的耦合起来,受版本变化影响。

还有一种方法,就是在你的访问控制模块里面,重新实现一遍usb_submit_urb函数,在入口的时候加上访问控制的代码。此外,把原始的usb_submit_urb的入口替换为一个jmp命令。

PS,如果允许重新编译vmlinx的话,就在usb_submit_urb的入口处插入一个callback(函数指针),导出这个符号。在访问控制模块中实现callback,注册函数指针。

leishaoweiwu 发表于 2015-05-26 20:22

恩,我在32位ubuntu中就是用第二种方法的,在原始的usb_submit_urb的入口替换为一个jmp命令,执行usb_submit_urb之前跳转到访问控制函数,然后再执行执行usb_submit_urb。已经能够成功实现,我现在想在64位ubuntu中用类似的思路实现,可是有问题,在32位ubuntu中要想hook函数必须将CPU寄存器CR0的写保护位置为0,我现在的不知道是不是64位ubuntu下只有把CPU寄存器CR0的写保护位置0才能hook函数?回复 7# nswcfd


   

nswcfd 发表于 2015-05-27 16:39

不好意思,不太了解这个细节。最好参阅一下intel的cpu手册。

不过跟踪register_kprobe的反汇编,没有发现mov %cr0……

不管需不需要,先尝试一下呗,大不了crash一下,:p
页: [1]
查看完整版本: 如何在64位ubuntu中截获内核模块的导出函数?