首页 > 其他分享 >从 VNCTF2024 的一道题学习QEMU Escape

从 VNCTF2024 的一道题学习QEMU Escape

时间:2024-03-15 19:04:45浏览次数:27  
标签:VNCTF2024 mmio pci vn exp Escape 0x0000000000000000 QEMU

说在前面

本文的草稿是边打边学边写出来的,文章思路会与一个“刚打完用户态 pwn 题就去打 QEMU Escape ”的人的思路相似,在分析结束以后我又在部分比较模糊的地方加入了一些补充,因此阅读起来可能会相对轻松。(当然也不排除这是我自以为是)

题目 github 仓库

[1] 题目分析流程

[1-1] 启动文件分析

读 Dockerfile,了解到它在搭起环境以后启动了start.sh

再读 start.sh,了解到它启动了 xinetd 程序

再读 xinetd,这个程序的主要作用是监听指定 port,并根据预先定义好的配置来启动相应服务。可以看到 server_args 处启动了 run.sh

再读 run.sh,发现它用 QEMU 起了一个程序,通过 -device vn 我们可以知道 vn 是作为 QEMU 中的一个 pci设备 存在的。

通过 IDA 查找字符串 vn_ 可以找到 vn_instance_init,跟进调用 字符串vn_instance_init 的 函数vn_instance_init,再按 x 查看 函数vn_instance_init 的引用,可以看到下面还有一个 vn_class_init ,反汇编后看到

__int64 __fastcall vn_class_init(__int64 a1)
{
  __int64 result; // rax
​
  result = PCI_DEVICE_CLASS_23(a1);
  *(_QWORD *)(result + 176) = pci_vn_realize;
  *(_QWORD *)(result + 184) = 0LL;
  *(_WORD *)(result + 208) = 0x1234; // 厂商ID (Vendor ID)
  *(_WORD *)(result + 210) = 0x2024; // 设备ID (Device ID)
  *(_BYTE *)(result + 212) = 0x10;
  *(_WORD *)(result + 214) = 0xFF;
  return result;
}

通过厂商ID和设备ID,我们可以判断下列 pci 设备中 00:04.0 Class 00ff: 1234:2024 就是我们要找的 vn

/sys/devices/pci0000:00/0000:00:04.0 # lspci
lspci
00:01.0 Class 0601: 8086:7000
00:04.0 Class 00ff: 1234:2024
00:00.0 Class 0600: 8086:1237
00:01.3 Class 0680: 8086:7113
00:03.0 Class 0200: 8086:100e
00:01.1 Class 0101: 8086:7010
00:02.0 Class 0300: 1234:1111

进而去/sys/devices/pci0000:00/0000:00:04.0 目录查看该设备 mmio 与 pmio 的注册情况

/sys/devices/pci0000:00/0000:00:04.0 # ls -al
...
...
-r--r--r--    1 0        0             4096 Feb 18 12:18 resource
-rw-------    1 0        0             4096 Feb 18 12:18 resource0
...
...

有了 resource0 这个文件,我们就可以在exp里 mmap 做虚拟地址映射。

并且我们可以看到 vn 这个设备只注册了 mmio,那就考虑用 mmio攻击(点击这里了解 mmio 运行原理)

[1-2] 静态分析

如果我写的不够清楚,读者可以参考 blizzardCTF 里的 strng这一实现,读完这段代码会对 pci 设备的了解提升一个台阶。

我们先补充一些概念:

QEMU 提供了一套完整的模拟硬件给 QEMU 上的 kernel 来使用,而 -device 参数为 kernel 提供了模拟的 pci 设备。

如果 kernel 实现了类似 linux 的 rootfs,我们就可以通过 lspci 来查看相关 pci,并在/sys/devices/...找到 pci 设备启动时 kernel 分配给 pci 的资源,也就是 resource0 等,这也是前文提到过的。

resource0 可以看作是一大片开关,当我们修改 resource0 中的内容时,可以看做对应开关被启动,pci设备也随着开关的启动而变化,具体表现为“控制寄存器、状态寄存器以及设备内部的内存区域 随着 resource0 的变化而变化”

所以我们可以 open resource0 这个文件,用 mmap 映射它,从而使我们能够在C代码中对 resource0 这片内存进行修改

可是由于 QEMU 也只不过是一个程序,虚拟的 pci 设备意味着,一定有一片内存存储着 pci 相关的数据

关于 pci 存储数据的这一部分好像就涉及 QOM 了,还没太搞懂,总之跟pci_xx_realize, xx_class_init, xx_instance_init 等函数有关

假设我们的调用链是这样的: 
docker -> QEMU -> exp
​
则 docker 会让 QEMU 误以为自己占据全部内存空间,QEMU 会让 exp 认为自己占据全部内存空间
​
而 QEMU 的 pci 设备的 MemoryRegion 就存储在 QEMU 的堆区上,我们在程序 exp 中读写 resource0,就相当于操控 vn_mmio_read 和 vn_mmio_write 去读写 QEMU 的堆区,如果我们正好修改到 MemoryRegion 的 xx_mmio_ops 指针,就可以劫持控制流。

