首页
社区
课程
招聘
[原创]2026腾讯游戏安全竞赛pc端初赛
发表于: 3小时前 129

[原创]2026腾讯游戏安全竞赛pc端初赛

3小时前
129


2026腾讯游戏安全竞赛pc端初赛

仅为本人题解,并非参考答案不能保证正确,和其他题解的不同为第五点泄漏通信方式。



目录

一、成功加载驱动并与之正确通信,理解题目基本机制

1.1题目基本机制

1.2驱动加载

二、隐匿通信手段总结

2.1命名事件泄漏

2.2命名信号量泄漏

2.3 TEB 字段泄漏

2.4 句柄属性泄漏

2.5 页属性泄漏

2.6完整脚本验证

附:详细分析见后文

三、探索迷宫

3.1驱动端静态分析

3.2驱动端动态分析

3.3 迷宫地图

四、求解路径

五、flag

六、详细分析(针对隐蔽通道的分析)

6.1三环程序静态分析

6.2三环程序动态分析

6.3驱动静态分析

6.4命名事件泄漏

6.5命名信号量泄漏

6.6 TEB 字段泄漏

6.7句柄属性泄漏

6.8页属性泄漏

七、脚本介绍

7.1 监控脚本

7.2 解密脚本

 


一、成功加载驱动并与之正确通信,理解题目基本机制

 

1.1题目基本机制

题目提供两个文件:

