From b3fbc045a94a26001d6ef82226d65c68fda65d0d Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 29 Feb 2016 20:38:14 +0100 Subject: [PATCH] Optimize crash procedure --- deps/protobuf | 2 +- src/Components/Modules/AntiCheat.cpp | 85 +++++++++++++++++++++++---- src/Components/Modules/AntiCheat.hpp | 3 + src/Components/Modules/QuickPatch.cpp | 2 +- 4 files changed, 78 insertions(+), 14 deletions(-) diff --git a/deps/protobuf b/deps/protobuf index 60a0d41a..52f62e36 160000 --- a/deps/protobuf +++ b/deps/protobuf @@ -1 +1 @@ -Subproject commit 60a0d41a2988a40cf3a94a4cb602f5f1c94135e9 +Subproject commit 52f62e3652ce80ab14593331f4277539e7fa29c8 diff --git a/src/Components/Modules/AntiCheat.cpp b/src/Components/Modules/AntiCheat.cpp index 8ab4a630..6b2590e3 100644 --- a/src/Components/Modules/AntiCheat.cpp +++ b/src/Components/Modules/AntiCheat.cpp @@ -5,10 +5,35 @@ namespace Components int AntiCheat::LastCheck; std::string AntiCheat::Hash; + // This function does nothing, it only adds the two passed variables and returns the value + // The only important thing it does is to clean the first parameter, and then return + // By returning, the crash procedure will be called, as it hasn't been cleaned from the stack + void __declspec(naked) AntiCheat::NullSub() + { + __asm + { + push ebp + push ecx + mov ebp, esp + + xor eax, eax + mov eax, [ebp + 8h] + mov ecx, [ebp + 0Ch] + add eax, ecx + + pop ecx + pop ebp + retn 4 + } + } + void __declspec(naked) AntiCheat::CrashClient() { static uint8_t crashProcedure[] = { + // Variable space + 0xDC, 0xC1, 0xDC, 0x05, + // Uninstall minidump handler 0xB8, 0x63, 0xE7, 0x2F, 0x00, // mov eax, 2FE763h 0x05, 0xAD, 0xAD, 0x3C, 0x00, // add eax, 3CADADh @@ -21,19 +46,47 @@ namespace Components 0x05, 0xDD, 0x28, 0x1A, 0x00, // add eax, 1A28DDh 0x80, 0x00, 0x68, // add byte ptr [eax], 68h 0xC3, // retn + + // Random stuff + 0xBE, 0xFF, 0xC2, 0xF4, 0x3A, }; __asm { // This does absolutely nothing :P - // TODO: Obfuscate even more xor eax, eax mov ebx, [esp + 4h] shl ebx, 4h + setz bl - // Call our crash procedure - push offset crashProcedure - retn + // Push the fake var onto the stack + push ebx + + // Get address to VirtualProtect + mov eax, 6567h + shl eax, 0Ch + or eax, 70000A50h + + // Move the address into ebx + push eax + pop ebx + + // Save the address to our crash procedure + mov eax, offset crashProcedure + push eax + + // Unprotect the .text segment + push eax + push 40h + push 2D5FFFh + push 401001h + call ebx + + // Increment to our crash procedure + add dword ptr [esp], 4h + + // This basically removes the pushed ebx value from the stack, so returning results in a call to the procedure + jmp AntiCheat::NullSub } } @@ -44,14 +97,13 @@ namespace Components AntiCheat::Hash.clear(); } - void AntiCheat::Frame() + void AntiCheat::PerformCheck() { - // Perform check only every 30 seconds - if (AntiCheat::LastCheck && (Game::Com_Milliseconds() - AntiCheat::LastCheck) < 1000 * 30) return; - AntiCheat::LastCheck = Game::Com_Milliseconds(); - - // Get base module - std::string hash = Utils::Cryptography::SHA512::Compute(reinterpret_cast(GetModuleHandle(NULL)) + 0x1000, 0x2D6000, false); + // Hash .text segment + // Add 1 to each value, so searching in memory doesn't reveal anything + size_t textSize = 0x2D6001; + uint8_t* textBase = reinterpret_cast(0x401001); + std::string hash = Utils::Cryptography::SHA512::Compute(textBase - 1, textSize - 1, false); // Set the hash, if none is set if (AntiCheat::Hash.empty()) @@ -59,12 +111,21 @@ namespace Components AntiCheat::Hash = hash; } // Crash if the hashes don't match - else if(AntiCheat::Hash != hash) + else if (AntiCheat::Hash != hash) { AntiCheat::CrashClient(); } } + void AntiCheat::Frame() + { + // Perform check only every 30 seconds + if (AntiCheat::LastCheck && (Game::Com_Milliseconds() - AntiCheat::LastCheck) < 1000 * 30) return; + AntiCheat::LastCheck = Game::Com_Milliseconds(); + + AntiCheat::PerformCheck(); + } + AntiCheat::AntiCheat() { AntiCheat::EmptyHash(); diff --git a/src/Components/Modules/AntiCheat.hpp b/src/Components/Modules/AntiCheat.hpp index 4c322c98..94d89efb 100644 --- a/src/Components/Modules/AntiCheat.hpp +++ b/src/Components/Modules/AntiCheat.hpp @@ -15,5 +15,8 @@ namespace Components static std::string Hash; static void Frame(); + static void PerformCheck(); + + static void NullSub(); }; } diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 42e6a556..53b6eab2 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -44,7 +44,7 @@ namespace Components for (int j = 0; j < 10; ++j) { int progress = atoi(Game::TabeLookup(challengeTable, i, 6 + j * 2)); - if (!progress )break; + if (!progress) break; maxState = j + 2; maxProgress = progress;