首页
社区
课程
招聘
[原创]2026腾讯游戏安全PC初赛 新手使用IDAPRO+AI结合参赛 分析复盘
发表于: 1天前 513

[原创]2026腾讯游戏安全PC初赛 新手使用IDAPRO+AI结合参赛 分析复盘

1天前
513

这篇文章是我对 ShadowGate 题目的完整复盘整理版。

和我之前的阶段性记录不同,这一版的目标不是只写“我已经做到哪”,而是尽可能把整道题的分析链路整理完整,形成一篇可以单独阅读的文章。

不过我想把边界说清楚:

· 文中有一部分内容,是我自己本地逆向、写工具、验证协议后得到的结论;

· 还有一部分,是我当时没有完全做出来,后面参考了吾爱破解上一篇公开 writeup 才补齐的内容;

· 所以这篇文章不是“纯原创完整通关”,而是一篇以我的分析为主、并结合公开 writeup 补全后续步骤的复盘文。

这样写的好处是比较诚实,也更接近真实的做题过程。

题目样本主要包括三部分:

· 驱动:ShadowGateSys.sys

· IDA 数据库:ShadowGateSys.sys.i64

· 用户态程序:ShadowGateApp.exe

从题目行为来看,它表面上是一个“迷宫 + 驱动 + 最短路”的组合题,但真正核心并不是迷宫本身,而是:

· 用户态如何与驱动通信;

· 驱动如何把“移动结果”反馈回用户态;

· 这些反馈中,哪些是正常返回,哪些是隐藏泄露通道。

如果把题目拆开,其实就是:

1. 加载驱动并正确通信;

2. 找出所有隐匿通信方式;

3. 还原迷宫地图;

4. 求最短路;

5. 到达终点并恢复最终 Flag。

这题最先让我锁定方向的,不是驱动,而是用户态控制台程序。

从 ShadowGateApp.exe 的字符串和控制逻辑里,可以直接得到:

· 设备路径:\\.\ShadowGate

· 两个全局事件:

o Global\MazeMoveOK

o Global\MazeMoveWall

对应截图如下:

这一步非常关键,因为它说明:

· 这题并不是完全黑盒;

· 用户态和驱动之间存在一个清晰可复现的通信入口;

· 同时,“移动结果”很可能还通过命名事件额外传回用户态。

回到 ShadowGateSys.sys 之后,我本地确认到:

· DriverEntry 在 0x140008000

· 很快会跳转到实际初始化例程

初始化阶段至少做了这些事情:

1. 分配一块大小为 0x1D8 的内存;

2. 创建设备对象 \Device\ShadowGate;

3. 创建符号链接 \??\ShadowGate;

4. 注册分发函数。

驱动侧对应设备路径与用户态完全对上:

· 驱动:\Device\ShadowGate

· 符号链接:\??\ShadowGate

· 用户态:\\.\ShadowGate

这意味着我后续完全可以围绕 CreateFileW + DeviceIoControl 来做实验。

我本地确认到的主要分发表如下:

· IRP_MJ_CREATE -> 0x1400014B0

· IRP_MJ_CLOSE -> 0x140001410

· IRP_MJ_DEVICE_CONTROL -> 0x140001540

· DriverUnload -> 0x140001840

所以这题真正要啃的核心函数,其实就是:

· IRP_MJ_DEVICE_CONTROL

也就是说,整道题的协议层本质上就是若干个 IOCTL。

我当时本地最先恢复出来的三个控制码是:

IOCTL

功能

输入

输出

0x8001200C

查询迷宫几何信息

24 字节

0x80012008

重置迷宫状态

0x80012004

执行移动

12 字节

0x84 字节

其中 0x8001200C 返回六个 DWORD:

· width

· height

· entry_x

· entry_y

· exit_x

· exit_y

公开 writeup 里对这三个 IOCTL 的识别图如下:

这一部分我本地和公开 writeup 是能互相印证的。

从 ShadowGateApp.exe 的命令跳转表中,我本地能恢复出一套应用层方向语义:

· UP = 0x10

· DOWN = 0x20

· LEFT = 0x30

· RIGHT = 0x40

接受的按键分别是:

· W / I

· S / K

· A / J

· D / L

程序还支持:

· R:重置

· T:查看日志

· H:帮助

· Q / ESC:退出

到这里为止,我已经能比较稳定地还原“控制台程序怎么看待方向”的这一层。

这是我当时最重视的一部分,因为我觉得这题的本质不在迷宫,而在“反馈机制”。

已经明确存在:

· Global\MazeMoveOK

· Global\MazeMoveWall

这组名字几乎已经把用途写脸上了:

· 成功前进 -> MazeMoveOK

· 撞墙失败 -> MazeMoveWall

我本地还恢复出了两组混淆后的名字:

· Global\{B8E2C3D0

· Global\{A7F3B2C1

结合驱动中出现的:

· ObReferenceObjectByName

· KeReleaseSemaphore

· ObfDereferenceObject

我能比较有把握地说:

· 除了事件以外,驱动还会通过命名信号量额外传递状态。

为了不让分析停留在“静态猜测”,我本地还写了一个工具:

· tools/shadowgate_tool.py

它现在已经能做:

· 打开 \\.\ShadowGate

· 调 query / reset / move

· 监控命名事件

· 监控命名信号量

· 统计耗时

· 读取返回缓冲区关键字段

· 可选监控用户态内存变化

也就是说,我当时虽然还没完整把题做完,但已经把后续实验框架搭起来了。

这一节的内容,严格来说不属于“我当时已经独立做出来的结果”,而是我后面参考了吾爱破解那篇文章之后,重新整理并补进来的。

我会尽量用自己的表达去写,但要明确说明来源。

参考文章:


传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 8小时前 被kanxue编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 114
活跃值: (170)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢
4小时前
0
雪    币: 20
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3

这个题我现在觉得应该直接dump驱动内存来分析会好一点,直接把驱动内存读出来,迷宫地图和最短步数都是明文的,再反过来想办法写自动探索地图(因为时序泄漏探测起来很不可靠,写R3的DFS探索很容易误判)

最后于 28分钟前 被XieCZ1337编辑 ,原因:
4小时前
0
游客
登录 | 注册 方可回帖
返回