Kernel环境搭建
内核文件类型
bzImage:目前主流的 kernel 镜像格式,即 big zImage(即 bz 不是指 bzip2),适用于较大的(大于 512 KB) Kernel。这个镜像会被加载到内存的高地址,高于 1MB。bzImage 是用 gzip 压缩的,文件的开头部分有 gzip 解压缩的代码,所以我们不能用 gunzip 来解压缩。
zImage:比较老的 kernel 镜像格式,适用于较小的(不大于 512KB) Kernel。启动时,这个镜像会被加载到内存的低地址,即内存的前 640 KB。zImage 也不能用 gunzip 来解压缩。
1
2
3
4zImage && bzImage
---------------- difference ------------------
zImage—是vmlinux经过gzip压缩后的文件。
bzImage—bz表示"big zImage",不是用bzip2压缩的,而是要偏移到一个位置,使用gzip压缩的。两者的不同之处在于,zImage解压缩内核到低端内存(第一个 640K),bzImage解压缩内核到高端内存(1M以上)。如果内核比较小,那么采用zImage或bzImage都行,如果比较大应该用bzImage。vmlinuz:vmlinuz 不仅包含了压缩后的 vmlinux,还包含了 gzip 解压缩的代码。实际上就是 zImage 或者 bzImage 文件。该文件是 bootable 的。 bootable 是指它能够把内核加载到内存中。对于 Linux 系统而言,该文件位于 /boot 目录下。该目录包含了启动系统时所需要的文件。
vmlinux:静态链接的 Linux kernel,以可执行文件的形式存在,尚未经过压缩。该文件往往是在生成 vmlinuz 的过程中产生的。该文件适合于调试。但是该文件不是 bootable 的。
vmlinux.bin:也是静态链接的 Linux kernel,只是以一个可启动的 (bootable) 二进制文件存在。所有的符号信息和重定位信息都被删除了。生成命令为:
objcopy -O binary vmlinux vmlinux.bin
。uImage:uImage 是 U-boot 专用的镜像文件,它是在 zImage 之前加上了一个长度为 0x40 的 tag 而构成的。这个 tag 说明了这个镜像文件的类型、加载位置、生成时间、大小等信息。
source code
查看当前内核版本
注解:
/proc
文件系统,它不是普通的文件系统,而是系统内核的映像- 该目录中的文件是存放在系统【内存】之中的,它以【文件系统】的方式为访问系统内核数据的操作提供接口。
- 而我们使用命令
uname -a
的信息就是从该文件获取的,当然用方法二的命令直接查看它的内容也可以达到同等效果.另外,加上参数”a”是获得【详细信息】,如果不加参数为查看系统名称。
1
2[Method 1] uname -a
[Method 2] cat /proc/version查看整个系统剩余磁盘空间
1
df -hl
查看
[1]
当前目录【总大小】,[2]
指定目录大小,[3]
当前目录下各文件、文件夹的大小1
2
3[1] du -sh
[2] du -sh [目录名称]
[3] du -h --max-depth=1 *
recently version
下载某个版本的核
1
2curl -O -L https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-5.4.98.tar.xz
unxz linux-5.4.98.tar.xz此时得到的是
.tar
文件签名验证
1
curl -O -L https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-5.4.98.tar.sign
导入
Torvalds
的公钥1
gpg --locate-keys torvalds@kernel.org gregkh@kernel.org
使用密钥(我们可以选择使用 TOFU 信任对应的密钥)并验证
1
2gpg --tofu-policy good 647F28654894E3BD457199BE38DBBDC86092693E
gpg --trust-model tofu --verify linux-5.4.98.tar.sign最终得到验证结果
1
2
3
4
5
6gpg: assuming signed data in 'linux-5.4.98.tar'
gpg: Signature made 2021年02月13日 星期六 20时54分47秒 CST
gpg: using RSA key 647F28654894E3BD457199BE38DBBDC86092693E
gpg: Good signature from "Greg Kroah-Hartman <gregkh@kernel.org>" [full]
gpg: gregkh@kernel.org: Verified 1 signatures in the past 0 seconds. Encrypted
0 messages.解压即可得到源码
1
tar -xf linux-5.4.98.tar
old version
赵炯博士维护的网站有早起
linux 0.11
和linux 0.12
的源码:http://www.oldlinux.org/Linux.old/解压
1
2tar -zxvf linux-0.11.tar.gz
tar -zxvf linux-0.12.tar.gz旧版本环境搭建
编译和调试
- 参考链接
工具准备
环境
1
ubuntu20.04
更新软件源
1
sudo apt-get update
安装依赖
1
sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils qemu flex libncurses5-dev fakeroot build-essential ncurses-dev xz-utils libssl-dev bc bison libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev libelf-dev
下载
linux-5.11.tar.xz
1
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.11.tar.xz
解压
1
tar -xvf linux-5.11.tar.xz
进入文件夹内【配置编译选项】
1
make menuconfig
通过空格键进行【选择/取消选择】
开启的(一般已经默认开启了)
1
2[1 调试] Kernel hacking —-> Compile-time checks and compiler options —-> Compile the kernel with debug info
[2 KGDB调试内核] Kernel hacking —-> Generic Kernel Debugging Instruments —> KGDB: kernel debugger关闭的
1
[1 关闭KALSR(否则会导致打断点失败)]Processor type and features -> Randomize the address of the kernel image (KASLR)
编译内核
编译
-j$(nproc)
是尽可能多线程的编译,可加速,且可以通过指令nproc
查看当前系统所支持的所线程的数量1
2
3make -j$(nproc)
...编译报错解决 1
1
No rule to make target 'debian/canonical-certs.pem', needed by 'certs/x509_certificate_list'. Stop.
编辑
.config
文件1
vim .config
修改
CONFIG_SYSTEM_TRUSTED_KEYS
,将其置空。1
2
3
4# 原本内容
CONFIG_SYSTEM_TRUSTED_KEYS="debian/canonical-certs.pem"
# 将该项原有内容删掉即可,如下
CONFIG_SYSTEM_TRUSTED_KEYS=""编译报错解决 2
1
2
3
4BTF: .tmp_vmlinux.btf: pahole (pahole) is not available
Failed to generate BTF for vmlinux
Try to disable CONFIG_DEBUG_INFO_BTF
make: *** [Makefile:1165: vmlinux] Error 1系统缺少
dwarves
软件包1
sudo apt-get install dwarves
此时得到的文件有
1
2arch/x86/boot/bzImage --> 压缩内核镜像
vmlinux --> 原始内核文件先用
qemu
测试一下(没有文件系统会kernel panic
)这时候,qemu会卡住不动,因为现在还没有文件系统,电脑加电启动首先由bootloader加载内核,内核紧接着需要挂载内存根文件系统。
1
qemu-system-x86_64 -kernel arch/x86/boot/bzImage
制作根文件系统
获取
buzybox
源码1
wget https://busybox.net/downloads/busybox-1.33.0.tar.bz2
编译选项
-
Settings -> Build static binary file (no shared lib)
1
make menuconfig
-
编译
1
make -j$(nproc) && make install
构建根文件系统镜像
参考:使用QEMU和GDB调试Linux内核 | Consen
注意:
rootfs
在目录busybox-1.33.0
下- 最后生成的根文件镜像
rootfs.cpio
在linux-5.11
下
制作内存根文件系统镜像
在目录
busybox-1.33.0
下1
2
3
4
5mkdir rootfs
cd rootfs
cp ../_install/* ./ -rf # 注意路径
mkdir dev proc sys home
sudo cp -a /dev/{null,console,tty,tty1,tty2,tty3,tty4} dev/准备
init
脚本文件放在根文件系统跟目录下rootfs/init
,添加如下内容到init
文件1
2
3
4
5
6!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
echo "Wellcome to Linux!"
echo "--------------------"
/bin/sh使用
chmod +x init
给init脚本添加可执行权限,然后执行下面的命令打包成内存根文件系统镜像1
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../rootfs.cpio
qemu运行内核
将
rootfs.cpio
和bzImage
放到一个目录下,并在该目录下创建脚本boot.sh
测试脚本
boot.sh
1
2
3
4
5
6
7
8
9qemu-system-x86_64 \
-m 128M \
-kernel ./bzImage \
-initrd ./rootfs.cpio \
-monitor /dev/null \
-cpu kvm64,+smep \
-append "console=ttyS0 loglevel=3 quiet nokaslr" \
-nographic \
-s部分参数说明如下:
-m
:虚拟机内存大小-kernel
:内存镜像路径-initrd
:磁盘镜像路径-append
:附加参数选项nokalsr
:关闭内核地址随机化,方便我们进行调试loglevel=3
&quiet
:不输出logconsole=ttyS0
:指定终端为/dev/ttyS0
,这样一启动就能进入终端界面
-monitor
:将监视器重定向到主机设备/dev/null
,这里重定向至null主要是防止CTF中被人给偷了qemu拿flag-cpu
:设置CPU安全选项,在这里开启了smep保护-s
:相当于-gdb tcp::1234
的简写(也可以直接这么写),后续我们可以通过gdb连接本地端口进行调试
添加可执行权限并执行
1
2chmod +x ./boot.sh
./boot.sh如果存在
/etc/inittab
文件,Busybox init
程序解析它,然后按照他的指示创建各种子进程,否则使用默认的配置创建子进程.- 一般不搞这个
实验结果
Wonderful!
[废弃]构建磁盘映像
注意
busybox
文件在linux-5.11
下
建立文件系统
初始化文件系统
1
2
3
4
5
6$ cd _install
$ mkdir -pv {bin,sbin,etc,proc,sys,home,lib64,lib/x86_64-linux-gnu,usr/{bin,sbin}}
$ touch etc/inittab
$ mkdir etc/init.d
$ touch etc/init.d/rcS
$ chmod +x ./etc/init.d/rcS配置初始化脚本
配置
etc/inittab
1
2
3
4
5
6::sysinit:/etc/init.d/rcS
::askfirst:/bin/ash
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
::restart:/sbin/init在上面的文件中指定了系统初始化脚本,因此接下来配置
etc/init.d/rcS
配置
etc/init.d/rcS
1
2
3
4
5
6!/bin/sh
mount -t proc none /proc
mount -t sys none /sys
/bin/mount -n -t sysfs none /sys
/bin/mount -t ramfs none /dev
/sbin/mdev -s配置各种目录的挂载
或者:
根目录下创建
init
文件,写入如下内容1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs devtmpfs /dev
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console
echo -e "\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n"
setsid cttyhack setuidgid 1000 sh
umount /proc
umount /sys
poweroff -d 0 -f配置用户组
1
2
3
4
5echo "root:x:0:0:root:/root:/bin/sh" > etc/passwd
echo "ctf:x:1000:1000:ctf:/home/ctf:/bin/sh" >> etc/passwd
echo "root:x:0:" > etc/group
echo "ctf:x:1000:" >> etc/group
echo "none /dev/pts devpts gid=5,mode=620 0 0" > etc/fstab在这里建立了两个用户组
root
和ctf
,以及两个用户root
和ctf
配置
glibc
库略
打包文件系统为镜像文件
在
busybox
下1
find . | cpio -o -H newc > ../core.cpio
(即在
linux-5.11
下编译出core.cpio
根文件系统镜像)或者(只是名字不同)
1
find . | cpio -o --format=newc > ../../rootfs.cpio
qemu
运行内核
将
bzImage
和core
配置启动脚本1
touch boot.sh
注意两个文件
1
2
3
4$ file bzImage
bzImage: Linux kernel x86 boot executable bzImage, version 5.11.0 (ganliber@ganliber-virtual-machine) #2 SMP Mon Jul 11 19:16:12 CST 2022, RO-rootFS, swap_dev 0x9, Normal VGA
$ file rootfs.cpio
rootfs.cpio: ASCII cpio archive (SVR4 with no CRC)放在同一个文件夹下
编写脚本
boot.sh
1
2
3
4
5
6
7
8
9
10
11
12!/bin/sh
qemu-system-x86_64 \
-m 128M \
-kernel ./bzImage \
-initrd ./rootfs.cpio \
-monitor /dev/null \
-append "root=/dev/ram rdinit=/sbin/init console=ttyS0 oops=panic panic=1 loglevel=3 quiet nokaslr" \
-cpu kvm64,+smep \
-smp cores=2,threads=1 \
-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \
-nographic \
-s解释:
部分参数说明如下:
-m
:虚拟机内存大小-kernel
:内存镜像路径-initrd
:磁盘镜像路径```
-append1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
:附加参数选项
- `nokalsr`:关闭内核地址随机化,方便我们进行调试
- `rdinit`:指定初始启动进程,`/sbin/init`进程会默认以`/etc/init.d/rcS`作为启动脚本
- `loglevel=3` & `quiet`:不输出log
- `console=ttyS0`:指定终端为`/dev/ttyS0`,这样一启动就能进入终端界面
- `-monitor`:将监视器重定向到主机设备`/dev/null`,这里重定向至null主要是防止CTF中被人给偷了qemu拿flag
- `-cpu`:设置CPU安全选项,在这里开启了smep保护
- `-s`:相当于`-gdb tcp::1234`的简写(也可以直接这么写),后续我们可以通过gdb连接本地端口进行调试
* 或者
```bash
qemu-system-x86_64 -kernel ./bzImage -initrd ./rootfs.cpio -S -s
解释:
-s
:一个是-s,在TCP 1234端口上创建了一个gdb-server-S
:-S代表启动时暂停虚拟机,等待 gdb 执行 continue指令(可以简写为c)
下载现有的镜像
列出可下载的镜像
1 | sudo apt search linux-image- |
拉取5.11
版本(例)
1 | sudo apt download linux-image-5.11.0-43-generic |
其中的./extract/boot/vmlinuz-5.11.0-43-generic
便是bzImage
内核镜像文件