qemu逃逸学习笔记

本文介绍了QEMU逃逸的基础知识,通过分析津门杯赛题,讲解了如何利用monitor模式、栈溢出和数组越界漏洞进行逃逸。重点分析了edu_mmio_write和edu_mmio_read函数,展示了如何利用这些漏洞执行命令并读取敏感信息。此外,还分享了调试技巧和POC编写方法,包括使用mmap访问MMIO空间和通过IN/OUT指令访问PMIO。
摘要由CSDN通过智能技术生成

前言

记录一下qemu逃逸的基础知识以及做题相关的技巧
例题是津门杯的qemu逃逸,个人觉得比较简单适合入门

分析

run.sh
#! /bin/sh
./qemu-system-x86_64 \
-initrd ./rootfs.cpio \
-kernel ./vmlinuz-4.8.0-52-generic \
-append 'console=ttyS0 root=/dev/ram oops=panic panic=1 quiet' \
-monitor /dev/null \
-m 64M --nographic \
-L pc-bios \
-device edu,id=vda
非预期

首先我们需要注意的-monitor这一句,因为如果有的题目没有加这一句则有可能导致非预期的产生,具体的做法可以参考:链接
步骤是首先ctrl+a 然后输入c回车之后即可进入monitor模式,然后就可以为所欲为了,可以用migrate来执行命令读取flag

migrate "exec:cat flag 1>&2"
正常分析

如果有monitor这一句的话那就接着分析
可以注意到-device edu,我们将所给的qemu-system-x86_64文件导进ida中,因为文件比较大,因此需要一段时间,导入成功后我们搜索edu相关函数,可以看到如下

通常漏洞是数组越界以及栈溢出,产生漏洞的函数常常集中在pmmio以及mmio或者timer函数,因此我们着重分析这些函数,当然也不排除特殊情况,具体还要看相关题目来做具体的分析,因为本题只有mmio函数,我们只要分析mmio函数即可
这里还有一个注意点,由于ida分析函数的顺序问题,可能会出现试别不出结构题的情况这时候我们只需要切换到汇编模式,查看相应的rdi对应的结构体的名称,然后在反汇编的页面将rdi按y修改类型即可例如

可以看到初始时没有试别结构体的,然后我们按y来修改类型


可以看到成功识别结构体

edu_mmio_write
void __fastcall edu_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
   
  __int64 v4; // rdi
  __int64 v5; // rax
  __int64 v6; // rdx
  _BYTE v7[24]; // [rsp+0h] [rbp-28h]
  unsigned __int64 v8; // [rsp+18h] [rbp-10h]

  v8 = __readfsqword(0x28u);
  if ( addr <= 0xFF && size == 4 )
  {
   
    cmd_buf[(unsigned int)addr] = val;
  }
  else if ( addr == 296 )
  {
   
    if ( buf_len > 0 )
    {
   
      v4 = (unsigned int)(buf_len - 1);
      v5 = 0LL;
      do
      {
   
        v7[v5] = cmd_buf[v5];
        v6 = v5++;
      }
      while ( v4 != v6 );
    }
    if ( v7[4] == 3 )
      buf_len = 291;
  }
  else if ( addr == 304 )
  {
   
    buf_len = val;
  }

通过分析可以看到该函数主要实现了以下作用:
addr <= 0xff 将val赋值给cmd_buf[addr]处
addr = 0x130 将val赋值给buf_len
addr = 0x128 && buf_len>0 && v6!=v4将cmd_buf数组的内容逐字节赋值给v7数组
这里很容易发现有个栈溢出漏洞,可以溢出v7来达到栈溢出的目的

edu_mmio_read
uint64_t __fastcall edu_mmio_read(EduState *opaque, hwaddr addr, unsigned int size)
{
   
  uint64_t result; // rax
  char buf[16]; // [rsp+10h] [rbp-38h]
  unsigned __int64 v5; // [rsp+28h] [rbp-20h]

  v5 = __readfsqword(0x28u);
  if ( addr <= 0x2FF && size == 4 )
    return buf[(unsigned int)addr];
  if ( addr <= 0x7F && size != 4 )
    return buf_len + cmd_buf[addr];
  if ( ((size - 4) & 0xFFFFFFFB) == 0 || (result = -1LL, addr <= 0x7F) )
  {
   
    if ( addr <= 0x24 )
      __asm {
    jmp     rax }
    if ( addr != 144 )
    {
   
      if ( addr <= 0x90 )
      {
   
        if ( addr == 128 )
          return opaque->dma.src;
        if ( addr == 136 )
          return opaque->dma.dst;
      }
      else if ( addr == 152 )
      {
   
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值