https://bugs.winehq.org/show_bug.cgi?id=45936
--- Comment #10 from Anastasius Focht focht@gmx.net --- Hello mirh,
--- quote --- So.. Like, the thing has gone open source just for the records. Not sure if it couldn't help. --- quote ---
well, it essentially confirms my analysis for LoadLibrary{Ex}{A,W} hooks. The issue is obviously still present.
https://github.com/IW4x/iw4x-client/blob/23e9aa7ac0107a3a7a8c7cda2de4287f127...
--- snip --- void AntiCheat::InitLoadLibHook() { __VMProtectBeginUltra(""); static uint8_t kernel32Str[] = { 0xB4, 0x9A, 0x8D, 0xB1, 0x9A, 0x93, 0xCC, 0xCD, 0xD1, 0x9B, 0x93, 0x93 }; // KerNel32.dll static uint8_t loadLibAStr[] = { 0xB3, 0x90, 0x9E, 0x9B, 0xB3, 0x96, 0x9D, 0x8D, 0x9E, 0x8D, 0x86, 0xBE }; // LoadLibraryA static uint8_t loadLibWStr[] = { 0xB3, 0x90, 0x9E, 0x9B, 0xB3, 0x96, 0x9D, 0x8D, 0x9E, 0x8D, 0x86, 0xA8 }; // LoadLibraryW
HMODULE kernel32 = GetModuleHandleA(Utils::String::XOR(std::string(reinterpret_cast<char*>(kernel32Str), sizeof kernel32Str), -1).data()); if (kernel32) { FARPROC loadLibA = GetProcAddress(kernel32, Utils::String::XOR(std::string(reinterpret_cast<char*>(loadLibAStr), sizeof loadLibAStr), -1).data()); FARPROC loadLibW = GetProcAddress(kernel32, Utils::String::XOR(std::string(reinterpret_cast<char*>(loadLibWStr), sizeof loadLibWStr), -1).data());
std::string libExA = Utils::String::XOR(std::string(reinterpret_cast<char*>(loadLibAStr), sizeof loadLibAStr), -1); std::string libExW = Utils::String::XOR(std::string(reinterpret_cast<char*>(loadLibWStr), sizeof loadLibWStr), -1);
libExA.insert(libExA.end() - 1, 'E'); libExA.insert(libExA.end() - 1, 'x');
libExW.insert(libExW.end() - 1, 'E'); libExW.insert(libExW.end() - 1, 'x');
FARPROC loadLibExA = GetProcAddress(kernel32, libExA.data()); FARPROC loadLibExW = GetProcAddress(kernel32, libExW.data());
if (loadLibA && loadLibW && loadLibExA && loadLibExW) { #ifdef DEBUG_LOAD_LIBRARY AntiCheat::LoadLibHook[0].initialize(loadLibA, LoadLibaryAStub, HOOK_JUMP); AntiCheat::LoadLibHook[1].initialize(loadLibW, LoadLibaryWStub, HOOK_JUMP); AntiCheat::LoadLibHook[2].initialize(loadLibExA, LoadLibaryExAStub, HOOK_JUMP); AntiCheat::LoadLibHook[3].initialize(loadLibExW, LoadLibaryExWStub, HOOK_JUMP); #else static uint8_t loadLibStub[] = { 0x33, 0xC0, 0xC2, 0x04, 0x00 }; // xor eax, eax; retn 04h static uint8_t loadLibExStub[] = { 0x33, 0xC0, 0xC2, 0x0C, 0x00 }; // xor eax, eax; retn 0Ch AntiCheat::LoadLibHook[0].initialize(loadLibA, loadLibStub, HOOK_JUMP); AntiCheat::LoadLibHook[1].initialize(loadLibW, loadLibStub, HOOK_JUMP); AntiCheat::LoadLibHook[2].initialize(loadLibExA, loadLibExStub, HOOK_JUMP); AntiCheat::LoadLibHook[3].initialize(loadLibExW, loadLibExStub, HOOK_JUMP); #endif } }
static uint8_t ldrLoadDllStub[] = { 0x33, 0xC0, 0xC2, 0x10, 0x00 }; static uint8_t ldrLoadDll[] = { 0xB3, 0x9B, 0x8D, 0xB3, 0x90, 0x9E, 0x9B, 0xBB, 0x93, 0x93 }; // LdrLoadDll
HMODULE ntdll = Utils::GetNTDLL(); //AntiCheat::LoadLibHook[4].initialize(GetProcAddress(ntdll, Utils::String::XOR(std::string(reinterpret_cast<char*>(ldrLoadDll), sizeof ldrLoadDll), -1).data()), ldrLoadDllStub, HOOK_JUMP);
// Patch LdrpLoadDll Utils::Hook::Signature::Container container; container.signature = "\x8B\xFF\x55\x8B\xEC\x83\xE4\xF8\x81\xEC\x00\x00\x00\x00\xA1\x00\x00\x00\x00\x33\xC4\x89\x84\x24\x00\x00\x00\x00\x53\x8B\x5D\x10\x56\x57"; container.mask = "xxxxxxxxxx????x????xxxxx????xxxxxx"; container.callback = [](char* addr) { static uint8_t ldrpLoadDllStub[] = { 0x33, 0xC0, 0xC2, 0x0C, 0x00 }; AntiCheat::LoadLibHook[5].initialize(addr, ldrpLoadDllStub, HOOK_JUMP); };
Utils::Hook::Signature signature(ntdll, Utils::GetModuleSize(ntdll)); signature.add(container); //signature.process();
__VMProtectEnd; } --- snip ---
$ wine --version wine-5.6-299-gf65cfbfe9b
Regards