Tinker 的绘制循环仅仅使用简单而传统的while (1)
。这没什么问题,但为 Web 设计时这也是要重写的,不过 Emscripten 已经帮我们准备好了。
无聊插播:当我反编译二进制文件时,Tinker.exe 已经拆掉版本验证了。一起来看看哪里发生了变化?
根据这篇文章,找到在这:
GetProductInfo = (BOOL (__stdcall *)(DWORD, DWORD, DWORD, DWORD, PDWORD))GetProcAddress(LibraryW, "GetProductInfo");
HIBYTE(v40) = 1;
if ( !GetProductInfo )
{
hInstance = (HINSTANCE)&v33;
sub_46D460(&v33, v6, 0x8A1u, 1, 0);
v42 = &v26;
v51 = 1;
sub_46D460(&v26, v6, 0x85Fu, 1, 0);
v51 = -1;
sub_4785C0(*(HWND *)(a3 + 4), v26, v27, v28, v29, v30, v31, (unsigned int)v32, v33, v34, v35, v36, v37, v38, v39);
return 0;
}
memset(VersionInformation, 0, sizeof(VersionInformation));
*(_DWORD *)VersionInformation = 284;
GetVersionExW((LPOSVERSIONINFOW)VersionInformation);
GetProductInfo(
*(_DWORD *)&VersionInformation[4],
*(_DWORD *)&VersionInformation[8],
*(unsigned __int16 *)&VersionInformation[276],
*(unsigned __int16 *)&VersionInformation[278],
(PDWORD)&v46);
CoInitialize(0);
和原文结构类似,不过因为判断语句中关键跳转指令被 Nope 掉的原因,原本应在if ( v43 != 1 && v43 != 28 || !v48 )
中执行的代码被移到了原本调用 goto 语句的地方(上面引用的代码块中的第三行),但那块地方的判断条件只是一个单纯的if ( !GetProductInfo )
,因此 Hack 之后的程序永远不会触发版本错误提示。