- 论坛徽章:
- 0
|
在32位系统上进行系统调用劫持的文章,前面很多高手都总结过了。但是x86-64架构上,还没有一个帖子有完整的说明。
我在32位系统上(centos5.4 内核版本:2.6.18-164.e15)替换了系统调用,但是移到64位系统上时出现了问题,高手们帮忙看下。
我的源码如下:- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/unistd.h>
- asmlinkage long (*ptr_sys_mkdir) (const char __user *pathname, int mode);
- static unsigned int orig_cr0;
- /**
- * clear WP bit of CR0, and return the original value
- */
- #if 1
- unsigned int clear_and_return_cr0(void)
- {
- unsigned int cr0 = 0;
- unsigned int ret;
- asm volatile ("movl %%cr0, %%eax"
- : "=a"(cr0)
- );
- ret = cr0;
- /* clear the 16th bit of CR0, a.k.a WP bit */
- cr0 &= 0xfffeffff;
- asm volatile ("movl %%eax, %%cr0"
- :
- : "a"(cr0)
- );
- return ret;
- }
- /** set CR0 with new value
- *
- * @val : new value to set in cr0
- */
- void setback_cr0(unsigned int val)
- {
- asm volatile ("movl %%eax, %%cr0"
- :
- : "a"(val)
- );
- }
- #endif
- /*
- * usage: /sbin/insmod $MOD_NAME sct_addr=0xXXXXXXXXXXXXXXXX recycled_dir=/A/B/C/D
- */
- static char *sct_addr;
- asmlinkage long new_sys_mkdir(const char __user *pathname, int mode)
- {
- int ret=0;
-
- printk("new_sys_mkdir!\n");
- ret = ptr_sys_mkdir(pathname, mode);
- printk("after sys_mkdir ret:%d!\n",ret);
- return ret;
- };
- /* sctbl address */
- static unsigned long *sctbl;
- static int __init hello_init(void)
- {
- printk("hello world start init!\n");
-
- sctbl = (unsigned long *) simple_strtoul(sct_addr, NULL, 16);
-
- /* replace with our syscall address */
- ptr_sys_mkdir = (void *)sctbl[__NR_mkdir];
- orig_cr0 = clear_and_return_cr0();
- sctbl[__NR_mkdir] = (long) new_sys_mkdir;
- setback_cr0(orig_cr0);
- printk("hello world end init!\n");
- return 0;
- };
- static void __exit hello_cleanup(void)
- {
- printk("hello world start clean!\n");
- orig_cr0 = clear_and_return_cr0();
- sctbl[__NR_mkdir] = (long) ptr_sys_mkdir;
- setback_cr0(orig_cr0);
- printk("hello world end clean!\n");
- };
- module_init(hello_init);
- module_exit(hello_cleanup);
- MODULE_LICENSE("GPL");
- MODULE_PARM_DESC(sct_addr, "sctbl address in hex");
- 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平台上,这两个函数应该怎样实现?
请各位高手解答一下,获得指导一下方向。不甚感激。。
|
|