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