qemu pwn 2021 HWS FastCP

启动脚本长这样。

#!/bin/sh

./qemu-system-x86_64 -initrd ./initramfs-busybox-x64.cpio.gz -nographic -kernel ./vmlinuz-5.0.5-generic -append "priority=low console=ttyS0" -monitor /dev/null --device FastCP

在这里插入图片描述
绿肯定是全绿

设备是FastCP

在这里插入图片描述
这是里面设备结构体的全貌
在这里插入图片描述里面还有一个叫CP_state的结构体
在这里插入图片描述三个参数

FastCP_realize函数中设置了一个定时器
定时器时间到了会调用fastcp_cp_timer函数
然后创建了一个mmio
在这里插入图片描述

fastcp_mmio_read
在这里插入图片描述功能0x00 返回opaque->handling
功能0x08 返回opaque->cp_state.CP_list_src
功能0x10 返回opaque->cp_state.CP_list_cnt
功能0x18 返回opaque->cp_state.cmd

fastcp_mmio_write
在这里插入图片描述功能0x08 给cp_list_src赋值
功能0x10 handing不是1的情况下给cp_list_cnt赋值
功能0x18 handing不是1的情况下给cp_list_cmd赋值然后调用timer

然后我们瞅瞅fastcp_cp_timer函数

void __fastcall fastcp_cp_timer(FastCPState *opaque)
{
   
   
  uint64_t v1; // rax
  uint64_t v2; // rdx
  __int64 v3; // rbp
  uint64_t v4; // r12
  uint64_t v5; // rax
  uint64_t v6; // rax
  bool v7; // zf
  uint64_t v8; // rbp
  __int64 v9; // rdx
  FastCP_CP_INFO cp_info; // [rsp+0h] [rbp-68h] BYREF
  char buf[8]; // [rsp+20h] [rbp-48h] BYREF
  unsigned __int64 v12; // [rsp+28h] [rbp-40h]
  unsigned __int64 v13; // [rsp+38h] [rbp-30h]

  v13 = __readfsqword(0x28u);
  v1 = opaque->cp_state.cmd;
  cp_info.CP_src = 0LL;
  cp_info.CP_cnt = 0LL;
  cp_info.CP_dst = 0LL;
  switch ( v1 )                                 // cp_state.cmd来做选择
  {
   
   
    case 2uLL:                                  // 选择2
      v7 = opaque->cp_state.CP_list_cnt == 1;   // v7是cp_list_cnt是不是1
      opaque->handling = 1;                     // handing置1
                                                // 也就是不再给计时器机会
      if ( v7 )                                 // 要求v7是1也就是cp_list_cnt不是1
      {
   
                                            // cpu_physical_memory_rw(a1, a2, a3, 1);是将a2复制到a1,而cpu_physical_memory_rw(a1, a2, a3, 0);则将a1复制到a2
                                                // 但是要注意的是,cpu_physical_memory_rw的第一个参数为硬件地址,即物理地址,所以我们需要将qemu里面的虚拟地址,转化为物理地址。
        cpu_physical_memory_rw(opaque->cp_state.CP_list_src, &cp_info, 0x18uLL, 0);// 所以就list_src里面的复制0x18个字节到cp_info结构体
        if ( cp_info.CP_cnt <= 0x1000 )         // cp_cnt必须小于0x1000
                                                // 然后就可以把cp_info.cp_src中的复制到cp_buffer
          cpu_physical_memory_rw(cp_info.CP_src, opaque->CP_buffer, cp_info.CP_cnt, 0);
        v6 = opaque->cp_state.cmd & 0xFFFFFFFFFFFFFFFCLL;
        opaque->cp_state.cmd = v6;
        goto LABEL_11;                          // 然后拜拜
      }
      break;
    case 4uLL:
      v7 = opaque->cp_state.CP_list_cnt == 1;
      opaque->handling = 1;
      if ( v7 )                                 // cp_list_cnt还得不是1
      {
   
                                            // 还是list_src写进去cp_info结构体
                                                // cp_buffer又能写cnt个到cp_dst
        cpu_physical_memory_rw(opaque->cp_state.CP_list_src, &cp_info, 0x18uLL, 0);
        cpu_physical_memory_rw(cp_info.CP_dst, opaque->CP_buffer, cp_info.CP_cnt, 1);// 这里没有对这个cnt有检查
        v6 = opaque->cp_state.cmd & 0xFFFFFFFFFFFFFFF8LL;
        opaque->cp_state.cmd = v6;              // 然后又拜拜
LABEL_11:
        if ( (v6 & 8) != 0 )                    // cmd要求是8
        {
   
   
          opaque->irq_status |= 0x100u;
          if ( msi_enabled(&opaque->pdev) )
            msi_notify(&opaque->pdev, 0);
          else
            pci_set_irq(&opaque->pdev, 1);
        }
        goto LABEL_16;                          // 但是走了这个地方之后又handing等于0了
                                                // 就又能启动timer了
      }
      break<
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值