感谢
1.
godbach大神2.
http://technica.blogbus.com/logs/18945123.htmlmodule代码
syscall.c
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
#define __NR_newhandler 223
struct
{
unsigned short limit;
unsigned int base;
}__attribute__((packed))idtr;
struct
{
unsigned short off1;
unsigned short sel;
unsigned char none, flags;
unsigned short off2;
}__attribute__((packed))idt;
unsigned int* syscall_table;
unsigned int old_handler;
unsigned int get_sys_call_table(void)
{
unsigned int sys_call_off;
unsigned int sys_call_table;
char *p;
int i;
//获得中断描述符表寄存器地址
asm("sidt %0":"=m"(idtr));
printk("add of idtr %x\n", idtr.base);
//获取0x80中断处理程序的地址
memcpy(&idt, idtr.base + 8 * 0x80, sizeof(idt));
sys_call_off = ((idt.off2 << 16) | idt.off1 );
printk("addr of idt 0x80 %x\n", sys_call_off);
//从0x80中断处理程序的二进制代码中搜索sys_call_table地址
p = sys_call_off;
for(i = 0; i < 100; i++)
{
//0xff 0x14 0x85暂时不明白是什么特殊的汇编代码
if(p[i] == '\xff' && p[i+1] == '\x14' && p[i+2] == '\x85')
{
sys_call_table = *(unsigned int*)(p + i + 3);
printk("addr of sys_call_table %x\n", sys_call_table);
return sys_call_table;
}
}
return 0;
}
asmlinkage long sys_newhandler(void)
{
printk("hello I'm new handler\n");
return 0;
}
unsigned int clear_and_return_cr0(void)
{
unsigned int cr0 = 0;
unsigned int ret;
asm("movl %%cr0 ,%%eax":"=a"(cr0));
ret = cr0;
//清除cr0的WP(Write Protect)标志位
cr0 &= 0xfffeffff;//第16位为WP
asm("movl %%eax, %%cr0"::"a"(cr0));
return ret;
}
void setback_cr0(unsigned int val)
{
asm("movl %%eax, %%cr0"::"a"(val));
}
static int hello_init(void)
{
printk(KERN_ALERT "hello world\n");
syscall_table = (unsigned int*) get_sys_call_table();
if(syscall_table == 0)
{
printk("can't find syscall_table addr\n");
return 0;
}
old_handler = syscall_table[__NR_newhandler];
printk("addr of old_handler %x\n", old_handler);
unsigned int orig_cr0 = clear_and_return_cr0();
syscall_table[__NR_newhandler] = (unsigned long) sys_newhandler;
setback_cr0(orig_cr0);
return 0;
}
static void hello_exit(void)
{
unsigned int orig_cr0 = clear_and_return_cr0();
syscall_table[__NR_newhandler] = (unsigned long) old_handler;
setback_cr0(orig_cr0);
printk(KERN_ALERT "hello exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
|
Makefile
ifneq ($(KERNELRELEASE),)
obj-m := syscall.o
else
KERNELDIR ?=/lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
rm *.mod.c *.o *.order *.symvers
endif
.PHONY:clean
clean:
-rm *.mod.c *.o *.order *.symvers *.ko .*
|
用户态测试文件
user.c
#include <unistd.h>
#include <errno.h>
#define __NR_newhandler 223
#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
_syscall0(int, newhandler)
int main()
{
newhandler();
return 0;
}
|
1.生成模块文件
make
2.加载
sudo insmod syscall.ko
3.编译user.c
gcc user.c -o user
4.运行user
./user
5.查看dmesg
dmesg
[ 6061.492687] hello world [ 6061.492694] add of idtr c0761000 [ 6061.492696] addr of idt 0x80 c01033a0 [ 6061.492699] addr of sys_call_table c0593150 [ 6061.492701] addr of old_handler c0167e20 [ 6065.754162] hello I'm new handler
|
6.删除模块
sudo rmmod syscall
7.查看dmesg
dmesg
[ 6061.492687] hello world [ 6061.492694] add of idtr c0761000 [ 6061.492696] addr of idt 0x80 c01033a0 [ 6061.492699] addr of sys_call_table c0593150 [ 6061.492701] addr of old_handler c0167e20 [ 6065.754162] hello I'm new handler [ 6067.688628] hello exit
|
输出hello I'm new handler表明新添的syscall已成功call了
备注
在linux源代码linxu-source-2.6.32/arch/x86/kernel/entry_32.S有0x80中断处理程序的汇编代码,其中有一行如下
call *sys_call_table(,%eax,4)
|
为了得到它的二进制码,测试如下
syscall.s
.section .data
sys_call_table:
.ascii "hello,syscall!!!!\n"
.section .text
.globl _start
_start:
call *sys_call_table(, %eax,4)
|
编译链接如下
wj@wj-laptop:~/work/test$ as -o syscall.o syscall.s
wj@wj-laptop:~/work/test$ ld -o syscall syscall.o
wj@wj-laptop:~/work/test$ objdump -d ./syscall
./syscall: file format elf32-i386
Disassembly of section .text:
08048074 <_start>:
8048074: ff 14 85 7c 90 04 08 call *0x804907c(,%eax,4)
|
上图中ff 14 85即是程序中搜索sys_call_table地址时用的搜索词,后面便是它的地址了
阅读(2793) | 评论(1) | 转发(1) |