首页
社区
课程
招聘
[原创]腾讯游戏安全技术竞赛2026决赛题解
发表于: 4天前 1640

[原创]腾讯游戏安全技术竞赛2026决赛题解

4天前
1640

从三环程序中可以直接提取出驱动,我个人比较习惯先分析驱动,因此直接开始

image-20260418162653451

发现没有导入表,膨胀严重且驱动入口加了虚拟化,先选择hook一下常见api跑一下,但是导入表无了,这说明驱动是自己解析内核导出来调用的,不过一般驱动都会自己用MmGetSystemRoutineAddress解析几个导出来用,所以先hook一下跑一下日志来收集证据。

对这里面和反调试相关的api下断点再跑一遍

发现驱动确实在调用 KdDisableDebugger

将其ret后发现驱动调用 IoDriverObjectType ,因此可能是在和驱动对象通信

hook RtlInitUnicodeString 找一下字符串

很可能是在用 IoEnumerateDeviceObjectList 扫其下的设备

image-20260418164536002

果然发现命中,执行完就返回了失败逻辑,猜测其是做了某些校验

hook RtlCompareMemory 发现了比较逻辑一共比较两次,综合起来预期的返回值应当是Msft Virtual Disk

image-20260418164721418

伪造返回值,让其成功通过校验试试

image-20260418165523367大量MmCopy 和 MmMapVideoDisplay(其实就是MmMapIOSpace) 后蓝屏了,传入的地址可以看出是物理地址,参数不断+0x1000扫页,驱动在拿到合适的磁盘设备后,进行了爆搜物理地址的操作

总结一下

驱动手动解析出一堆api,尝试获取一个 Msft Virtual Disk 的磁盘设备,成功后进行爆搜内核,现在给了驱动的一个fake返回值而蓝屏,目前不清楚驱动真正想要的设备是什么样的

根据以上的证据我找到了一个老项目

d2fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6T1N6r3u0V1i4K6u0r3k6r3c8E0j5b7`.`.

和 在运行时修改 Hyper-V 和SLAT绕过有关,先把题目往这方面想

获取 Msft Virtual Disk 的磁盘设备 可能是为了 访问/修改 Hyper-V 的某些函数,劫持某些功能,结合后面爆搜内核地址的逻辑来看,很可能存在特征码,因为固定偏移就不需要爆扫内核了。

在驱动中找相关的逻辑image-20260418170520573

发现明显的特征码扫描特征分析一下看看命中的是什么组件

直接用我的分析系统 22631

pattern

mask

patch_offset

命中了 hvix64 .text 的 RVA 0x23E407

image-20260418164000958

image-20260418171800519

里面似乎是VmExithandle

结合ida中有关扫内核和windbg的hook日志

image-20260418172653466

不难判断出驱动使用了一种类似 9b9K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6T1N6r3u0V1i4K6u0r3k6r3c8E0j5b7`.`. 的技术来绕过 Hyper-v SLAT 搜索并定位相关 VmExithandle,因为现在还没有分析三环程序 我只猜测可能改了 VmExithandle 的hypercall之类的把校验逻辑藏在里面

既然大概的逻辑可以分析出来,接下来就是定位它往VmExithandle里面到底改了什么

尝试伪造磁盘信息骗过驱动

之后却发现驱动总是失败退出或蓝屏,定位不到目标区域,在这里卡了好长一段时间

后来想到既然三环程序总归是能独立加载并拉起驱动的,说明三环程序有着让驱动能真正找到patch点的能力

因此转到三环进行分析

从驱动入手可以基本分析得到可能是一个 Hyper-v SLAT bypass 因此首先想到三环程序可能是检测了 Microsoft Hv

搜一下 cpuid 果然如此

image-20260418181135416

sub_144A06650

image-20260418181209978

xor恢复结果

逻辑如下

通过动态解密字符串后获取 firmware table 相关 API

枚举 ACPI / firmware table

扫描表项签名

若发现:

DMAR

IVRS则返回成功

上述的两个函数检查了

是否运行在 Microsoft Hyper-V

是否存在 IOMMU / VT-d / AMD-Vi 相关 ACPI 表

开启 Hyper-V 关掉 iommu 虚拟化 ,程序运行成功且成功加载了驱动

image-20260418181807913

根据前面的分析 三环程序大概率 是有创建 VHD 的功能,不过既然能成功加载驱动并正确使用其功能,我们可以继续进行驱动的分析

