2026 腾讯游戏安全 PC 初赛 WP
97k字 •
193分钟
驱动加载
使用 EfiGuard 进行 PG 和 DSE 修复
1 | // 挂载 EFI 到 M:,注意在 explorer 中是看不到的 |
绿字进系统后关闭 DSE 就可以加载驱动了
1 | EfiDSEFix.exe -d |
启动驱动后运行程序

exe 分析
1 | int __fastcall main_0(int argc, const char **argv, const char **envp) |
重点在驱动交互,其余均为负责输入的逻辑
IO_8001200C
初始化
1 | BOOL __fastcall IO_8001200C(__int64 a1, void *lpOutBuffer) |
1 | struct __unaligned ioctl_8001200c_out |
IO_80012004
1 | __int64 __fastcall IO_80012004(void *hDevice, __int64 _RDX, int a3, _BYTE *buf, DWORD *out) |
负责移动,发送给驱动的数据结构见下
1 | struct ioctl_80012004_in |
1 | from struct import pack |
IO_80012008_Reset
重置迷宫
1 | BOOL IO_80012008_Reset() |
sys 分析
有一些难以分析的 call,nop 掉看整体流程

载入点
1 | __int64 __fastcall sub_140003208(struct _DRIVER_OBJECT *DriverObject) |
Contorl 里面也有两处难以分析 call,nop 掉看整体逻辑
1 | __int64 __fastcall IRP_Control_Func(__int64 a1, IRP *IRP, __int64 a3, char a4) |
CODE 0x8001200C
传递迷宫大小,位置信息
CODE 0x80012008
重置
CODE 0x80012004
移动,主要逻辑
移动延迟
KeDelayExecutionThread 对每步移动都进行一点延迟,所以算法爆破特别慢,需要 patch

VA 0x1400026BD,RVA 0x26BD 全 nop (5字节)
1 | eq ShadowGateSys+0x26bd c483489090909090 |
五个泄漏点
sys data 段起始有一个花指令魔数,通过该魔数可以定位四个泄漏点

1. Event 泄漏
exe 0x140001340 创建 Global Event

sys 0x1400022B0 中 event 泄漏:n2==0/2 置 MazeMoveOK,否则置 MazeMoveWall

2. 信号量 泄漏
exe 0x14021B91F 创建信号量,异或 0x4B 解密字符串


得到
1 | Global\{A7F3B2C1-9E4D-4C8A-B5D6-1F2E3A4B5C6D} |
sys 0x140319A37 中 semaphore 泄漏,_EDX ==0/2 释放 {A7F3B2C1-9E4D-4C8A-B5D6-1F2E3A4B5C6D} ,否则释放 {B8E2C3D0-0F5A-5D9B-C6E7-2A3F4B5C6D7E}

3. TEB.LastError 泄漏
sys 0x140316ADF 中修改 exe LastErrorValue ,n2 为 0 时设置 0xC0DE0001, 2 时设置 0xC0DE0002, 其他时设置 0xC0DE0000

4. TEB + 0x1748 泄漏
exe 0x14021BC88 在释放时有部分提示

sys 0x14031857E 中,使用 PsGetThreadTeb 获取 TEB 后使用 ZwSetInfomationObject 对 teb + 0x1748 处进行设置
在 icall 分发处能够看到实际调用的 call 为 PsGetThreadTeb 和 ZwSetInfomationObject

两个 icall 都清理为 call rax 不然反编译有问题

n2 = 0/2,设置 1,否则设置 0

5. 内存属性 泄漏
在 _guard_dispatch_icall_nop 下断点,当输入断在 rax=ZwProtectVirtualMemory 时就是触发第五个漏洞
调用参数为
rdx = ShadowGateApp.exe 的 .data 页
rcx = ShadowGateApp.exe 的 .data 页长度
将 .data 页的属性修改为 RW 或 ERW
1 | 3: kd> dq rdx L1 |

找了下没找到,看堆栈这个是真的在 vm 里面了,该泄漏通过观察页得到,猜测 sys 会修改名为 .data 的页


根据上面规则猜测 n2 = 0/2 时,页属性变成 PAGE_EXECUTE_READWRITE 其他时,保持 PAGE_READWRITE
查询迷宫 & 探索迷宫
方法一:r3 下通过泄漏探索迷宫
伪代码,完整见附件
1 | Init(): |
得到以下迷宫图
1 | .......#..... |
方法二:可以通过 sys 直接读取分配内存读取到迷宫


最短路径求解
bfs
1 | from __future__ import annotations |
Flag
flag{SHAD0WNT_HYPERVMX}
1 | ============================================= |