Hacking the Kernel - 修改系統調用表
Posted on 2008-02-19 14:55 ZelluX 閱讀(755) 評論(0) 編輯 收藏 所屬分類: Linux 、System昨天硬是沒找到正確的sys_call_table的地址,原來我之前在虛擬機上裝的ArchLinux是64位的。。
今天在真機上成功地修改了系統調用表。
測試環境: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


#include?<linux/unistd.h>
#include?<stdio.h>

#define?__NR_changeuid?238

int?main()


{
????printf("Previous?uid?=?%d\n",?syscall(__NR_getuid));
????syscall(__NR_changeuid);
????printf("Current?uid?=?%d\n",?syscall(__NR_getuid));
????return?0;
}
使用gcc -o test test.c編譯
5. 運行./test,即可看到類似的成功信息:
Previous uid = 1002
Current uid = 0
6. 卸載模塊rmmod addcall,此時再次運行./test就會失敗
今天在真機上成功地修改了系統調用表。
測試環境: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

















































對應的Makefile:












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就會失敗