击败二进制验证¶
击败二进制验证就像不在游戏特定二进制内放置钩子一样简单。Windows API 函数上的跳转钩子和 IAT 钩子极其常见,所以只要可以,尽量使用这些方法,而不是在游戏二进制中使用跳转或近调用钩子。在必须直接钩住游戏代码的情况下,你可以通过拦截二进制扫描并欺骗数据匹配软件期望内容,来欺骗反作弊软件的二进制验证例程。
与 SBD 一样,二进制验证通常用 NtQueryVirtualMemory()扫描内存。要欺骗验证代码,从该函数上的钩子开始。然后,编写一个像这样的函数,在调用 NtQueryVirtualMemory() 时欺骗数据:
NTSTATUS onNtQueryVirtualMemory(
HANDLE process, PVOID baseAddress,
MEMORY_INFORMATION_CLASS
memoryInformationClass,
PVOID buffer, ULONG numberOfBytes, PULONG
numberOfBytesRead) {
process, baseAddress,
memoryInformationClass,
buffer, numberOfBytes, numberOfBytesRead);
// 把棘手代码放在这里的某处
return ret;
}
在这个钩子内部,你需要留意对已被你某个钩子修改的内存的任何扫描。
注 这个示例假设机器人只有一个钩子,并且前缀为 HOOK_ 的变量已经存在,描述钩子替换的代码。
清单 12-2 展示了一些扫描监控代码。
// 扫描是否针对当前进程?
bool currentProcess =
process == INVALID_HANDLE_VALUE ||
process == GetCurrentProcess();
// 钩子是否在被扫描的内存范围内?
auto endAddress = baseAddress + numberOfBytesRead
- 1;
bool containsHook =
(HOOK_START_ADDRESS >= baseAddress &&
HOOK_START_ADDRESS <= endAddress) ||
(HOOK_END_ADDRESS >= baseAddress &&
HOOK_END_ADDRESS <= endAddress);