该题以qemu虚拟机软件的某CVE漏洞为参考,在qemu某模块中置入存在漏洞的代码,导致一些不可预测的执行流程,从而完成虚拟机逃逸攻击。选手需要在运行在qemu虚拟机中的ubuntu操作系统下进行逃逸操作,尝试触发漏洞并在宿主机(Deepin Linux)中执行任意代码。
题目给出了宿主机(Deepin Linux)的虚拟机镜像。在宿主机上运行qemu虚拟机中的ubuntu操作系统。题目要求在ubuntu操作系统中执行程序进行逃逸操作,在宿主机(Deepin Linux)中使用chrome打开本地某页面。
比赛时队里大佬做了出来。本菜鸡赛后找了点时间分析了一下。
./qemu-system-x86_64 -m 1024 -smp 2 -boot c -cpu host -hda ubuntu_server.qcow2 --enable-kvm -drive file=./blknvme,if=none,id=D22 -device nvme,drive=D22,serial=1234 -net user,hostfwd=tcp::2222-:22 -net nic
正常版本nvme_mmio_read部分
漏洞版本nvme_mmio_read部分
在此需要先了解nvme设备的基础结构
nvme是一种控制协议。用于访问通过PCI-Express(PCIe)总线附加的非易失性内存介质(SSD设备)
PCIe的Header空间和BAR空间是PCIe得以广泛使用的关键特性。
Header空间是PCIe设备的通有属性,所有的PCIe Spec功能和规范都在这里实现,PCIe Header空间中有几个寄存器专门用来存储BAR空间地址,一个PCIe设备有6个32位BAR寄存器
BAR空间是PCIe设备体现自己功能的地方。NVMe协议在BAR空间上定义了一系列的寄存器。有了这些寄存器,Host就可以与NVMe SSD的Controller进行交互了。
NVME设置BAR空间上寄存器。将BAR空间使用mmio方式映射到系统地址空间。用户打开设备,mmap后即可使用普通的访存指令直接访问设备的寄存器。
dev->bar = ioremap(pci_resource_start(pdev, 0), 8192);
此后,驱动就可以通过dev->bar加上寄存器的偏移地址(如Controller Status的偏移地址是0x1C),使用writel,readl这类函数访问Controller寄存器了。
关于pcie更多信息请自行搜索。。大意就是设备将bar空间映射在host内存中。host通过这个空间与设备交互。
在nvme驱动初始化过程中,做了有以下几件事情:
1)将BAR空间使用mmio方式映射到系统地址空间
2)host 发送第一次identify命令,获取controller 等配置,这些配置信息包括namespace个数
3)host 接下来针对每个namespace 发送identify 命令,获取每个namaspace的配置信息。通过add_disk()将每个namespace 加入到块设备层,IO就可以开始对其进行访问。
在/sys/module目录下一路跟随nvme目录能够进入设备文件所在文件夹0000:00:04.0
其中
config 是配置空间对用户的接口。
resource0, resource1, resource2 等是从"PCI 配置空间"解析出来的资源定义段落分别生成的,它们是 PCI 总线驱动在 PCI 设备初始化阶段加上去的,都是二进制属性,但没有实现读写接口,只支持 mmap 内存映射接口,尝试进行读写会提示 IO 错误,它们用于作应用程序的内存映射,就可以访问对应的 PCI 设备上相应的内存资源段落
经观察resource0大小正好为8192,与bar空间吻合。
提前使用gdb附加qemu,在nvme_mmio_write上下断点,打开此设备通过mmap方式写入。断点触发,判定resource0文件即为bar空间内存映射。通过mmap的方式使用访存指令即可与nvme设备交互。触发漏洞函数
通过堆越界读的方式我们可以得知bar空间的地址及程序加载基址,通过基址与system plt地址相加得到system地址。
堆的越界写存在限制。只能进行堆上的编辑。
简单的了解了下bar空间的使用原理
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2019-7-2 14:39
被Ezrak1e编辑
,原因: