天天看点

系统调用捕获和分析—修改内核方法添加系统调用

本文为毕业设计过程中学习相关知识、动手实践记录下来的完整笔记,通过阅读本系列文章,您可以从零基础了解系统调用的底层原理并对系统调用进行拦截。由于本人能力有限,文章中可能会出现部分错误信息,如有错误欢迎指正。

完整系列文章列表

系统调用捕获和分析—通过ptrace获取系统调用信息

系统调用捕获和分析—通过strace获取系统调用信息

系统调用捕获和分析—必备的系统安全的知识点

系统调用捕获和分析—使用LKM方法添加系统调用

文章目录

  • 编译新内核
  • 通过修改内核添加系统调用

编译新内核

实验环境使用ubuntu16.04,内核版本4.15.0-112-generic,安装4.13.10版本内核。

安装依赖环境

sudo apt-get install libncurses5-dev libssl-dev  
sudo apt-get install build-essential openssl  
sudo apt-get install zlibc minizip  
sudo apt-get install libidn11-dev libidn11
sudo apt-get install bison
sudo apt-get install libelf-dev
sudo apt-get install flex
sudo apt-get install vim-gtk      

官网​

​https://www.kernel.org/​

​下载linux-4.13.10.tar.xz,放到/usr/src目录下,并解压。

sudo cp ./linux-4.13.10.tar.xz /usr/src
cd /usr/src
sudo tar -xavf linux-4.13.10.tar.xz      

查看当前内核版本​

​uname -r​

将当前内核目录下的config文件拷贝到下载的新内核源码根目录​

​sudo cp /usr/src/linux-headers-4.15.0-112-generic/.config ./​

[非必要] 配置选项​

​sudo make menuconfig​

​​,加载.config文件​

​选择Load​

​​和​

​ok​

​​,​

​save​

​​和​

​ok​

​​,最后​

​exit​

​(可以理解为make menuconfig 就是make oldconfig的图形版本。在将新的设定更新到.config中去的同时,将原来的.config文件保存为.config.old)。

进行配置​

​sudo make oldconfig​

​。

执行编译​

​sudo make -j5​

​ ,

​sudo make modules_install​

出现报错​

​make[1]: *** 没有规则可制作目标“debian/canonical-certs.pem”,由“certs/x509​

编辑刚才的config文件,将其中CONFIG_SYSTEM_TRUSTED_KEYS="debian/canonical-certs.pem"引号中内容删除。

安装内核二进制映像​

​sudo make install​

更新grub引导​

​sudo update-grub2​

重启电脑​

​sudo reboot​

​,开机过程中按esc键选择新版本内核进入。

使用​

​uname -r​

​查看内核已被更新为新的版本。

make相关说明

直接make不加任何参数就是make all,包含make modules。

make bzImage是编译系统内核;

make相当于执行了make bzImage和make modules。

make modules是单独编译模块,驱动被配置成M的都是modules,modules不会被编译进内核image,需要单独安装到rootfs。

make modules_install是把编译好的模块拷贝到系统目录下(一般是/lib/modules/)。

make install是安装内核二进制映像, 生成并安装boot初始化文件系统映像文件。

make oldconfig是用当前的.config作为基础,按相互依赖关系重新生成一个.config文件。如果新生成的.config文件和作为基础的.config文件不一致。就把作为基础的.config重命名为.config.old,用于恢复对.config的修改。

通过修改内核添加系统调用

在上面下载解压好内核源文件后,进行下面的工作添加一个自定义的系统调用。

修改​

​/usr/src/linux-4.13.10/arch/x86/entry/syscalls/syscall_64.tbl​

​,添加系统调用号。

系统调用捕获和分析—修改内核方法添加系统调用

在目录​

​/usr/src/linux-4.13.10/arch/x86/kernel/​

​下添加一个文件syshello.c,其中是添加的系统调用。

#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/sched.h>

int sys_hello(void){
    printk("oh~ hello world");
    return 5;
}      

修改​

​/usr/src/linux-4.13.10/arch/x86/kernel/Makefile​

​文件,添加编译syshello.o文件

系统调用捕获和分析—修改内核方法添加系统调用

修改​

​usr/src/linux-4.13.10/include/linux/syscalls.h​

​,文件末尾增加函数声明。(vim编辑器用shift+g跳到文件末尾)

系统调用捕获和分析—修改内核方法添加系统调用

将当前内核目录下的config文件拷贝到下载的新内核源码根目录​

​sudo cp /usr/src/linux-headers-4.15.0-112-generic/.config ./​

​,接下来和上面编译内核的步骤一样。

1.编辑刚才的config文件,将其中CONFIG_SYSTEM_TRUSTED_KEYS="debian/canonical-certs.pem"引号中内容删除。
2.sudo make clean
3.进行配置sudo make oldconfig
4.执行编译sudo make -j5
5.sudo make modules_install
6.sudo make install
7.sudo update-grub2
8.sudo reboot
9.开机按esc键选高级选项,选择新版本内核进入
10.uname -r验证是否进入新版本内核系统      

测试系统调用是否添加成功

准备测试程序a.c

#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>

int main(){
  int res = syscall(333);  333就是刚才添加的系统调用号
  printf("res = %d\n", res);
}      

编译运行,dmesg查看内核打印信息

gcc -o a a.c
./a