2024鹅厂安全竞赛题解-初赛

image-20240421214715351

hack.exe

反调试

​ 对hack.exe脱外壳+IAT修复后,进行简单分析,可知存在三种检测反调试(不完全),后边调试dll_shellcode是还发现了有扫字符串。

​ 1、调用NtQueryInformationProcess 扫描进程的DebugPort。

image-20240317173702735

​ 2、清空dr寄存器。

image-20240317173717384

​ 3、隐藏线程

image-20240317173736127

token1

​ 运行hack.exe后,运行调试器附加后发现提示非法,且下次重新打开hack.exe时仍然提示。

image-20240317170300603

​ 偶然发现重启后,非法失效(不弹框),因此猜测存在写文件 or 傀儡进程检测。使用WinAPIOverride进行api监视(API Monotor被加黑),发现进程存在频繁读内存,且意外发现存在写内存(4D5A),因此考虑到dll-MapInject

439a9a0b23f027889ec8f272740bb995

​ 自行编写工具,hook WriteProcessMemoryReadProcessMemory

image-20240317171003438

​ 得到shellcode文件。

image-20240317171113180

​ 并且通过日志文件发现在最后一次弹窗的时候,有访问winlogon.exe内存1字节。

image-20240317171450397

​ 使用CE查看可知该内存的值为0xF,大胆修改为0后,第二次启动发现不弹窗,猜测已经过了检测,但原理没仔细分析,至少避免每次都要重启。

​ 对工具保存到的bin文件分析发现每个bin作用如下:

filename todo
9_10316_Taskmgr.exe_390_000002060B510000_58c.bin map_loader
10_10316_Taskmgr.exe_390_000002060B51058C_3f7e00.bin dll数据
11_10316_Taskmgr.exe_390_000002060B90838C_228.bin 调用map_loader的参数指针

​ 直接对dll进行分析,代码vm不多,对iat进行查看,发现可疑的APIWriteProcessMemory,交叉引用后得到相关位置,该处未vm,直接F5分析。

image-20240317172046646

​ 首先发现存在写addr+0xACE地址,并且是跨进程,与上边工具记录到的最后一条内容0x327eb92ace符合,并且写入的值(0xF),与实际内存查看一致。往下分析发现存在写文件。

image-20240317172453057

​ 记得题目条件有说写出token1,因此直接进行调试该处。

image-20240317172240158

​ 对CreateFileA打断点断下后,查看rcx值。

![$CRE%4CR$}CNQ8%MHT7`EFC](../images/Reverse/./2024鹅厂安全竞赛题解-初赛/$CRE%254CR$%7DCNQ8%25MHT7%60EFC-1710667944748-5.png)

​ 发现为C:\2024GameSafeRace.token1,接着继续往下F8,发现CreateFileA执行返回-1,呃,,OPEN_EXISTING,第二次重新操作,先手动在C盘创建该文件,然后再F8执行,一直执行到CloseHandle结束,对文件进行打开查看,得到token1。

QQ图片20240317173146

ace.sys

ace.sys需要在hack.exe启动后加载才行,不然驱动加载失败(非31返回值)。

image-20240317235824134

​ 首先是返回值31,第一个想法就是估计是个Loader,想双机,但是有题目调试,用之前写的反反调试工具尝试绕过,失败。驱动加载后尝试用一些ark(pchunter、ydark,noone,winark),但发现打开立马蓝屏,蓝屏代码为0xACE

​ 重新思考了一下,内核线程是跑在system进程里的,而且看题目描述运行时修改尽量少的内存,让两段token输出成功,那应该是挂了一个线程的用来输出flag的(r3层也是一个while在跑)。因此得出两点:

​ 1、system线程列表里挂着一个线程在等待flag输出。

​ 2、因为猜测ace.sys是作用是个Loader,因此线程所属模块极大可能是无模块。

​ 根据第一点,首先猜到是会不会有dbg输出,因此打开dbgviewdbgview++分别测试,发现无输出;因此疯狂尝试切换各种冷门ark,测试后发现WKE(https://github.com/AxtMueller/Windows-Kernel-Explorer)、OpenArk(https://github.com/BlackINT3/OpenArk)可以使用。

​ 打开WKEsystem进程的线程扫描,发现存在一个无模块线程。

image-20240318000953267

​ 因此下一步想法是dump,由于检测双机,因此使用了livekd(https://learn.microsoft.com/zh-cn/sysinternals/downloads/livekd)进行dump。

image-20240318001112456

​ 使用!address命令进行内存区域扫描,发现RegionSize相当大,全部dump显然不合理,因此只对部分内存dump(保证dump的内存中包含了完整的线程代码)。

image-20240318001254749

​ 使用ida加载后发现,代码段和r3的很类似。

image-20240318004204559

​ 对照反汇编进行分析,实际上rax_FFFF848C4C016018对应的函数是DbgPrintEx

image-20240318001442111

image-20240318001500150

​ 那就有点奇怪了,,,,明明有调用,但是没输出,那么考虑到Log是不是被过滤了。对注册表操作一段,发现还是没用,于是对调用参数进行分析。MSDN(https://learn.microsoft.com/zh-cn/windows-hardware/drivers/debugger/reading-and-filtering-debugging-messages)

image-20240318001728574

image-20240318001740675

​ 以往驱动开发中DbgPrintEx的参数二没印象可以传这个值,想到可能是需要修改参数?因此打开OpenArk直接修改对参数修改.

image-20240318002011345

​ 读一下,确保修改生效。

image-20240318002032835

​ 然后重新打开dbgview,发现token已经输出了。

image-20240317235649316

总结

flag{ 757f4749aebb1891ef5ac2a9b5439cea-8b3f14a24d64f3e697957c252e3a5686}