如何在Linux中添加新的linux下添加系统调用用

您的位置:
在linux操作系统中如何截获系统调用
相关栏目:
介绍:在linux操作系统中如何截获系统调用,在linux操作系统中如何截获系统调用
难度:初级
& 作者: Luster 出处: LinuxAid   使用Linux Kernel Module的一般目的就是扩展系统的功能,或者给某些特殊的设备提供驱动等等。其实利用Linux内核模块我们还可以做一些比较“黑客”的事情,例如用来拦截系统调用,然后自己处理。嘿嘿,有意思的说。  下面给出一个简单的例子,说明了其基本的工作过程。#define MODULE#define __KERNEL__#include &linux/module.h#include &linux/kernel.h#include &asm/unistd.h#include &sys/syscall.h#include &linux/types.h#include &linux/dirent.h#include &linux/string.h#include &linux/fs.h#include &linux/malloc.hextern void* sys_call_table[]; /*sys_call_table is exported, so we can access it*/int (*orig_mkdir)(const char *path); /*the original systemcall*/int hacked_mkdir(const char *path){return 0; /*everything is ok, but he new systemcalldoes nothing*/}int init_module(void) /*module setup*/{orig_mkdir=sys_call_table[SYS_mkdir];sys_call_table[SYS_mkdir]=hacked_return 0;}void cleanup_module(void) /*module shutdown*/{sys_call_table[SYS_mkdir]=orig_ /*set mkdir syscall to the origalone*/}  大家看到前面的代码了,非常简单,我们就是替换了内核的系统调用数组中我们关心的指针的值,系统调用在内核中实际就是一个数组列表指针对应的函数列表。我们通过替换我们想“黑”的函数的指针,就可以达到我们特定的目的。这个例子中我们替换了“mkdir”这个函数。这样,用户的应用程序如果调用mkdir后,当内核响应的时候,实际上是调用我们“黑”了的函数,而我们实现的函数里面是什么都没有干,所以这里会导致用户运行“mkdir”得不到结果。这个例子很简单,但是我们可以看出,如果我们想截获一个系统调用,那么我们只需要做以下的事情:  1.查找出感兴趣的系统调用在系统内核数组中的入口位置。可以参看include/sys/ syscall.h文件。  2.将内核中原来的调用函数对应的指针sys_call_table[X]保留下来。  3.将我们新的伪造的系统函数指针给sys_call_table[X]。&
来源:/n/0106.html
分享给朋友:
拥有教程:593个
共有学生:19位
相关知识点linux下添加系统调用
一、实验目的
学习Linux内核的系统调用,理解、掌握Linux系统调用的实现框架、用户界面、参数传递、进入/返回过程。阅读Linux内核源代码,通过添加一个简单的系统调用实验,进一步理解Linux操作系统处理系统调用的统一流程。
二、实验内容
在现有的系统中添加一个不用传递参数的系统调用。这个系统调用的功能是实现遍历进程。实验主要内容:
l& 添加系统调用的名字
l& 利用标准C库进行包装
l& 添加系统调用号
l& 在系统调用表中添加相应表项
l& sys_mysyscall的实现
l& 编写用户态测试程序
三、主要仪器设备(必填)
Linux环境:utuntu10.10,linux内核2.6.36
待编译内核:linux2.6.36
四、操作方法和实验步骤
【1】下载并部署内核源代码
&&&&&& 此步已经在实验2中完成。
【2】添加系统调用号
&&&&&& 系统调用号在文件unistd.h里面定义。这个文件在ubuntu10.10下位于/usr/include/asm/unistd_32.h。现在我们在unistd.h中添加我们的系统调用号:__NR_mysyscall,如下所示:
&&& 231 #define __NR_mysyscall&&&&&&&&&&&&&&&&&&&&&&&&&& &&&& 223&& &&&/*添加或修改为mysyscall */
/* 注意:不同版本的内核系统调用号不一样,您可以根据内核版本不同对系统调用号进行修改*/
&&&&&& 添加系统调用号之后,系统才能根据这个号,作为索引,去找syscall&_table中的相应表项。
【3】在系统调用表中添加或修改相应表项
&&&&&& 我们知道,系统调用处理程序(system_call)会根据eax中的索引到系统调用表(sys_call_table)中寻找相应的表项。所以,我们必须在那里添加我们自己的一个值。
&&&&&& 在2.6.36的内核下,只需要修改arch/x86/kernel/syscall_table_32.S。注意,修改该文件首先要切换到root权限,此外使用gedit打开该文件时注意它的扩展名是大写的S。
233&&&&&&&& .long sys_mysyscall &&&&&/*在对应的位置修改或添加*/
234&&&&&&&& .long sys_gettid
235 &&&&&&&&.long sys_readahead &&&&&&&&&&&&&&&&&&&&&&/* 225 */
&&&&&& 到现在为止,系统已经能够正确地找到并且调用sys_mysyscall。剩下的就只有一件事情,那就是sys_mysyscall的实现。
【4】sys_mysyscall的实现
&&&&&& 我们把一小段程序添加在kernel/sys.c里面。在这里,我们并没有在kernel目录下另外添加自己的一个文件,这样做的目的是为了简单,而且不用修改makefile,省去不必要的麻烦。
&&&&&& mysyscall系统调用实现遍历系统中的所有的进程,并打印每个进程的进程名字,进程标识符,进程的状态和父进程的标识符。
&&&&&& 进程名字、pid、进程状态、父进程的指针在task-struct结构的字段中。在内核中使用printk函数打印有关变量的值。遍历进程可以使用next_task宏,init_task进程为0号进程。
& asmlinkage int sys_mysyscall(void)
&&&&&&&&&&&&& //在此处加入遍历进程的代码;
&&&&&&&&&&&&& return 0;
【5】重新编译内核
&&&&&& 一定要重新编译内核。内核编译完成后,重新启动编译后的新内核。
【6】编写用户态程序
&&&&&& 要测试新添加的系统调用,需要编写一个用户态测试程序(test.c)调用mysyscall系统调用。mysyscall系统调用中printk函数输出的信息在/var/log/message文件中。也可以在shell下用dmesg命令查看。
用户态测试程序可以用如下方法实现
650) this.width=650;" onclick='window.open("/viewpic.php?refimg=" + this.src)' alt="圆角矩形标注: 系统调用号根据实验具体数字而定" width="244" height="61" src="/upload//80.gif" />#include &linux/unistd.h&
# include &sys/syscall.h&
#define __NR_ mysyscall 223
int main()
syscall(__NR_mysyscall);& &&/*或syscall(223)& */
//在此加入在屏幕输出每个进程相关信息的代码;
l& 用gcc编译源程序
# gcc &o test test.c
l& 运行程序
l& 用shell命令查看遍历进程输出的信息
五、实验结果和分析
【1】&& 在ubuntu10.10下位于/usr/include/asm/unistd_32.h。现在我们在unistd.h中添加我们的系统调用号:__NR_mysyscall,如下图
231 #define __NR_mysyscall&&&&&&&&&&&&&&& &&&& 223&&&
【2】在系统调用表中添加相应表项,即修改arch/x86/kernel/syscall_table_32.S。如下图
650) this.width=650;" onclick='window.open("/viewpic.php?refimg=" + this.src)' alt="" width="218" height="25" src="/upload//91.gif" />
650) this.width=650;" onclick='window.open("/viewpic.php?refimg=" + this.src)' border="0" alt="" src="/upload//02.png" />
【3】sys_mysyscall的实现,我们把一小段程序添加在kernel/sys.c里面,如下图
650) this.width=650;" onclick='window.open("/viewpic.php?refimg=" + this.src)' border="0" alt="" src="/upload//13.png" />
其中task是进程结构指针,task-&comm是进程名,task-&pid是进程id,task-&state是进程状态,task-&parent-&pid是进程的父进程id。
【4】重新编译内核。成功后,重启。此时,在启动项中有2.6.36和2.6.36old两个选项,其中新的内核是2.6.36。选择它并进入系统。至此,我们已经成功添加了一个自己的系统调用。
【5】编写用户态程序test.c,代码如下
#include&&stdio.h&
#include&&stdlib.h&
#include&&sys/types.h&
#include&&sys/stat.h&
#include&&fcntl.h&
#include&&time.h&
#include&&string.h&
#define&__NR_mysyscall&223
int&main()
syscall(223);&//系统调用
char&temp[40];&//缓冲区
char&m_time[16];&//存放所需要的特定格式的当前时间
time(&mytime);&//得到当前时间
strcpy(temp,ctime(&mytime));//把某种格式的当前时间的内容存入缓冲区
//对当前时间格式化使之与messages文件中时间格式对应
while(i&15)
m_time[i]=temp[i+4];&//从第4个字符开始复制
char&ch2[16];
fp=fopen(&/var/log/messages&,&r&);&//以流的方式打开文件
int&flag=0;
while(!feof(fp))
mm=fgetc(fp);
if(mm=='\n'&&&&flag==0)
fgets(ch2,16,fp);&//得到某行的前16个字符,即时间
if(strncmp(ch2,m_time,15)==0)&//判断是否与当前时间相同
{//如果messages中时间为当前时间则输出
fseek(fp,-15,SEEK_CUR);
if(flag==1&&&&mm!=EOF)
printf(&%c&,mm);
fclose(fp);
&&& 详细的注释见代码
&&&&程序运行后得到的截图如下
650) this.width=650;" onclick='window.open("/viewpic.php?refimg=" + this.src)' border="0" alt="" src="/upload//24.png" />
&&&&&& 在终端输入dmesg后得到的截图如下
650) this.width=650;" onclick='window.open("/viewpic.php?refimg=" + this.src)' border="0" alt="" src="/upload//35.png" />
&&&&&& 使用gedit查看/var/log/message文件,截图如下
650) this.width=650;" onclick='window.open("/viewpic.php?refimg=" + this.src)' border="0" alt="" src="/upload//46.png" />
六、讨论、心得
1、编译过一次内核后,由于.o文件都在存在,所以第二次编译时间非常快,本次实验,编译只用了10分钟左右。
2、添加一个系统调用类似于MFC中添加一个自定义的消息,首先要注册这个消息,以便系统知道有这么个消息,然后用户在程序中才能使用它。
4、在2.6.36中,有unistd.h,unistd_32.h,unistd_64.h,其实unistd.h中的内容只有几句代码,用来判断要使用unistd_32.h还是unistd_64.h。所以,平时我们在编写程序时引入头文件unistd.h,其实是引入了unistd_32.h(前提是你的机器是32位的,64位的同理)。
3、在编写test.c时,通过搜索互联网、查看c语言的相关书籍以及和同学的探讨,深入理解和运用了相关的流文件函数,包括fopen,fgetc,fgets,fseek等。对c的流文件操作是这次实验收获最大的,尤其是文件指针的定位。
&晓伟的sky
文章评论 以下网友留言只代表其个人观点,不代表本网站的观点和立场。增加新的系统调用_图文_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
增加新的系统调用
上传于||暂无简介
大小:173.50KB
登录百度文库,专享文档复制特权,财富值每天免费拿!
你可能喜欢第七下载是国内最新、最齐、最安全的软件下载基地!
当前位置:
在Linux中添加新的系统调用方法
& 作者:佚名 & 来源:本站整理 & 浏览:518 & 评论: &
.long SYMBOL_NAME(sys_mycall)
(3) 重建新的Linux内核
为使新的系统调用生效,需要重建Linux的内核。这需要以超级用户身份登录。
/usr/src/linux
超级用户在当前工作目录(/usr/src/linux)下,才可以重建内核。
#make config
#make clearn
#make bzImage
编译完毕后,系统生成一可用于安装的、压缩的内核映象文件:
/usr/src/linux/arch/i386/boot/bzImage
(4) 用新的内核启动系统
要使用新的系统调用,需要用重建的新内核重新引导系统。为此,需要修改/etc/lilo.conf文件,在我们的系统中,该文件内容如下:
boot=/dev/hda
map=/boot/ma
install=/boot/boot.b
timeout=50
image=/boot/vmlinuz-2.2.5-15
label=linux
root=/dev/hdb1
other=/dev/hda1
table=/dev/had
首先编辑该文件,添加新的引导内核:
image=/boot/bzImage-new
label=linux-new
root=/dev/hdb1
添加完毕,该文件内容如下所示:
boot=/dev/hda
map=/boot/ma
install=/boot/boot.b
timeout=50
image=/boot/bzImage-new
label=linux-new
root=/dev/hdb1
image=/boot/vmlinuz-2.2.5-15
本文地址:在Linux中添加新的系统调用方法由整理并发布,欢迎转载!
顶一下(431)
踩一下(53)
3395723425200441236298839183911082618197814658965831529550944870
8 GB5.79 MB4.59 MB17.39 MB25.08 MB429 KB2.58 MB41.7 MB537 KB532 KB3264人阅读
Linux(21)
本文以linux-3.5.4内核、x86平台、64位,为例进行说明。
添加新的系统调用,共需修改3处文件:
(1)分配系统调用号:include/asm-generic/unistd.h
(2)修改系统调用表:arch/x86/syscalls/syscall_64.tbl。较早版本的内核,修改的是arch/x86/kernel/syscall_table_32.S文件。
(3)添加处理函数:kernel/sys.c,(不是必须在这个文件中添加,可在其他文件或新建文件)
1、分配系统调用号
修改include/asm-generic/unistd.h文件,设系统调用号为313,不冲突即可。同时修改__NR_syscalls的&#为273。
#define __NR_mysyscall 313
__SYSCALL(__NR_mysyscall, sys_mysyscall)
#undef __NR_syscalls
#define __NR_syscalls 273
2、修改系统调用表
修改arch/x86/syscalls/syscall_64.tbl文件,根据原有表内容的格式,在322行处添加如下内容
sys_mysyscall
3、添加处理函数
修改kernel/sys.c文件。添加不带参数的系统调用处理函数。
SYSCALL_DEFINE0(mysyscall)
//在此处加入遍历进程的代码
struct task_struct *p;
printk(&********************************************\n&);
printk(&------------the output of mysyscall------------\n&);
printk(&********************************************\n\n&);
printk(&%-20s %-6s %-6s %-20s\n&,&Name&,&pid&,&state&,&ParentName&);
for(p = &init_ (p = next_task(p)) != &init_)
printk(&%-20s %-6d %-6d %-20s\n&,p-&comm , p-&pid, p-&state, p-&parent-&comm);
4、系统调用测试程序
编写简单的测试程序
#include &linux/unistd.h&
#include &sys/syscall.h&
//系统调用号根据实验具体
#define __NR_mysyscall 313
//数字而定
int main()
syscall(__NR_mysyscall); /*或 syscall(313) */
编译新内核并启动,编译测试程序,在新启动的内核中执行测试程序,并利用dmesg命令查看输出信息。
本文利用的是qemu工具启动新内核,并进行相关测试。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:266946次
积分:3289
积分:3289
排名:第6214名
原创:69篇
转载:32篇
评论:54条
(1)(4)(2)(3)(2)(1)(1)(2)(2)(1)(7)(6)(1)(1)(3)(1)(2)(10)(3)(3)(3)(4)(2)(2)(6)(2)(1)(8)(13)(6)

我要回帖

更多关于 linux系统调用 的文章

 

随机推荐