腾讯游戏安全大赛2023初赛题解
终于如愿参加一次腾讯游戏安全大赛,也算是把所有题目都做出来了,进入决赛。
但是自己太菜了,只会暴力NOP。
腾讯游戏安全大赛初赛题解
参赛人员信息
略
找到明文
1.在64位Windows10系统上运行contest.exe, 找到明文的信息,作为答案提交(1分)。
答案:catchmeifyoucan
正常运行会在当前目录下的 contest.txt 去写入一个 ImVkImx9JG12OGtlImV+
。
CE打开,先通过CE的memory view找到一串一直在变化的内存。
虽然不确定,找到了 contest.txt 这个明文,但是 catchmeifyoucan
不确定它是不是flag,还得进一步确定,于是查找是谁访问了这个地址。
在第三项中,发现后面有一个读取 r10
所指示的内存的操作。
同样memory view查找 7FF713657190
地址,结果找到一串 base 表:
QRSTUVWXYZabcdefABCDEFGHIJKLMNOPwxyz0123456789+/ghijklmnopqrstuv
于是果断拿密文解密,发现得到了正确答案。
写入明文信息
2.编写程序,运行时修改尽量少的contest.exe内存,让contest.exe 由写入密文信息变为写入明文信息成功。(满分2分)
Base64编码的一组中,三个原文对应四个密文。第一个密文和第四个密文只会被原文第一个字符和第三个字符影响。第二个字符会被第一个原文和第二个原文字符影响,第三个字符会被第二个原文和第三个原文字符影响。
对 base 表进行访问查询,找到三个地址,对三个地址分析。
查看第一项访问地址
右移两位进行查表,很明显就是对第一个密文的操作,因此把中间的操作全部NOP,只剩读取和写入操作。
再对第二个项目分析,很明显看到了对第四个密文的操作:
这里的 and 0x3f
就是取得最低的六位,很明显是最后一位,同样也把中间的指令全部NOP掉。
不仅如此,同时注意到赋值的时候,对 r14+1了,并且r14的值在后面+1。这里有一个很头疼的点就是明文密文长度不一致,三个原文对应四个密文,因此这里可以为这个点考虑起来了。如果我 r14 的值不给他 +1,直接给 r14 的值赋值,结果会怎样呢?也就是对应指令修改为:
1 | mov [r14],al |
发现输出文件的内容果然变短了。
并且此时,我们再处理中间的一位,就能得到明文输出了。
我们来看第三个项目:
这里同样把 BA5D-BA68的代码段NOP掉,做完之后,发现contest输出明文了。
总结一下:
- contest.exe+BA39~BA41 全部NOP掉
- contest.exe+B9FD~BA04 全部NOP掉
- contest.exe+BA5D~BA68 全部NOP掉
- contest.exe+BA05开始,把指令变成:
1 | mov [r14],al |
编写dll进行一次性修改:
但是在写内存的时候,发现 VirtualProtect
一直调用失败,拿火绒剑扫了一下,发现 VirtualProtect
被下了钩子。
尝试修复一下这个钩子,写一个注入器和dll
思路讲解
DLL不能直接使用 VirtualProtect 去修改内存属性,所以我们需要在注入之前,使用 VirtualProtectEx
先修改内存权限,再通过 WriteProcessMemory
函数修复程序在 API
处下的一个钩子,这里是 inline hook
,因此直接遍历模块寻找 ZwProtectVirtualMemory
函数把钩子取消。
取消之后,即可使用远程线程注入的方式去注入dll,远程注入的思路就是开辟一块远程内存,写入dll路径,创建远程线程回调 LoadLibraryA
函数去加载 DLL。
DLL主要就是作上面分析的一些PATCH内存的操作。
下面是源码:
注入器
1 |
|
dll
1 |
|
更改写入文件
在一开始的时候我们在内存看到了 contest.txt
,于是尝试直接修改,发现可以成功更改写入的文件,因此为了达到目的我们可以直接修改这里的内存,但是因为它一直在变化,因此可以查看什么写了这个内存。
主要是做了一个异或运算,直接 NOP即可。
需要注意在把指令patch掉之后,一定要写一下这里存储 Name 的地方,把 Name 替换为自己想要的名字即可。
但是发现 flag 写进去时而变化,究其原因还是因为flag内存一直在变化,因此patch修改flag的内存让它也不再变化即可。
注入器不变,DLL 需要稍微改变一下。
1 |
|