免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3519 | 回复: 4
打印 上一主题 下一主题

[内核模块] x86-64位上的系统调用替换 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-07-18 18:06 |只看该作者 |倒序浏览
在32位系统上进行系统调用劫持的文章,前面很多高手都总结过了。但是x86-64架构上,还没有一个帖子有完整的说明。
我在32位系统上(centos5.4 内核版本:2.6.18-164.e15)替换了系统调用,但是移到64位系统上时出现了问题,高手们帮忙看下。
我的源码如下:
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/unistd.h>

  4. asmlinkage long (*ptr_sys_mkdir) (const char __user *pathname, int mode);
  5. static unsigned int orig_cr0;
  6. /**
  7. * clear WP bit of CR0, and return the original value
  8. */
  9. #if 1
  10. unsigned int clear_and_return_cr0(void)
  11. {
  12.     unsigned int cr0 = 0;
  13.     unsigned int ret;

  14.     asm volatile ("movl %%cr0, %%eax"
  15.               : "=a"(cr0)
  16.               );
  17.     ret = cr0;

  18.     /* clear the 16th bit of CR0, a.k.a WP bit */
  19.     cr0 &= 0xfffeffff;

  20.     asm volatile ("movl %%eax, %%cr0"
  21.               :
  22.               : "a"(cr0)
  23.               );
  24.     return ret;
  25. }

  26. /** set CR0 with new value
  27. *
  28. * @val : new value to set in cr0
  29. */
  30. void setback_cr0(unsigned int val)
  31. {
  32.     asm volatile ("movl %%eax, %%cr0"
  33.               :
  34.               : "a"(val)
  35.               );
  36. }

  37. #endif
  38. /*
  39. * usage: /sbin/insmod $MOD_NAME sct_addr=0xXXXXXXXXXXXXXXXX recycled_dir=/A/B/C/D
  40. */
  41. static char *sct_addr;

  42. asmlinkage long new_sys_mkdir(const char __user *pathname, int mode)
  43. {
  44.         int ret=0;
  45.        
  46.         printk("new_sys_mkdir!\n");
  47.         ret = ptr_sys_mkdir(pathname, mode);
  48.         printk("after sys_mkdir ret:%d!\n",ret);
  49.         return ret;
  50. };

  51. /* sctbl address */
  52. static unsigned long *sctbl;

  53. static int __init hello_init(void)
  54. {
  55.         printk("hello world start init!\n");
  56.        
  57.         sctbl = (unsigned long *) simple_strtoul(sct_addr, NULL, 16);
  58.        

  59.         /* replace with our syscall address */
  60.         ptr_sys_mkdir = (void *)sctbl[__NR_mkdir];
  61.         orig_cr0 = clear_and_return_cr0();   
  62.         sctbl[__NR_mkdir] = (long) new_sys_mkdir;
  63.         setback_cr0(orig_cr0);

  64.         printk("hello world end init!\n");
  65.         return 0;  
  66. };

  67. static void __exit hello_cleanup(void)
  68. {  
  69.         printk("hello world start clean!\n");
  70.         orig_cr0 = clear_and_return_cr0();   
  71.         sctbl[__NR_mkdir] = (long) ptr_sys_mkdir;
  72.         setback_cr0(orig_cr0);
  73.         printk("hello world end clean!\n");
  74. };


  75. module_init(hello_init);  
  76. module_exit(hello_cleanup);  

  77. MODULE_LICENSE("GPL");

  78. MODULE_PARM_DESC(sct_addr, "sctbl address in hex");
  79. module_param(sct_addr, charp,0);



复制代码
这里获取系统调用表地址的方法不是广为流传的通过IDT去找,而是在应用层用命令grep -w sys_call_table /boot/System.map-`uname -r`得到系统调用表的地址,在insmod的时候通过参数传递给模块初始化函数。上面代码里的sct_addr就是系统调用表的地址。

当我将上述代码拿到centos5.4的64位上编译时,就出现问题了:
[root@localhost hello]# uname -a
Linux localhost.localdomain 2.6.18-164.el5 #1 SMP Thu Sep 3 03:28:30 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
[root@localhost hello]# make
make -C /lib/modules/2.6.18-164.el5/build M=/usr/src/kernel_self/hello modules
make[1]: Entering directory `/usr/src/kernels/2.6.18-164.el5-x86_64'
  CC [M]  /usr/src/kernel_self/hello/hello.o
{standard input}: Assembler messages:
{standard input}:18: Error: suffix or operands invalid for `mov'
{standard input}:30: Error: suffix or operands invalid for `mov'
{standard input}:47: Error: suffix or operands invalid for `mov'
{standard input}:129: Error: suffix or operands invalid for `mov'
{standard input}:136: Error: suffix or operands invalid for `mov'
{standard input}:152: Error: suffix or operands invalid for `mov'
{standard input}:198: Error: suffix or operands invalid for `mov'
{standard input}:210: Error: suffix or operands invalid for `mov'
{standard input}:228: Error: suffix or operands invalid for `mov'
make[2]: *** [/usr/src/kernel_self/hello/hello.o] 错误 1
make[1]: *** [_module_/usr/src/kernel_self/hello] 错误 2
make[1]: Leaving directory `/usr/src/kernels/2.6.18-164.el5-x86_64'
make: *** [all] 错误 2
[root@localhost hello]#

上面的错误是clear_and_return_cr0和setback_cr0这两个函数中的嵌入汇编代码导致的。
不知道在x86-64平台上,这两个函数应该怎样实现?
请各位高手解答一下,获得指导一下方向。不甚感激。。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2013-07-18 18:35 |只看该作者
回复 1# lawrencehero

你不沿用原先的方法的原因是什么。有拿 32 位的 code 到 64 位上编译吗?


   

论坛徽章:
0
3 [报告]
发表于 2013-07-18 20:33 |只看该作者
回复 2# Godbach

不沿用以前的方法是因为这种方法相对简单一点。

这段代码拿到64位上编译过,有编译错误,我上面给出错误信息了。

不知道在上面那段修改cr0寄存器的汇编代码在64位上为什么编译不过去。难道是cr0寄存器在x86-64上有什么不同的地方吗?还是因为指令有所不同?
我在网上搜都不到x86-64的寄存器和指令相关的完整说明。如果有人知道,请给条明路。


   

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
4 [报告]
发表于 2013-07-18 22:15 |只看该作者
回复 3# lawrencehero

@帅绝人寰 指点一下。


   

论坛徽章:
0
5 [报告]
发表于 2013-07-22 10:28 |只看该作者
找到答案了。
原来这个问题论坛上已经有人问过了:求助:x86_64上面的cr0清零的问题
看来下次发帖前搜索论坛要更仔细点。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP