Chinaunix首页 | 论坛 | 博客
  • 博客访问: 537795
  • 博文数量: 120
  • 博客积分: 3030
  • 博客等级: 中校
  • 技术积分: 1445
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-05 01:00
文章存档

2011年(1)

2009年(2)

2008年(32)

2007年(33)

2006年(52)

我的朋友

分类: LINUX

2008-02-26 15:26:47

成功地修改了系统调用表。
测试环境:ArchLinux 2.6.24


1. 2.4.20以后的内核出于安全考虑,没有导出sys_call_table符号,所以要先通过System.map找到sys_call_table的地址
$ cat /boot/System.map26 | grep sys_call_table
c0375680 R sys_call_table
另外也可以用nm工具获得vmlinux中的所有符号
$ nm /usr/src/linux-2.6.24-ARCH/vmlinux | grep sys_call_table
结果一样

2. 以添加一个把uid改成root(0)为例,写一个内核模块:
addcall.c

#include <linux/kernel.h>
#include 
<linux/module.h>
#include 
<linux/init.h>
#include 
<linux/unistd.h>
#include 
<linux/time.h>
#include 
<asm/uaccess.h>
#include 
<linux/sched.h>

#define __NR_changeuid 238

MODULE_DESCRIPTION(
"Change uid to 0");
MODULE_AUTHOR(
"ZelluX");

static int (*saved) (void);

void ** sys_call_table = 0xc0375680;

asmlinkage 
int sys_changeuid(void)
{
    current
->uid = current->euid = current->suid = current->fsuid = 0;
    printk(KERN_ALERT 
"uid has been changed.");
    
return 0;
}


int __init init_addsyscall(void)
{
    saved 
= (int (*) (void)) (sys_call_table[__NR_changeuid]);
    sys_call_table[__NR_changeuid] 
= (unsigned long) sys_changeuid;
    printk(KERN_ALERT 
"the call has been added.");
    
return 0;
}


void __exit exit_addsyscall(void)
{
    sys_call_table[__NR_changeuid] 
= (unsigned long) saved;
    printk(KERN_ALERT 
"the call has been removed");
}


module_init(init_addsyscall);
module_exit(exit_addsyscall);

对应的Makefile:

ifneq ($(KERNELRELEASE),)
    obj-m :
= addcall.o
else
    KERNELDIR ?
= /lib/modules/$(shell uname -r)/build
    PWD  :
= $(shell pwd)

default:
        $(MAKE) -C $(KERNELDIR) M
=$(PWD) modules
endif

3. 使用insmod addcall.ko载入模块后,用dmesg可以看到the call has been added.
4. 测试程序
test.c

使用gcc -o test test.c编译

5. 运行./test,即可看到类似的成功信息:
Previous uid = 1002
Current uid = 0

6. 卸载模块rmmod addcall,此时再次运行./test就会失败
阅读(2055) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~