那么,接下来我们要做的事情就是去读一下 vn_mmio_read 和 vn_mmio_write 的反汇编,了解怎样读写堆区内容。

oNxdA.md.png

由于对 QEMU 不是很熟悉,我只能瞎命名,vn_mmio_write 的大体逻辑是

相关文章

  • Linux内核编译(版本6.0以及版本v0.01)并用qemu驱动
    系统环境:ubuntu-22.04.1-desktop-amd64目标平台:x86i386内核版本:linux-6.0.1linux-0.0.1环境配置修改root密码sudopasswd修改软件源(非必要)vmtools安装(实现win-linux软件互传)安装一些必须的软件:sudoaptinstallbuild-essentialopenssh-servervimnet-toolsgc......
  • Ubuntu中安装使用QEMU/KVM/virt-manager运行虚拟机
    本文为原创,原文发布于个人博客网站:Ubuntu中安装使用QEMU/KVM/virt-manager运行虚拟机有时候我们需要在同一台计算机中使用多种不同操作系统环境,基于已有的同一堆硬件资源来获得不同操作系统各自的便利性。对此,常用的解决方案主要有:在物理机器中安装使用双系统在宿主系统中安......
  • Ubuntu中安装使用QEMU/KVM/virt-manager运行虚拟机
    本文为原创,首次发布于我的个人博客网站:Ubuntu中安装使用QEMU/KVM/virt-manager运行虚拟机有时候我们需要在同一台计算机中使用多种不同操作系统环境,基于已有的同一堆硬件资源来获得不同操作系统各自的便利性。对此,常用的解决方案主要有:在物理机器中安装使用双系统在宿主系统......
  • CF932F Escape Through Leaf【DP,李超线段树】
    有一颗\(n\)个节点的树,根节点为\(1\)。每个节点有两个权值,第\(i\)个节点的权值为\(a_i,b_i\)。你可以从一个节点跳到它的子树内任意一个节点上。从节点\(x\)跳到节点\(y\)一次的花费为\(a_x\timesb_y\)。跳跃多次走过一条路径的总费用为每次跳跃的费用之和。求每个节......
  • ReadableStream/TransformStream/HMR/软件设计哲学/SSR 条件渲染/CSS.escape/Copilot
    ReadableStream,TransformStream-探索如何在React服务器组件中使用流来提升性能和用户体验。HMR-简介热模块替换技术,使前端开发更加高效。软件设计哲学-深入理解软件设计背后的哲学思考。SSR条件渲染组件-SSR条件渲染的实现方法,优化页面加载速度和SEO。C......
  • VNCTF2024-WEB-gxngxngxn
    VNCTF2024-WEB-gxngxngxnCheckin签到题,直接看js文件CutePath按照上述穿越下可以看到一串base64加密的,解密后是账号密码:登录看到有新功能,可以重命名文件.我们找到flag.txt文件,但是不能查看,我们可以利用重命名将flag.txt文件传送到share_main目录下,这样我们就可以查看......
  • 手把手搭建QEMU ARM64开发环境
    根据上篇我们讲了搭建ARM32QEMU环境没看到的小伙伴可以看下https://mp.weixin.qq.com/s?__biz=MzUyNDUyMDQyNQ==&mid=2247483838&idx=1&sn=87a65f10e558bdfc35277153d4b42f6a&chksm=fa2d5f38cd5ad62ead217bd0efe857b2ac06e1a14042cacb488f926e8791b75f28c6ec930c4f&token=420704......
  • WordPress 技巧:解决 3.6 版本的 "wpdb::escape is deprecated" 错误提示
    来源:http://www.shanhubei.com/archives/13621.html升级到WordPress3.6之后,发现在debuglog中有很多以下的错误信息:Notice:wpdb::escapeisdeprecatedsinceversion3.6!Usewpdb::prepare()oresc_sql()instead.这个错误信息的意思是WordPress3.6将$wpdp类......
  • qemu重定向串口serial
    背景运行qemu的环境为host,qemu模拟的系统为guest。基于不同的需求,有时需要对串口进行重定向qemu-serial选项qemu提供了很多的重定向选项,null,socket,udp,msmouse,vc,file,pipe,console,serial,pty,stdio,braille,tty,parport,spicevmc,下面我们简单列几个分析一......
  • 详解'unicodeescape' codec can't decode bytes in position 16-17: malformed \N ch
    详解'unicodeescape'codeccan'tdecodebytesinposition16-17:malformed\Ncharacterescape在Python的字符串处理中,有时候可能会遇到如下错误信息:'unicodeescape'codeccan'tdecodebytesinposition16-17:malformed\Ncharacterescape。本篇文章将详细解释这个错......