在开始前你应该首先完成syzkaller的安装与基础测试:https://blog.csdn.net/m0_46161993/article/details/112981753
环境
虚拟机:VMware Ubuntu 16.04
内核版本:linux-5.10.9
gcc版本:8.1.0
准备工作
下载需要测试的Linux内核到某一工作目录,笔者放在~/workspace
目录下,同时解压该文件。
编译安装较高版本的GCC,笔者为8.1.0版本。
添加自定义的系统调用
进入下载的内核目录下。主要修改一下三个文件:./include/linux/syscalls.h
、./kernel/sys.c
和./arch/x86/entry/syscalls/syscall_64.tbl
。
添加头文件声明
在./include/linux/syscalls.h
文件尾部添加如下函数声明:
asmlinkage long sys_mycopy(char* dst, char* buf, int len);
asmlinkage long sys_fuzzertest(char* user, int len);
添加函数定义
在./kernel/sys.c
文件尾部添加如下函数定义(由于sys_fuzzertest()函数中存在对新系统调用sys_mycopy()函数的调用,且由于较高版本的内核使用SYSCALL_DEFINEx
宏来完成函数定义的展开,对直接使用asmlinkage long func_name(...)
的方式不再支持,因此学习Linux内核的写法来完成函数定义):
long __sys_mycopy (char* dst, char* buf, int len) {
int i;
printk("In the mycopy func.\n");
for (i = 0; i < len && buf[i]; i++) {
dst[i] = buf[i];
}
dst[i] = 0;
return i;
}
SYSCALL_DEFINE3 (mycopy, char*, dst, char*, buf, int, len) {
return __sys_mycopy(dst, buf, len);
}
long __sys_fuzzertest (char* user, int len) {
char buf[16];
int i, test;
printk("In the fuzzertest func.\n");
__sys_mycopy(buf, user, len);
if (len > 64) {
test = 0;
i = 16 / test;
return i;
}
return 0;
}
SYSCALL_DEFINE2 (fuzzertest, char*, user, int, len) {
return __sys_fuzzertest(user, len);
}
声明系统调用号
在./arch/x86/entry/syscalls/syscall_64.tbl
文件中为函数分配系统调用号。注意:系统调用号添加的位置很有讲究,否则会失败,具体如下:
由于该文件中存在如下注释1
:
因此系统调用号应该添加在423号之后。又因为该文件中还存在如下注释2
:
因此系统调用号应添加在注释2之前。故添加如下:
重新编译内核
在下载的内核目录下执行如下操作:
make CC="$GCC/bin/gcc" defconfig
make CC="$GCC/bin/gcc" kvmconfig # 该命令可能报错,错误可以忽略
执行结束后会出现.config
文件,在其中找到如下参数,并对其进行替换(注意是替换不是添加,要在原有的位置进行替换):
CONFIG_KCOV=y
CONFIG_DEBUG_INFO=y
CONFIG_KASAN=y #这个默认配置中可能没有,需要添加
CONFIG_KASAN_INLINE=y #这个默认配置中可能没有,需要添加
CONFIG_CONFIGFS_FS=y
CONFIG_SECURITYFS=y
接着执行如下命令即可:
make CC="$GCC/bin/gcc" olddefconfig
make CC="$GCC/bin/gcc" -j8
测试可否使用qemu进入该指定内核的虚拟机
使用root
身份可无密码进入:
sudo qemu-system-x86_64 \
-kernel /home/lyg/workspace/source/linux-5.10.9/arch/x86/boot/bzImage \
-append "console=ttyS0 root=/dev/sda debug earlyprintk=serial slub_debug=QUZ"\
-hda /home/lyg/workspace/source/image/stretch.img \
-net user,hostfwd=tcp::10021-:22 -net nic \
-enable-kvm \
-nographic \
-m 2G \
-smp 2 \
-pidfile vm.pid \
2>&1 | tee vm.log
观察到可正常启动。
syzkaller漏洞测试
在syzkaller/sys/linux
中添加描述文件fuzzer.txt
,测试新的系统调用,文件如下:
include <linux/fs.h>
fuzzertest$proc(buf buffer[in], count len[buf])
(如果你的syzkaller/bin目录下没有syz-extract文件,要执行这条)由于原有syzkaller暗中的Makefile默认安装中不包含bin/extract
,但是在进行测试系统调用时需要该文件,因此需要手动再make一下,具体如下:
make bin/extract
在syzkaller
目录下执行如下命令:
sudo ./bin/syz-extract -os linux -arch amd64 -sourcedir "/home/lyg/workspace/source/linux-5.10.9" fuzzer.txt #生成const文件
sudo ./bin/syz-sysgen
make clean #需要重新编译
make
在syzkaller-master
目录下的my.cfg
文件中添加如下选项:
"enable_syscalls": [ "fuzzertest$proc" ]
(my.cfg原来内容如下:)
{
"target": "linux/amd64",
"http": "127.0.0.1:56741",
"workdir": "/home/lyg/workspace/fuzz/syzkaller/src/github.com/google/syzkaller/workdir",
"kernel_obj": "/home/lyg/workspace/source/linux-5.10.9",
"image": "/home/lyg/workspace/source/image/stretch.img",
"sshkey": "/home/lyg/workspace/source/image/stretch.id_rsa",
"syzkaller": "/home/lyg/workspace/fuzz/syzkaller/src/github.com/google/syzkaller",
"procs": 8,
"type": "qemu",
"vm": {
"count": 4,
"kernel": "/home/lyg/workspace/source/linux-5.10.9/arch/x86/boot/bzImage",
"cpu": 1,
"mem": 1024
}
}
在syzkaller-master
目录下运行syzkaller并使用浏览器查看,如下:
sudo ./bin/syz-manager -config=my.cfg
观察到可以看到该漏洞出现在系统调用的mycopy
函数中,如下图: