首页
社区
课程
招聘
[原创]2022腾讯游戏安全决赛PC端解题
发表于: 2022-4-30 22:01 13649

[原创]2022腾讯游戏安全决赛PC端解题

2022-4-30 22:01
13649

这里借尸还魂用初赛的程序来当成dwm做测试
图片描述

看到决赛题目加了个驱动,盲猜:功能肯定在驱动里面~
图片描述
无花无壳,IDA之!
注册了一个FirmwareTableCallback
图片描述

驱动主要逻辑功能在14A0中,主要看截图函数和说明吧
图片描述

找到需要的函数之后,解密shellcode
图片描述

通过mdl方式hook和unhook
图片描述

FixVad的时候成功之后没有减去引用计数[BUG](没事,反正没用到驱动)
图片描述

patch一下,修复此bug,增加引用计数的释放
图片描述

没看,因为没用到...
看完驱动逻辑之后发现主要实现已经给出,所以exe不需要看了。

命题的实现方法:

笔者的实现方式:

找到 dwm.exe 的 D3DCOMPILER_47.dll 和 dxgi.dll:
D3DCOMPILER_47.dll 和 dxgi.dll 是系统share类型dll,故而全局进程内的模块地址都应该一致的,通过process hacker证实。
图片描述

定位到 D3DCompile 函数和 PresentMultiplaneOverlay 函数
由1得知,既然一致,那直接写个demo程序,LoadLibrary此两个dll,通过模拟驱动获取模块的逻辑,也是一样的效果
图片描述

解密 shellcode 并且注入到 dwm.exe 进程里面
解密shellcode的代码逻辑可以直接从驱动反汇编里面扣出来。但是,特征码代码太巨型,怎么办?这里使用mapfile方式将驱动加到进程模块列表当中,那就等于访问普通dll方式来访问了!
图片描述

映射完驱动文件之后,通过扣驱动的获取PresentMultiplaneOverlay地址的特征搜索代码实现获取对应函数
图片描述

扣驱动的shellcode解密和生成hook跳的代码
图片描述

hook PresentMultiplaneOverlay 跳转到 shellcode 执行
最后是hook和unhook,一样的扣驱动代码
图片描述
图片描述

问题:
因为是直接注入到dwm进程实现的功能,那么在调试shellcode的时候,就会有一个很大的问题:dwm不能卡住啊!卡住了你界面都没法动了。

解决方法:
既然驱动都能借尸还魂,那么dwm能不能也借一下?
回过头看了一眼初赛题,哎~这不巧了!这就是一具嗷嗷待借的尸啊!
注: 初赛.exe没有D3DCOMPILER_47.DLL,只有D3DCOMPILER_43.DLL。但不碍事。

代码逻辑不变,将进程改成初赛.exe,完美实现将shellcode注入到了进程中,这不就可以直接当作普通进程一样进行shellocde动态调试了么!

hook 初赛shellcode + 0x420 jmp到决赛shellcode + 0x420
图片描述

直接F5 shellcode的话,笔者的IDA没法还原真正的伪代码逻辑
图片描述

参考调试问题的解决方法,F5动态调试的代码,不就可以还原更友好的伪代码了么!(F5赛高!)
图片描述
通过上图可以明显看出,动态调试之后的代码识别比静态时候更友好(也可能是笔者静态分析时候不懂用ida去patch,望赐教)

直接扣IDA动态调试时候生成的F5伪代码,将shellcode + 0x420的函数,也就是虚拟机抠出来。通过直接调用。
虚拟机命令码解密需要跑6次,第7次呢跑出来的就是最后绘图的所有点信息
图片描述

虚拟机主体逻辑跟初赛类似:
生成坐标对应key
图片描述

经过调试发现,点其实都全部画了,只是前面11个点的坐标被赋值成了负值,也就是flag被设置成了负值坐标
图片描述

负值如何产生?虚拟机里的sub就成了最大的嫌疑
图片描述

通过对sub添加输出信息,明显发现前11个点存在着异常sub数据,分别减去了1000和500,从12点开始数据就正常了。前面11个点?那不恰好是flag么~
图片描述

直接将1000和500的数值去掉,可以获取到flag的真实坐标
图片描述

可是画出来的很多不能显示
图片描述

既然坐标是对的,还不能显示,那只能说明是key不对,如下图:
第11个点:
decrypt -> x key = 0xc42d8b, y key = 0x38f0f
draw -> x key = 0x38f0f, y key = 0xc42d8b

第12个点:
decrypt -> x key = 0xeabf17, y key = 0x8f7323
draw -> x key = 0xeabf17, y key = 0x8f7323

对比发现,第11个点的key在draw时候被翻转了。
图片描述

笔者在琢磨着怎么解决翻转问题的时候,突然灵光一闪,哎?等会!
既然decrypt是只执行一次的,并且此时数据是正确的
而最终的draw也是只执行一次,并且根据正确的数值去画图
那么,decrypt之后,直接调用draw的话,那不就已经是正确的数据了么?!
图片描述

1.patch虚拟机的sub处理,发现等于1000和500的时候直接sub 0
2.patch虚拟机的key生成部分,生成之后直接调用draw画图

1.patch sub处理
shellcode + 0x627 处是sub处理, hook之
图片描述

判断是否是1000和500,是的话不处理
图片描述

2.patch decrypt key处理
shellcode + 0x7a5 处是decrypt key处理,在处理结尾处hook之
图片描述

将算出来的坐标key,直接保存成draw的参数位置,然后jmp回draw函数
图片描述

红色箭头位置是调用draw函数的地方
图片描述

well done~!
图片描述

先看看hook PresentMultiplaneOverlay处,通过push mov ret方式写入一个x64 long jmp, 跳到shellcode + 0x860处
图片描述


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2022-4-30 22:22 被z许编辑 ,原因: 错别字
上传的附件:
收藏
免费 3
支持
分享
最新回复 (3)
雪    币: 6124
活跃值: (4606)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
2
很吊
2022-5-2 21:55
0
雪    币: 38
活跃值: (798)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
很吊
2023-9-30 22:13
0
雪    币: 2698
活跃值: (30776)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2023-9-30 23:08
1
游客
登录 | 注册 方可回帖
返回
//