用于上传文件的脚本就放到最后啦
baby.ko
漏洞模块,要拖到 IDA 看的,要打的题就是它
bzImage
概述
vmlinux
vmlinux 是 ELF 文件,未压缩的内核,即编译出来的最原始的文件
vmlinux 用于 kernel-debug,产生 system.map 符号表,不能用于直接加载,不可以作为启动内核,只是启动过程中的中间媒体
vmlinuz
vmlinuz 是可引导的、压缩的内核,vm 代表 Virtual Memory
Linux 支持虚拟内存,不像老的操作系统比如 DOS 有 640KB 内存的限制,因为 Linux 能够使用硬盘空间作为虚拟内存,所以得名 vm
vmlinuz 是可执行的 Linux 内核,位于/boot/vmlinuz
。它一般是一个软链接,但是已经丢失了调试信息等数据,不可用于调试
这就是为什么 perf 和 systemtap 等内核级别的调试软件安装的时候,需要重新编译内核的原因
同理,解压缩 vmlinuz 是不能得到 vmlinux 的,相对于 vmlinux,它增加了解压缩和 boot 的部分
zImage
zImage 是 vmlinuz 经过 gzip 压缩后的文件,适用于小内核(512KB 以内),加载到内存的开始 640KB 处
bzImage
bzImage 是 vmlinuz 经过 gzip 压缩后的文件,适用于大内核,为什么会发明 bzImage 这种内核镜像呢?
随着 Linux 内核的成熟,Linux 内核的大小逐渐增大,超过了一些体系结构的限制,导致存储压缩内核的空间受到限制
bzImage 这种格式就是为了克服这种限制,它通过把 kernel 分解到不相邻的内存区域来达到这一个目的
bzImage 包含以下目标文件:bootsect.o + setup.o + misc.o + piggy.o
bzImage 的解剖图:
做题要点
extract-vmlinux
主要是在题目没有提供 vmlinux 用以调试内核及查看 rop 的时候,利用 extract-vmlinux 命令可以从 bzImage 中提取 vmlinux
extract-vmlinux 存在于在搭建 Kernel 环境时编译 linux 内核的文件夹里,我的路径是/linux-4.20/scripts/extract-vmlinux
ropper
ropper 提取 rop 的速度比 ROPgadget 要快很多,但是安装属实困难,最主要的问题出在安装 filebytes 上面
安装这个库的时候包名都变成了 UNKNOWN,之后了解到是因为没更新 setuptools,用命令更新一下:
1 | sudo pip install setuptools --upgrade |
然后抛错
1 | ERROR: launchpadlib 1.10.3 requires testresources, which is not installed. |
再安装即可
1 | sudo pip install launchpadlib |
之后按照 github 上面写的安装 ropper 的步骤来就完事了,提取 rop 的方法如下:
1 | ropper -f vmlinux --nocolor > gadget.txt |
initramfs.cpio
cpio 文件的压缩和解包
压缩
这个一定要在解压出来的文件目录内运行,不然最后出来的镜像文件是不完整的
1 | find . | cpio -o --format=newc > initramfs.cpio |
解压
将 cpio 文件内的文件全部解压到当前目录,最好一开始建个文件夹,将这些文件都存在单独的文件夹里
1 | sudo cpio -idmv < initramfs.cpio |
这个右键归档管理器貌似也能解压,可能是因为我装了 7z
rcS
这个文件一般都在解包后文件夹的/etc/init.d
里,记载着内核启动时的参数,一般 rcS 文件内会写有如下参数:
1 |
|
这里调试的时候需要把 1000 改成 0000 来获得 root 权限,改成 0 会崩,一定要 4 个 0
下面就简单讲解一下这些参数:
mount -t devtmpfs none /dev
挂载 devtmpfs 类型的文件系统,设备名设置为 none,挂载目录为 /dev
devtmpfs 的功用是在 Linux 核心启动早期建立一个初步的 /dev,令一般启动程序不用等待 udev,缩短 GNU/Linux 的开机时间。
mount -t proc proc /proc
挂载 proc 类型的文件系统,设备名设置为 proc,挂载目录为 /proc
insmod /home/pwn/baby.ko
加载存在漏洞的题目模块到内核中
chmod 644 /dev/baby
这块还不懂,但是不设置内核会崩,改的是一个字符设备文件的权限
echo 1 > /proc/sys/kernel/dmesg_restrict
这个参数是不让非 root 用户读取 dmesg 的输出信息的
设置为 0 就可以输出 dmesg 的信息了,但是没必要,改成 root 用户就好了
echo 1 > /proc/sys/kernel/kptr_restrict
有 0、1、2 三个值可以选择,这里的 1 具体我也不懂,不过 1 和 0 都是能打印内核符号表的
如果是 2 的话,打印的符号表地址就都是 0,相当于不让你读取了,一般读取方法如下:
grep prepare_kernel_cred /proc/kallsyms
cd /home/pwn
漏洞模块在这,没啥好说的
setsid cttyhack setuidgid 1000 sh
创建一个子进程,并使子进程成为新会话的首进程,成为新进程组的组长进程
用户组设置为 1000,登录 shell 设置为 sh
这个 cttyhack 我不知道啥意思,不过写上就完了
umount /proc
卸除挂载的 /proc 文件夹
poweroff -f
不写起不了程序,暂且不知道是退出啥终端
startvm.sh
起程序的脚本,一般大致如下:
1 |
|
调试的时候需要在后面加一个 -s 用来开放本地的 1234 号端口,用 gdb-multiarch 监听 1234 端口即可
如果 1234 号端口用不了,也可以换成 -gdb tcp::端口号,改完大致如下:
1 |
|
exp 上传脚本
这里用的是 sixstars 战队中一位师傅的脚本,采用 base64 来进行文件编码传输
我改了改脚本,写 exp 的时候需要在当前目录下新建一个 poc 文件夹,把 c 文件和 c 程序都放在那里
这样看起来不乱,程序的名字设置成 exp 就好
普通用户
1 | #!/usr/bin/env python |
root 用户
1 | #!/usr/bin/env python |
参考链接
1 | https://www.cnblogs.com/javawebsoa/archive/2013/07/24/3212564.html |