- `ShadowGateApp.exe`:用户态控制台程序(Ring3

- `ShadowGateSys.sys`:内核驱动(Ring0

系统由用户态控制台与内核驱动通信,驱动内部隐藏一个加密迷阵。表面上系统不给任何反馈,但存在 5 种隐蔽信息泄露通道。需要:发现泄露通道、还原迷宫、求解最短路径、提取 Flag

 

三环程序启动时打印的 Banner 明确提示:

"The system is not as silent as it seems. Five hidden flaws betray the result of every move... after each reset, the first five successful moves reveal each flaw exactly once, in a fixed order."

 

即:每次 reset 后,前 5 次成功移动会按固定顺序各触发一次泄漏事件。

 

1.2驱动加载

 修改系统日期,驱动可以打上过期签名,即可成功加载。

二、隐匿通信手段总结

动态分析得到关键泄漏操作API槽位

 

 

 

2.1命名事件泄漏

驱动通过 ZwOpenEvent / ZwSetEvent 操作命名事件,将移动结果编码到事件信号中。

 

2.2命名信号量泄漏

驱动通过 ObReferenceObjectByName + KeReleaseSemaphore 操作用户态预先创建的命名信号量,将结果编码到信号量计数变化中。

 

2.3 TEB 字段泄漏

驱动通过 PsGetThreadTeb 获取目标线程的 TEB,并直接写入 TEB+0x68,也就是 LastErrorValue,从而把结果写入用户态可读字段。

 

2.4 句柄属性泄漏

驱动读取 TEB+0x1748 中保存的用户态句柄,并调用

ZwSetInformationObject(ObjectHandleFlagInformation) 修改该句柄的 HandleAttributes

 

2.5 页属性泄漏

 

驱动修改imagebase+0x5000页的属性为PAGE_EXECUTE_READWRITE (0x40)

 

2.6完整脚本验证

脚本验证(monitor_shadowgate.py

 

五条泄漏的正确判断:

[0001] 23:05:35

  rule1 event : OK

[0002] 23:05:36

  rule2 sem   : A 0->1 (delta=+1) ; B 0->0 (delta=+0)

[0003] 23:05:37

  rule3 teb68 : 0x00000000 -> 0xC0DE0001(success)

[0004] 23:05:38

  rule4 slot  : 0x00000000000000A4 -> 0x00000000000000A4

  rule4 attr  : attr16=00 00 (none) -> attr16=00 01 (PROTECT_FROM_CLOSE)

[0005] 23:05:39

  rule5 prot  : 0x00000004 (PAGE_READWRITE) -> 0x00000040 (PAGE_EXECUTE_READWRITE)  

 

五条泄漏的错误判断:

 

rule1 event : WALL

rule2 sem   : A 5->5 (delta=+0) ; B 0->1 (delta=+1)

rule3 teb68 : 0xC0DE0001(success) -> 0xC0DE0000(wall)

rule4 attr  : attr16=00 01 (PROTECT_FROM_CLOSE) -> attr16=00 00 (none)

rule5 prot  : 0x00000040 (PAGE_EXECUTE_READWRITE) -> 0x00000004 (PAGE_READWRITE)

 

 

 

附:详细分析见后文

 

三、探索迷宫

 

 

3.1驱动端静态分析


 



看到了关键信息,申请了页,名为Maze”,猜测为迷宫存储的具体位置。

3.2驱动端动态分析

双机验证一下,


 

Windbg下断点,

bp nt!PnpCallDriverEntry+0x44

g

加载驱动

bp rax

g

成功到DriverEntry,对比IDA,成功断下。

 

Pool2 = (void *)ExAllocatePool2(64, 0x1D8, 'ezaM');下断点,

 

成功断下,然后执行单步走,rrax存储的值,继续执行,打开三环进行通信,windbg访问内存,得到如下图:

 

 

3.3 迷宫地图

00 00 00 00 00 00 00 01 00 00 00 00 00

01 01 01 01 01 01 00 01 01 01 00 01 00

00 00 00 00 00 01 00 00 00 00 00 01 00

00 01 01 01 00 01 01 01 01 01 01 01 00

00 01 00 00 00 00 00 00 00 00 00 01 00

00 01 00 01 00 01 01 01 01 01 00 01 00

00 01 00 01 00 01 00 00 00 01 00 01 00

00 01 00 01 01 01 00 01 00 01 01 01 00

00 01 00 00 00 00 00 01 00 01 00 00 00

00 01 01 01 01 01 01 01 00 01 00 01 01

00 00 00 01 00 00 00 01 00 01 00 01 00

01 01 00 01 00 01 00 01 00 01 00 01 00

00 00 00 00 00 01 00 01 00 00 00 00 00

 

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

 

 

四、求解路径

 

脚本:shortest_path.py

DDDDDD SS DDDD WW DD SSSS SSSS AA SSSS DD

五、flag

 

flag{SHAD0WNT_HYPERVMX}

 

 

六、详细分析(针对隐蔽通道的分析)

 

已知前五步,每一步都有一种隐蔽的通信方式,并且拿到了地图和flag(第三部分)。

6.1三环程序静态分析

ida_ida.inf_set_auto_enabled(False)  ida停止自动分析

 

 

主函数如上图;驱动通信:MessageByEvent();MessageByIOwhile循环,其他基本都是打印。

 

 

创建了事件和信号量

 

 

 

信号量解密脚本:Semaphore.py

得到两个事件名和两个信号量。

 

Io通信,猜测为初始化的一部分(例如拿地图)。

 

6.2三环程序动态分析

while循环过程,因为没有看到通信函数。使用X64dbg getch下断点:

导入表找到getch函数,下断点。

 

 

通过栈回溯找到函数,并对ret前一步下断点

 

单步步过:

 

识别花指令,继续单步步过。

 

 

找到关键函数,ida静态看一下:

 

基本就是移动时与驱动的通信方式了,转到驱动,

6.3驱动静态分析

找到负责主要业务的函数。

 

 

分析汇编,通过导入DRIVER_OBJECT结构体,还原出来IRP分发函数,如下图:

 

三个函数看一下,很明显找到dispath

 

 

 

0x80012004--移动、0x80012008--R(重置)、0x8001200C--迷宫等初始化。

 

分析sub_140002161函数,发现是在Maze中写入数据,并且发现部分汇编并没有被成功反汇编,看一下,在0x0000000140317602处找到一个

call    loc_14040305A(动态分析这是泄漏分发函数

 

 

6.4命名事件泄漏

 

混淆太严重了,这时看了一下导入表

 

猜测很有可能和三环对的上,并且在string窗口也发现了相关字符串

 

 

 

交叉引用得到一个函数


 

ZwSetEvent下断点。

 

成功断下,找到第一种通信方式,脚本验证(monitor_event.py):

 

 

6.5命名信号量泄漏

 

考虑到信号量的初始化需要RtlInitUnicodeString函数,对字符串交叉引用,很容易得到了sub_140319A37函数,因为其他几个函数功能基本明确,这个仍有加密。

 

双机调试在RtlInitUnicodeString处下断点:

 

果然,断在第二处,并且在汇编代码中看到了下图:

 

 


脚本验证(monitor_semaphore.py):

 

 

 

6.6 TEB 字段泄漏

 

怀疑string中的函数,是出题人留下的信号,所以都引用看一下,得到下面的反汇编:

sub_140316ADF(交叉引用ProbeForWrite)

 

 

Windbg记录三环程序信息:

 

*Address = v10;下断点

 

Teb+0x68的位置写入00000000C0DE0001为正确路径。

如果被修改为00000000C0DE0001,说明可行;被修改为00000000C0DE0000,说明撞墙。

脚本验证(monitor_teb.py):

 

 

 

6.7句柄属性泄漏

 

ProbeForRead交叉引用得到函数,

 

 

其中0x1748比较让人在意,因为在三环中,也看到了对Teb+0x1748的动作,

 

(上图为三环程序的反编译)

重新拿一下线程地址,刚才重启了三环程序

 

 

 

对函数_guard_dispatch_icall_fptr()下断点,两处都下

 

 

 

执行,第四个d成功断下:

 

本质上调用nt!PsGetThreadTeb因为寄存器没有被修改p执行单步过,看返回值。

 

返回值为三环的线程,继续g。

 

所以下一个就是运行nt!ZwSetInformationObject参数解析如下:

Handle- 一个用于放置信息的手柄。句柄不需要授予任何特定的访问权限

ObjectInformationClass- 要设置的信息类型

ObjectInformation- 指向包含请求特定数据的缓冲区的指针

ObjectInformationLength- 提供的缓冲区大小(字节单位)。

此时的寄存器值为:

 

 

ZwSetInformationObject0xC4,4,0001,2;

p单步过执行:

 

rax==0,说明写入成功。

同时如果第五步输错,我这里输入的是w:

 

会再次调用写入 00 00。

 

 

 

op#3为w,op#4为d,也会写入 00 01,同时注意到,如果前四步为对,第五步为对的话,不会再次调用,只有错误情况才会调用。

脚本验证(monitor_teb.py):

 

 

 

6.8页属性泄漏

 

通过定位其他泄漏api相关的槽位

 

 

分析上下文得到下图,找到ZwProtectVirtualMemory函数

 

 

对槽位上的api下断点

 

 

三环运行第5步,成功断下

 

 

 

拿到修改页的地址00007ff66b1b5000

 

 

找到对应的ida地址。

 

脚本验证:(monitor_protect.py)

 

 

七、脚本介绍

 

monitor_shadowgate.py

自动外部监控,先加载该脚本,再启动三环程序

 


 



[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

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