QEMU-PWN记录
QEMU-PWN记录
关于QEMU基础知识参考raycp大师傅的文章。
笔者这里也推荐两本书入门QEMU或者说虚拟化安全:《QEMU/KVM源码解析与应用》、《深度探索Linux系统虚拟化:原理与实现》
关于QEMU的QOM机制,笔者也从书中做了一点点小的摘抄:
类型的注册 type_init
类型的初始化 class_init
对象的初始化 instnce_init realize (设备的具象化)
类型的注册. TypeInfo->TypeImpl. 哈希表(Name: TypeImpl)
类型的初始化. type_initialize 1.设置TypeImpl的域; 2.调用class_init
对象的初始化. object-new -> object_new_with _type -> object_initialize_with_type -> object_init_whith_type(递归调用父类型的初始化函数和自身的初始函数)每一个对象都会有一个xxxState与之对应。
经过对象的初始化后,仅仅是构造出了对象,但是相应的xxxState并没有初始化完成,还需要设置对象的realized属性对设备具现化。这个时候会调用相应的realize函数,对xxxState
HITB 2017 babyqemu
用户与PCI设备的交互:通过MMIO这一段内存区域(少量数据传送,多用于设置参数、控制命令等);通过DMA进行大量数据交互(直接与PCI设备的物理内存进行交互,需要将用户态虚拟地址转换为物理地址)。
https://xuanxuanblingbling.github.io/ctf/pwn/2022/06/09/qemu/
HWS 2021 FastCP
关键:分配连续的物理页。
在进行拷贝时,虽然用户可以申请一个大于0x1000在虚拟地址上连续的内存空间,但其未必是物理地址空间上连续的多个页。当使用cpu_physical_memory_rw
函数进行较长的内存拷贝时,一定要确保给出的空间在物理地址上连续。
Qemu常用的控制流原语
在bss段,存在一个全局变量main_loop_tlg
,其是一个QemuTimerList数组。当QEMUTimer->expire_time
超时(设置为-1会直接触发),就会执行QEMUTimer->cb(opaque)
,从而劫持控制流。
攻击方法:
- 任意地址写
main_loop_tlg
,在堆上伪造QEMUTimerList与QEMUTimer结构体,从而实现控制流劫持; - 任意地址写
main_loop_tlg[0]->active_timers
,在堆上伪造QEMUTimer结构体,从而实现控制流劫持。
1 |
|
参考文章:https://www.anquanke.com/post/id/254906
QWB 2021 EzTest
缺乏对应的链接库,直接google搜索,然后apt安装即可。
使用QTest(https://www.qemu.org/docs/master/devel/qtest.html)协议进行交互
关键点:如何定位MMIO基地址?
之前QEMU逃逸类型的题目都是在Linux系统下进行操作,mmio可以通过类似/sys/devices/pci0000:00/0000:00:04.0/resource1
的路径来操作,但是在qtest命令行下要怎么操作呢?
配置PCI标准空间:
获取设备地址:qwb设备的Bus number为0,Device number为2,Function number为0,得出qwb的地址为0x80001000
。
COMMAND:用于控制设备的行为,例如启用或禁用I/O空间、内存空间、总线主控等。
总结一下初始化需要操作的步骤:
将MMIO地址写入qwb设备的BAR0地址
通过0xcf8端口设置目标地址
通过0xcfc端口写值
将命令写入qwb设备的COMMAND地址,触发pci_update_mappings
通过0xcf8端口设置目标地址
通过0xcfc端口写值
1 |
|
劫持QWBState->mmio.ops
为system
,然后通过执行writeq addr val
触发获取flag。
参考文章:https://matshao.com/2021/06/15/QWB2021-Quals-EzQtest/
DefconQuals 2018 EC3
题目去掉了符号,搜索字符串以及比对其它有符号的qemu可以确定关键操作函数。
之后就是一个libc堆题,把堆塞到了qemu逃逸中。
总结
既然都写了,就做一个小的总结吧。
QEMU控制流劫持总结:
- 劫持
main_loop_tlg
,伪造QEMUTimer执行命令。 - QEMU对设备的读写注册了MMIO或者PMIO,劫持相应的读写指针。
- 每个设备都存在中断,劫持XXXState中中断相关的指针执行命令。
至于地址泄露,QEMU中存在很多能够泄露地址的地方,比如XXXState结构体就存在很多指向QEMU代码段的指针。