Linux内核监控模块-2-系统调用表地址的获取(Linux内核版本3.13)

那么在Linux内核2.6之后,不能直接导出sys_call_table的地址后,我们要如何获得系统调用表的地址,从而实现系统调用的截获呢。

先贴上我实现好的代码,然后再来讲解吧。

modu.c

#include<linux/init.h>
#include<linux/module.h>
#include<linux/moduleparam.h>
#include<linux/unistd.h>
#include<linux/sched.h>
#include<linux/syscalls.h>
#include<linux/string.h>
#include<linux/fs.h>
#include<linux/fdtable.h>
#include<linux/uaccess.h>

#include<linux/rtc.h>

MODULE_LICENSE("Dual BSD/GPL");

#define _DEBUG
#ifdef _DEBUG
#define kprintk(fmt,args...) printk(KERN_ALERT fmt,##args)
#define kprintf(fmt,args...) printf(fmt,##args)
#define kperror(str) perror(str)
#else
#define kprintk
#define kprintf
#define kperror
#endif

/*Function declaration*/
long * get_sys_call_table(void);

long * g_sys_call_table=NULL;//save address of sys_call_table

struct _idtr{
    unsigned short limit;
    unsigned int base;
}__attribute__((packed));

struct _idt_descriptor{
    unsigned short offset_low;
    unsigned short sel;
    unsigned char none,flags;
    unsigned short offset_high;
}__attribute__((packed));

/*Get the address of sys_call_table*/
long * get_sys_call_table(void){

    struct _idt_descriptor * idt;
    struct _idtr idtr;
    unsigned int sys_call_off;
    int sys_call_table=0;
    unsigned char* p;
    int i;
    asm("sidt %0":"=m"(idtr));
    kprintk("   address of idtr: 0x%x\n",(unsigned int)&idtr);
    idt=(struct _idt_descriptor *)(idtr.base+8*0x80);
    sys_call_off=((unsigned int)(idt->offset_high<<16)|(unsigned int)idt->offset_low);
    kprintk("   address of idt 0x80: 0x%x\n",sys_call_off);
    p=(unsigned char *)sys_call_off;
    for(i=0;i<100;i++){
        if(p[i]==0xff&&p[i+1]==0x14&&p[i+2]==0x85){
            sys_call_table=*(int*)((int)p+i+3);
            kprintk("   address of sys_call_table: 0x%x\n",sys_call_table);

            return (long*)sys_call_table;
        }
    }

    return 0;
}

int monitor_init(void){
    kprintk("Monitor init\n");
    g_sys_call_table = get_sys_call_table();
    return 0;
}

void monitor_exit(void){
    kprintk("Monitor exit\n");
}

module_init(monitor_init);
module_exit(monitor_exit);

Makefile

obj-m := modu.o
KERNELDIR := /lib/modules/3.13.0-32-generic/build
PWD := $(shell pwd)
modules:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

将modu.c和Makefile放在同一个目录下,执行“make”,编译程序,会生成modu.ko文件。

执行“sudo insmod modu.ko”,将modu.ko加载到内核中。

执行“dmesg”,查看系统日志,如图。

接下来就要解释解释原理了。

我们知道Linux系统中的系统调用是通过用户软件调用中断int0x80激发的,int0x80被执行后,内核获得CPU的控制权,并交由system_call程序处理。即sys_call_table是由system_call进行调用的。

而system_call是int0x80软中断,即int0x80中断对应的地址就是system_call函数的地址。而Linux系统中所有中断信息都保存在一张中断描述表IDT中,而这张表的地址又是保存在IDTR寄存器里面,所以整个截获过程可以用如下图表示。

即先在IDTR寄存器中获得IDT_TABLE的地址,再在IDT_TABLE中获得int0x80的地址,int0x80对应的是system_call函数的地址。最后通过system_call函数的地址获得sys_call_table的地址。

时间: 2024-10-14 02:04:43

Linux内核监控模块-2-系统调用表地址的获取(Linux内核版本3.13)的相关文章

linux内核编程入门--系统调用监控文件访问

参考的资料: hello world   https://www.cnblogs.com/bitor/p/9608725.html linux内核监控模块——系统调用的截获  https://www.cnblogs.com/lxw315/p/4773566.html 实现: 实验目的: 内核模块的编写:完成一个Linux/Windows内核/驱动模块的编写, 能够实现对文件访问的监控.或者对键盘设备.USB设备.网络设备. 蓝牙设备等的监控. 实验内容: 通过linux内核模块编程,写一个模块使

linux下系统调用、API、系统命令,内核函数的区别与联系

1.系统调用: 应用程序和内核间的桥梁,是应用程序访问内核的入口点;但通常情况下,应用程序通过操作系统提供的API进行编程而不是使用系统调用直接编程; linux的全部系统调用加起来大约只有250个左右. 2.API: API常以c库(libc)的形式提供,c库提供了绝大部分API,每个系统调用在c库中都有对应的封装函数(通常封装函数与系统调用的名称相同).系统调用与c库函数并不是一一对应的,有些c库函数可能使用多个系统调用来实现,也有可能多个c库函数使用同一个系统调用来实现,也有些c库函数不使

linux内核学习之四 系统调用

一  概念区分 提到linux系统调用,不得不区分几个比较容易混淆的概念: 系统调用:系统调用就是一种特殊的接口.通过这个接口,用户可以访问内核空间.系统调用规定了用户进程进入内核的具体位置. 应用程序接口(API,Application Programming Interface):是一些预定义的函数.API提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节. c库:c库实现了linux的主要API,包括标准的C库函数和系统调用.同时lin

多种方法获取sys call table linux系统调用表 的地址

一.方法一:常用方式,也是一google一堆的方式 我们首先需要找到call table-with-offset的特征,先看下面的代码 syscall_call: call *sys_call_table(,%eax,4) 假设我们没有vmlinux可供gdb反汇编,那也只有采用模拟的方式了,模拟出一个call *sys_call_table(,%eax,4),然后看其机器码,然后在system_call的附近基于这个特征进行寻找 :void fun1() { printf("fun1/n&qu

linux内核分析——扒开系统调用的三层皮(下)

20135125陈智威 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 实验目的: 通过以一个简单的menu小程序,跟踪系统调用的过程,分析与总结系统调用的机制和三层进入的过程. 实验原理: 系统调用是通过软中断指令 INT 0x80 实现的,而这条INT 0x80指令就被封装在C库的函数中.(软中断和我们常说的硬中断不同之处在于,软中断是由指令触发的,而不是由硬件外设引起的.)IN

Linux内核监控模块-3-系统调用的截获

上一章,我们获取了系统调用表的地址,这里我们来搞点所谓“截获”的事情.所谓“截获”即是将系统调用表里的地址指向我们自己写的一个函数,系统调用先执行我们自己写的函数,处理完后,再返回原来系统调用的执行函数. 还是先贴代码吧. modu.c #include<linux/init.h> #include<linux/module.h> #include<linux/moduleparam.h> #include<linux/unistd.h> #include&

Linux内核中添加系统调用接口简单示例

1. Linux体系结构 Linux系统的地址空间分为用户空间和内核空间,通过系统调用和硬件中断能够完成从用户空间到内核空间的转移. 2. 系统调用接口 ① 一般情况下,用户进程不能访问内核空间.Linux内核中提供了一组用于实现各种系统功能的子程序,用户可以调用它们访问Linux内核的数据和函数,这些子程序称为系统调用接口(SCI). ② 系统调用和普通函数的区别:系统调用由操作系统内核实现,运行于内核态:普通函数调用由函数库或用户自己提供,运行于用户态. 3. 系统调用分类:主要分3大类 ①

编译 linux 内核及添加系统调用

后面编译的是 4.2.2 在 gcc4.8 上编译4.14.14 时报不支持堆栈保护 反正都差不多就先编译了 4.2.21.下载 linux 内核源码2.解压放到 /usr/src3.创建软连接 (不一定非得打文件放到 /usr/src 看个人我直接放桌面) [email protected]:~# cd /usr/src [email protected]:/usr/src# ls linux-4.14.14 linux-headers-4.2.0-27-generic linux-heade

分析Linux内核5.0系统调用处理过程

学号: 363 本实验来源 https://github.com/mengning/linuxkernel/ 一.实验要求 1.编译内核5.02.qemu -kernel linux-5.0.1/arch/x86/boot/bzImage -initrd rootfs.img3.选择系统调用号后两位与您的学号后两位相同的系统调用进行跟踪分析https://github.com/mengning/menu4.给出相关关键源代码及实验截图,撰写一篇博客(署真实姓名或学号最后3位编号),并在博客文章中