记录一下安装使用QEMU+busybox搭建Linux内核运行环境的过程
参考以下文章来操作的
[23R3F’s blog - kernel pwn初探](https://23r3f.github.io/2019/05/15/kernel pwn初探/)
ZoE’s blog - 核环境搭建和基础知识
编译内核 安装依赖
1 2 3 4 sudo apt-get update sudo apt-get install bison sudo apt-get install flex sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc
下载linux kernel源码 ,我选择了4.19.65版本的tar.gz包
1 2 3 tar -zxvf ./linux-4.19.65.tar.gz cd ./linux-4.19.65/ sudo make menuconfig
进入kernel hacking
1 2 3 4 5 6 勾选以下项目 Kernel debugging Compile-time checks and compiler options —> Compile the kernel with debug info和Compile the kernel with frame pointers KGDB 然后保存退出 sudo make bzImage
完成编译, 得到一个bzImage
关于各种类型的内核的各种形式:
bzImage是vmlinuz经过gzip压缩后的文件,适用于大内核
vmlinux是未压缩的内核
vmlinuz是vmlinux的压缩文件。
vmlinux 是ELF文件,即编译出来的最原始的文件。
vmlinuz应该是由ELF文件vmlinux经过OBJCOPY后,并经过压缩后的文件
zImage是vmlinuz经过gzip压缩后的文件,适用于小内核
编译busybox
busybox是Linux上的一个应用程序 它整合了许多Linux上常用的工具和命令 IBM的一篇关于busybox的文章 文章地址,写的很详细。
busyboxz主要有这些功能
busybox是Linux上的一个应用程序
它整合了许多Linux上常用的工具和命令
由于启动内核还需要一个简单的文件系统和一些命令,而busybox就是用来完成生成简单文件系统的
先下载busybox ,我选择了busybox-1.31.1.tar.bz2
1 2 3 4 5 6 下载好后解压 cd ./busybox-1.31.1/ make menuconfig 进入 Settings 勾选 Build static binary (no shared libs) make install
目录下就会生成一个_install 文件夹,就是编译结果,进入这个文件夹进行配置
1 2 3 4 5 cd _install mkdir proc mkdir sys touch init gedit init
编辑init:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/bin/sh echo "{==DBG==} INIT SCRIPT" mkdir /tmpmount -t proc none /proc mount -t sysfs none /sys mount -t debugfs none /sys/kernel/debug mount -t tmpfs none /tmp mdev -s echo -e "{==DBG==} Boot took $(cut -d' ' -f1 /proc/uptime) seconds" setsid /bin/cttyhack setuidgid 1000 /bin/sh
几个常见命令
insmod : 指定模块加载到内核中
rmmod : 从内核中卸载指定模块
lsmod : 列出已经加载的模块
在_install目录下find . | cpio -o --format=newc > ./rootfs.img
将文件夹里的内容打包成一个文件系统。
安装qemu 建议先把apt源更换成国内的,不然会很慢。清华源: https://mirror.tuna.tsinghua.edu.cn/help/ubuntu/
1 2 3 4 5 安装依赖 sudo apt-get install libncurses5-dev sudo apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev 安装QEMU sudo apt-get install qemu
输入qemu
+ TAB键,如果出现很多补全提示说明安装成功
QEMU启动kernel 将第一步编译出的bzImage文件和第二部打包出来的rootfs.img文件复制进一个新的目录下,并在目录下新建一个boot.sh作为启动脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 #!/bin/sh qemu-system-x86_64 \ -m 64M \ -kernel ./bzImage \ -initrd ./rootfs.img \ -append "root=/dev/ram rw oops=panic panic=1 kalsr" \ -netdev user,id =t0, -device e1000,netdev=t0,id =nic0 \ -monitor /dev/null \ -smp cores=2,threads=1 \ -cpu kvm64,+smep \
sh启动脚本中的一些命令解释
-m
是指定RAM大小(默认384)
-kernel
是指定的内核镜像,这里是我们编译的镜像路径,也可以是下载好的镜像,如./vmlinuz-4.15.0-22-generic
-initrd
设置刚刚利用 busybox
创建的 rootfs.img
,作为内核启动的文件系统
-append
附加选项,指定no kaslr可以关闭随机偏移
--nographic
和console=ttyS0
一起使用,启动的界面就变成当前终端
-s
相当于-gdb tcp::1234
的简写,可以直接通过主机的gdb远程连接
-monitor
配置用户模式的网络#将监视器重定向到主机设备/dev/null
-smp
用于声明所有可能用到的cpus, i.e. sockets cores threads = maxcpus.
-cpu
设置CPU的安全选项
chmod +x ./boot.sh
给启动脚本加权限后,跑起来,如图,启动成功
写一个简单驱动 在kernel源码目录下新建一个目录。并添加两个文件,mydriver.c
和Makefile
mydriver.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/cred.h> MODULE_LICENSE("Dual BSD/GPL" ); static int my_init (void ) { printk("Hello Sunxiaokong's baby driver!\n" ); printk("Size of struct cred : %ld\n" , sizeof (struct cred)); printk("Size of type atomic_t : %ld\n" , sizeof (atomic_t )); printk("Size of type void* : %ld\n" , sizeof (void *)); printk("Size of type unsigned : %ld\n" , sizeof (unsigned )); printk("Size of type kuid_t : %ld\n" , sizeof (kuid_t )); return 0 ; } static void my_exit (void ) { printk("Goodbye, baby driver!\n" ); } module_init(my_init); module_exit(my_exit);
Makefile
1 2 3 4 5 6 7 8 9 10 11 12 obj-m += mydriver.o KDIR = /home/sunxiaokong/Desktop/pwn/kernel-pwn/hello_kernel/linux-4.4.72/ all: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: rm -rf *.o *.ko *.mod.* *.symvers *.order
然后执行make
,编译得到mydriver.ko
将mydriver.ko拿进busybox的_install
目录下,编辑init文件,setuidgid 0 /bin/sh
使稍后可以使用insmod
和rmmod
指令装载和卸载驱动。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #!/bin/sh echo "{==DBG==} INIT SCRIPT" mkdir /tmpmount -t proc none /proc mount -t sysfs none /sys mount -t debugfs none /sys/kernel/debug mount -t tmpfs none /tmp mdev -s echo -e "{==DBG==} Boot took $(cut -d' ' -f1 /proc/uptime) seconds" setsid /bin/cttyhack setuidgid 0 /bin/sh
find . | cpio -o --format=newc > ./rootfs.img
将文件系统重新打包。将bzImage
、rootfs.img
放到一个目录下,写一个boot.sh
用于QEMU启动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/bin/sh qemu-system-x86_64 \ -m 64M \ -kernel ./bzImage \ -initrd ./rootfs.img \ -append "console=ttyS0 root=/dev/ram rw oops=panic panic=1 kalsr" \ -netdev user,id =t0, -device e1000,netdev=t0,id =nic0 \ -monitor /dev/null \ -smp cores=2,threads=1 \ -cpu kvm64,+smep \ --nographic
chmod +x ./boot.sh
然后./boot.sh
跑起来:
可以成功使用insmod
和rmmod
安装和卸载驱动
添加syscall 上手尝试一下添加syscall