image-20260418182446076

字符串定位到加载驱动的逻辑,这里再system32/driver下面落地了一个随机名字的驱动,给他patch成固定的ACEDriver.sys方便我们在windbg调试时少打一条lm

能成功启动三环程序说明对 Hyper-V 的修改是已经发生了,我们逆向一下对应的 读/写 函数所在位置,准备打断点分析

image-20260418184010674

image-20260418184027994

通过查找手动解析的发io请求的导入的调用位置 我们可以恢复出未被虚拟化的驱动读写函数

地址位于140003E60

其中 ddma_sptd_transfer_page 是底层函数,其调用的api如下图所示

其中构造

发 IOCTL_SCSI 请求虚拟磁盘按页读写,加载驱动后发现多了 vhdmp 设备对象

image-20260419005729553

设备是 vhdmp 驱动就是用这个设备对象发 IOCTL_SCSI_PASS_THROUGH_DIRECT 进行类ddma读写

image-20260418184817939

驱动爆搜内核找 hvix64的 vmexithandle

如果 MmCopyMemory 读不到 就走 MmMapIoSpace+

ddma_disk_copy_page 的类ddma读写

查引用发现还有一个使用ddma_disk_copy_page 类ddma读写 的函数

image-20260418185420115

一共找到如下的ddma写入函数

之后对于驱动的ddma读写函数都进行了hook来分析驱动是怎样劫持vmexit的

image-20260418200410783

dump出来一堆看似有用的垃圾数据既然驱动要劫持vmexit 必然会写hyper-v地址空间

因此hook全部的ddma写函数来分析驱动ddma写入行为

image-20260418191156764

找到一个看起来像是pe的页写入,先保存下来

image-20260418200808247

经过长时间的调试 终于在 HyperCharge-debug 释放完日志后的一次ddma写入函数调用中找到了目标hyperv进程

image-20260418200940489

原本是0xcc的代码洞被驱动写入了一个stub

对比winddbg中原逻辑 发现他 call FFFF96008FF4B8A0 后 jmp FFFF96008FF783E4 jmp到了

FFFF96008FF4B8A0 的下一条指令处

这说明 call FFFF96008FF4B8A0 应该会被修改为 jmp ffff9600`8ff78406

FFFFFF7FBFDFE000当前没法访问 stub把

生成出来的 PDPT 物理地址 0x100153000 写到它的 +0x320

FFFFFF7FBFDFE000 无法访问,可能是hyper-v私有页表之类的

mov cr3后立刻去访问 0x327FFFE00000 这块隐藏虚拟窗口

0x327FFFE00000= PML4[100] / PDPT[511] / PD[511] / PT[0]

0x320 / 8 = 100是 PML4 第 100 项

这说明 327FFFE00000 很可能就是这段stub带起来的逻辑,解题的关键就在 327FFFE00000 附近的可执行逻辑里面

随后解析了 原来Hyper-v的handle所在的地址 传到 0x327FFFE00000+0x4080

image-20260418202527640

继续找下一个写入点 果然stub被改了,这说明我们之前的分析是正确的

image-20260418203410189

FFFFFF7FBFDFE000这个地址我识别,在 Voyager 这个项目中也有使用Voyager 是一个旨在为 AMD 和 Intel 版本的 Hyper-V 提供模块注入和 vmexit 钩子的项目

这说明我们分析的驱动逻辑基本上正确

image-20260418203641056

从voyager的源码来看 驱动应该也有一个映射器,这和我们前面观察到的一个类pe页相符合,驱动很可能早就将最终payload映射到了内存中

image-20260418203918417重新分析下驱动 果然在 14000E630 找到了对应的映射函数此函数 构造了新的 PT/PD/PDPT 三页页表,有明显识别pe的特征,并且映射后抹去了pe头,这解释了之前为什么只看到像pe但没找到pe头

image-20260418204302069

也能通过地址确定这就是我们找的释放最终payload的函数

image-20260418204059708

image-20260418191156764

打断点dump下来分析一下,可以看dump的驱动和我们在运行态抓到的写入操作完全匹配

image-20260418204347561payload1偏移是 4080 与 前面提到过的 handle所在的地址 传到 0x327FFFE00000+0x4080 符合,确实有这么一个全局变量


[培训]《冰与火的战歌:Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回