以前玩过一个叫Zombie Army Trilogy的游戏,感觉挺好玩的,突然想安排一下
OK,开始
打开游戏,x64dbg附加,发现居然断不下来,下断点断点命中游戏卡死,x64dbg依然显示运行中。。。这游戏居然有反调试。。。
貌似DbgPort清零了,调试器接收不到调试信息,但这游戏并没有驱动保护,在ring3层能达到DbgPort清零的效果一般是调用了SetInformationThread(),第二个参数设置为ThreadHideFromDebugger (值为17)。如果程序处于被调试状态,那么该函数就可以使当前线程(一般是主线程)脱离调试器,使调试器无法继续接收该线程的调试事件。
ScyllaHide插件可以HOOK这个函数,但我发现这个插件在win10 1903 貌似不管用(我到GitHub上面下的2020-1-25最新的,反正我的机子没效果),自己HOOK吧,如何HOOK可以参考我以前的文章
NTSTATUS MyNtSetInformationThread(
HANDLE ThreadHandle,
THREADINFOCLASS ThreadInformationClass,
PVOID ThreadInformation,
ULONG ThreadInformationLength
)
{
if (17 == ThreadInformationClass)
{
KdPrint(("NtSetInformationThread被调用,参数:%d\n", ThreadInformationClass));
return STATUS_SUCCESS;
}
return ((pNtSetInformationThread)S_NtSetInformationThread)(ThreadHandle,ThreadInformationClass,ThreadInformation,ThreadInformationLength);
}
现在游戏正常附加并且断下来了,刚开始F9运行没事,但是一旦命中断点后,再F9运行运行就GG。最后发现是时钟检测,在QueryPerformanceCounter、GetTickCount、GetSystemTime、GetLocalTime都下个断点,GetTickCount断下来了,改下函数头,让它直接返回0
好了,现在游戏可以正常调试了
游戏血量没有直接显示,要直接找血量比较麻烦,先不理它
CE找一下子弹数,最后剩两个地址,其中一个是绿色基址,锁定它们,子弹一样是正常减少。可能子弹数据加密了,在基址下内存写入断点,可以通过它找到是哪里改写了它从而找到真正的子弹数据(注意一些call,这里懒得截图了,放两张主要流程)
最终找到的数据:
狙击枪子弹(5发子弹的那种狙)=[[[[[[[[[ZAT.exe+6E5708]+24]+A4]+18]+C]+4]+24]+4]+1A4]
其解密算法(eax储存解密结果,ecx+1A4储存加密数据):
在CE里试一下锁定看看,结果一锁定游戏就退出。。。右键查看一下访问,发现有个检测,把它nop掉就可以锁定了
但只能锁定狙击枪而已,其他武器照样正常减子弹。可以通过这个狙击枪子弹数的地址用CE找到使枪子弹减少的代码,把它nop掉,就可以实现所有的枪都无限子弹了
同理可以找到其他数据:
无限爆炸武器(nop掉):
冲锋枪无扩散:
关键代码改为:
F3 0F5C C9 - subss xmm1,xmm1
90 - nop
90 - nop
90 - nop
90 - nop
F3 0F11 8B 64010000 - movss [ebx+00000164],xmm1
找血量的话可以先模糊搜索,然后给僵尸打一下搜索变化的,等呼吸回血完再搜索一次变化的,然后选择对比首次扫描
尝试锁一下就可以找到了
[[[[ZAT.exe+7A2144]+0]+4]+0]+578