添加系统调用
来源:互联网 发布:excel省市数据 编辑:程序博客网 时间:2024/06/05 19:44
方式一:编译内核的方式。
我本机的内核是linux-2.6.38.1添加的内核是linux-2.6.39.1
第一步:在arch/x86/include/asm/unistd_32.h文件中添加系统调用号。
350 #define __NR_open_by_handle_at 342
351 #define __NR_clock_adjtime 343
352 #define __NR_syncfs 344
353 #define __NR_mysyscall 345 /*添加的部分*/
354
355 #ifdef __KERNEL__
356
357 #define NR_syscalls 346 /*将系统调用总数重新更新*/
第二步:在系统调用表中添加相应的表项。位置:arch/x86/kernel/syscall_table_32.s
344 .long sys_open_by_handle_at
345 .long sys_clock_adjtime
346 .long sys_syncfs
347 .long sys_mysyscall /*345*/ /*添加部分*/
第三步:实现系统调用的服务历程。
理论上,这个函数在的位置没有固定,最好加在arch/x86/kernel/目录下的文件里面。
我这次是加在arch/x86/kernel/sys_i386_32.c文件中。
写了一个很简单的函数。
第四步:重新编译内核。这可能要话很长的时间哦,最好是找个上课的时间,
或去吃饭的时间,写了小脚本。(以下都是root权限的操作阿)
首先,执行make menuconfig。使用默认配置,就是出现图形界面后,直接选择exit退出即可。
然后,执行如下一个小的脚本。
我使用了C语言和汇编两种方式测试。
以后可以在内核中加一些比较实用的系统调用了。
比如说:系统调用日志收集系统。用来监控系统调用的系统调用。
可以用来防止系统攻击
方式二:插入模块的方式。
通过插入模块的形式插入系统调用,免去了编译内核的这个比较费时的操作。
我本机的内核是linux-2.6.38.1添加的内核是linux-2.6.39.1
第一步:在arch/x86/include/asm/unistd_32.h文件中添加系统调用号。
350 #define __NR_open_by_handle_at 342
351 #define __NR_clock_adjtime 343
352 #define __NR_syncfs 344
353 #define __NR_mysyscall 345 /*添加的部分*/
354
355 #ifdef __KERNEL__
356
357 #define NR_syscalls 346 /*将系统调用总数重新更新*/
第二步:在系统调用表中添加相应的表项。位置:arch/x86/kernel/syscall_table_32.s
344 .long sys_open_by_handle_at
345 .long sys_clock_adjtime
346 .long sys_syncfs
347 .long sys_mysyscall /*345*/ /*添加部分*/
第三步:实现系统调用的服务历程。
理论上,这个函数在的位置没有固定,最好加在arch/x86/kernel/目录下的文件里面。
我这次是加在arch/x86/kernel/sys_i386_32.c文件中。
写了一个很简单的函数。
点击(此处)折叠或打开
- 27 asmlinkage long sys_mysyscall(long data)
- 28 {
- 29 return data;
- 30 }
或去吃饭的时间,写了小脚本。(以下都是root权限的操作阿)
首先,执行make menuconfig。使用默认配置,就是出现图形界面后,直接选择exit退出即可。
然后,执行如下一个小的脚本。
点击(此处)折叠或打开
- make
- make modules
- make modules_install
- mkinitramfs -o /boot/initrd-2.6.39.1.img 2.6.39.1
- make install
编译完后,重启新的内核,发现鼠标用不了,估计是编译内核的时候没配置好。第五步,在用户态测试是否成功。(注意内核安装好后,重启后选择新的内核)
我使用了C语言和汇编两种方式测试。
点击(此处)折叠或打开
- #include <linux/unistd.h>
- #include <syscall.h>
- #include <sys/types.h>
- #include <stdio.h>
- int main(void)
- {
- long id1 = 0;
- id1 = syscall(345,190);
- printf("%ld\n",id1);
- return 0;
- }
点击(此处)折叠或打开
- # hello.s
- # display a string "Hello, world."
-
- .section .rodata
- msg:
- .ascii "Hello, world.\n"
-
- .section .text
- .globl _start
- _start:
- movl $345,%eax
- movl $15 ,%ebx
- int $0x80
- movl $4, %eax # system call
- movl $1, %ebx # file descriptor
- movl $msg, %ecx # string address
- movl $14, %edx # string length
- int $0x80
-
- movl $1, %eax
- movl $0, %ebx
- int $0x80
注意汇编的时候要用gdb调试。用gdb调试汇编的方式见:http://blog.163.com/zhe_wang_2009/blog/static/172282121201151175619458/
到这儿就结束了。这只是一个小的实验。这可以说算是迈出了一大步了。以后可以在内核中加一些比较实用的系统调用了。
比如说:系统调用日志收集系统。用来监控系统调用的系统调用。
可以用来防止系统攻击
方式二:插入模块的方式。
通过插入模块的形式插入系统调用,免去了编译内核的这个比较费时的操作。
点击(此处)折叠或打开
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/unistd.h>
- #include <asm/uaccess.h>
- #include <linux/sched.h>
- #define my_syscall_num 223
- //如下的这个值要到你机子上查。cat /proc/kallsyms | grep sys_call_table
- #define sys_call_table_adress 0xc1511160
- unsigned int clear_and_return_cr0(void);
- void setback_cr0(unsigned int val);
- asmlinkage long sys_mycall(void);
- int orig_cr0;
- unsigned long *sys_call_table = 0;
- static int (*anything_saved)(void);
- unsigned int clear_and_return_cr0(void)
- {
- unsigned int cr0 = 0;
- unsigned int ret;
- asm("movl %%cr0, %%eax":"=a"(cr0));
- ret = cr0;
- cr0 &= 0xfffeffff;
- asm("movl %%eax, %%cr0"::"a"(cr0));
- return ret;
- }
- void setback_cr0(unsigned int val) //读取val的值到eax寄存器,再将eax寄存器的值放入cr0中
- {
- asm volatile("movl %%eax, %%cr0"::"a"(val));
- }
- static int __init init_addsyscall(void)
- {
- printk("hello, kernel\n");
- sys_call_table = (unsigned long *)sys_call_table_adress;//获取系统调用服务首地址
- anything_saved = (int(*)(void)) (sys_call_table[my_syscall_num]);//保存原始系统调用的地址
- orig_cr0 = clear_and_return_cr0();//设置cr0可更改
- sys_call_table[my_syscall_num] = (unsigned long)&sys_mycall;//更改原始的系统调用服务地址
- setback_cr0(orig_cr0);//设置为原始的只读cr0
- return 0;
- }
- asmlinkage long sys_mycall(void)
- {
- printk("current->pid = %d , current->comm = %s\n", current->pid, current->comm);
- return current->pid;
- }
- static void __exit exit_addsyscall(void)
- {
- //设置cr0中对sys_call_table的更改权限。
- orig_cr0 = clear_and_return_cr0();//设置cr0可更改
- //恢复原有的中断向量表中的函数指针的值。
- sys_call_table[my_syscall_num] = (unsigned long)anything_saved;
-
- //恢复原有的cr0的值
- setback_cr0(orig_cr0);
- printk("call exit \n");
- }
- module_init(init_addsyscall);
- module_exit(exit_addsyscall);
- MODULE_LICENSE("GPL");
0
上一篇:qq原理
下一篇:list_for_each_entry
相关热门文章
- linux 常见服务端口
- xmanager 2.0 for linux配置
- 【ROOTFS搭建】busybox的httpd...
- openwrt中luci学习笔记
- Linux里如何查找文件内容...
给主人留下些什么吧!~~
评论热议
阅读全文
0 0
- 内核添加系统调用
- 添加Linux系统调用
- 【操作系统】添加系统调用
- minix添加系统调用
- Linux添加系统调用
- 添加Linux系统调用
- 添加系统调用
- Linux添加系统调用
- ubuntu添加系统调用
- Linux添加系统调用
- Linux添加系统调用
- 添加系统调用
- 为linux添加系统调用
- 给linux添加系统调用
- 添加自定义Linux系统调用
- 添加系统调用自启动
- 如何添加linux系统调用
- Linux系统调用的添加
- linux下C和shell调用的popen函数
- 对工厂模式的简单理解
- linux进程调度
- 经典排序算法之冒泡排序
- qq原理
- 添加系统调用
- list_for_each_entry
- 字符串的包含
- 字符串的排列组合
- NGINX实现IF语句里的AND,OR多重判断
- 经典排序算法之堆排序
- 经典排序算法之归并排序
- linux内存管理--缺页异常处理
- 进程的页表创建详解
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
没考上高中怎么办
吃固元膏上火怎么办
退休后医保怎么办
临清市医疗卡怎么办
中考没考上怎么办
考籍号忘了怎么办
高考准证号丢了怎么办
没有高考成绩单怎么办
初中生出国学籍怎么办
初三成绩不好怎么办
高考失利怎么办
高中生成绩不好怎么办
孩子考试成绩差怎么办
孩子没考好怎么办
孩子考试成绩不好怎么办
孩子成绩不好怎么办
英语成绩不好怎么办
自考准考证丢失怎么办
英国读研挂科怎么办
高中会考不及格怎么办
初中会考不及格怎么办
生地会考没考好怎么办
被骗30万元钱怎么办
长沙市图书馆怎么办卡
长沙图书馆怎么办卡
邯郸市图书馆怎么办卡
图书馆借书丢了怎么办
上海图书馆怎么办卡
双流图书馆怎么办卡
湖北省图书馆怎么办卡
武汉图书馆怎么办卡
云南省图书馆怎么办卡
车辆合格证丢失怎么办
车辆丢失怎么办
车辆保单丢失怎么办
高校通用借书证怎么办
借书卡怎么办地址
广西柳州借书卡怎么办
温州市图书馆怎么办卡
邯郸图书馆怎么办卡
小孩成绩不好怎么办