From 7a3b48831bfc9c4aa8c39c1e42d5bf5dd73e43c5 Mon Sep 17 00:00:00 2001 From: boris Date: Tue, 1 Jan 2019 20:31:51 +1300 Subject: whole buncha fixes & switching to vmp --- csgo-loader/csgo-client/Security/Encryption.cpp | 43 +++-- csgo-loader/csgo-client/Security/Encryption.hpp | 14 +- .../csgo-client/Security/RuntimeSecurity.cpp | 194 ++++++++------------- .../csgo-client/Security/RuntimeSecurity.hpp | 18 +- 4 files changed, 124 insertions(+), 145 deletions(-) (limited to 'csgo-loader/csgo-client/Security') diff --git a/csgo-loader/csgo-client/Security/Encryption.cpp b/csgo-loader/csgo-client/Security/Encryption.cpp index 133946a..d361d1c 100644 --- a/csgo-loader/csgo-client/Security/Encryption.cpp +++ b/csgo-loader/csgo-client/Security/Encryption.cpp @@ -563,21 +563,36 @@ namespace Wrapper } // Wrapper for the AES256 encryption algorithm. - void Encryption::Start() { } + void Encryption::Start() + { + // Create cryptographic context. + if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, 0)) + { + if(!CryptAcquireContextA(&m_CryptProvider, nullptr, nullptr, PROV_RSA_AES, CRYPT_NEWKEYSET)) + INFO_ASSERT("Critical failure\nContact an admin with the following code: %08x", GetLastError()); + } + + uint8_t RandomBytes[32]; + uint32_t RandomBytesCount = sizeof RandomBytes; + + // Generate random bytes to use as encryption key. + if(CryptGenRandom(m_CryptProvider, RandomBytesCount, RandomBytes)) + std::memcpy(m_EncryptionKey, RandomBytes, RandomBytesCount); + + // Release context. + if(m_CryptProvider) + CryptReleaseContext(m_CryptProvider, 0); + } void Encryption::Start(ByteArray &EncryptionKey) { // If an encryption key is provided, initialise the wrapper with // the passed parameter. if(!EncryptionKey.empty()) - { - for(auto &It : EncryptionKey) - m_EncryptionKey.emplace_back(It); - } - else - { + std::memcpy(m_EncryptionKey, EncryptionKey.data(), EncryptionKey.size()); + + if(EncryptionKey.empty()) Start(); - } } ByteArray Encryption::Encrypt(ByteArray &Data) @@ -585,11 +600,7 @@ namespace Wrapper // Encrypt outgoing data. ByteArray Encrypted; - #ifdef DEBUG - Encrypted = Data; - #else - Aes256::encrypt(m_EncryptionKey, Data, Encrypted); - #endif + Aes256::encrypt(GetKey(), Data, Encrypted); return Encrypted; } @@ -599,11 +610,7 @@ namespace Wrapper // Decrypt incoming data. ByteArray Decrypted; - #ifdef DEBUG - Decrypted = Data; - #else - Aes256::decrypt(m_EncryptionKey, Data, Decrypted); - #endif + Aes256::decrypt(GetKey(), Data, Decrypted); return Decrypted; } diff --git a/csgo-loader/csgo-client/Security/Encryption.hpp b/csgo-loader/csgo-client/Security/Encryption.hpp index b1c49dc..bf1346e 100644 --- a/csgo-loader/csgo-client/Security/Encryption.hpp +++ b/csgo-loader/csgo-client/Security/Encryption.hpp @@ -5,6 +5,8 @@ #include #include +#include + using ByteArray = std::vector; #define BLOCK_SIZE 16 @@ -71,7 +73,7 @@ namespace Wrapper // Encryption wrapper. class Encryption { - ByteArray m_EncryptionKey; + uint8_t m_EncryptionKey[32]; HCRYPTPROV m_CryptProvider; public: @@ -87,7 +89,15 @@ namespace Wrapper // Exposes the encryption key. ByteArray GetKey() { - return m_EncryptionKey; + ByteArray TemporaryKey; + + TemporaryKey.insert( + TemporaryKey.begin(), + m_EncryptionKey, + m_EncryptionKey + sizeof m_EncryptionKey + ); + + return TemporaryKey; } }; } \ No newline at end of file diff --git a/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp b/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp index ab2ea87..6a5ce20 100644 --- a/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp +++ b/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp @@ -19,8 +19,6 @@ namespace Security decltype(&OpenProcess) oOpenProcess; HANDLE __stdcall Hooked_OpenProcess(DWORD AccessLevel, bool Inherit, DWORD ProcessId) { - WRAP_IF_RELEASE(VM_EAGLE_WHITE_START); - // Determine where the return address of the function actually points. void *Address = _ReturnAddress(); MEMORY_BASIC_INFORMATION Query = Protection->QueryMemory(Address); @@ -32,9 +30,7 @@ namespace Security if(ReturnModule != LoaderModule) { - WRAP_IF_RELEASE(STR_ENCRYPT_START); - Protection->SecurityCallback(__FUNCSIG__); - WRAP_IF_RELEASE(STR_ENCRYPT_END); + Protection->SecurityCallback("Malicious activity [Tampering]."); [&](decltype(&OpenProcess) A) { @@ -46,15 +42,11 @@ namespace Security // Call original function return oOpenProcess(AccessLevel, Inherit, ProcessId); - - WRAP_IF_RELEASE(VM_EAGLE_WHITE_END); } decltype(&ExitProcess) oExitProcess; void __stdcall Hooked_ExitProcess(DWORD ExitCode) { - WRAP_IF_RELEASE(VM_EAGLE_WHITE_START); - WRAP_IF_DEBUG(oExitProcess(ExitCode)); WRAP_IF_RELEASE( @@ -65,14 +57,11 @@ namespace Security A(NullPointer); }(oExitProcess); ); - - WRAP_IF_RELEASE(VM_EAGLE_WHITE_END); } decltype(&recv) oWSARecv; int __stdcall Hooked_WSARecv(SOCKET Socket, char *Buffer, int Length, int Flags) { - WRAP_IF_RELEASE(VM_EAGLE_WHITE_START); // Determine where the return address of the function actually points. void *Address = _ReturnAddress(); @@ -86,21 +75,17 @@ namespace Security // Let's meme anyone who tries to reverse this. if(ReturnModule != LoaderModule) { - WRAP_IF_RELEASE(STR_ENCRYPT_START); - return []() { Protection->SecurityCallback(__FUNCSIG__); return -1; }(); - WRAP_IF_RELEASE(STR_ENCRYPT_END); + return []() { Protection->SecurityCallback("Malicious activity [Tampering]."); return -1; }(); } // Call original function return oWSARecv(Socket, Buffer, Length, Flags); - WRAP_IF_RELEASE(VM_EAGLE_WHITE_END); } decltype(&send) oWSASend; int __stdcall Hooked_WSASend(SOCKET Socket, char *Buffer, int Length, int Flags) { - WRAP_IF_RELEASE(VM_EAGLE_WHITE_START); // Determine where the return address of the function actually points. void *Address = _ReturnAddress(); @@ -114,15 +99,11 @@ namespace Security // Let's meme anyone who tries to reverse this. if(ReturnModule != LoaderModule) { - WRAP_IF_RELEASE(STR_ENCRYPT_START); - return []() { Protection->SecurityCallback(__FUNCSIG__); return -1; }(); - WRAP_IF_RELEASE(STR_ENCRYPT_END); + return []() { Protection->SecurityCallback("Malicious activity [Tampering]."); return -1; }(); } // Call original function return oWSASend(Socket, Buffer, Length, Flags); - - WRAP_IF_RELEASE(VM_EAGLE_WHITE_END); } #pragma optimize("", on) @@ -139,8 +120,6 @@ namespace Security bool RuntimeSecurity::ApplyApiHooks() { - WRAP_IF_RELEASE(MUTATE_START); - // Make sure that MinHook is initialized properly. CreateMinHook(); CheckStatus(); @@ -159,17 +138,12 @@ namespace Security SafeCallTo(MH_EnableHook(&send)); return true; - - WRAP_IF_RELEASE(MUTATE_END); } #pragma optimize("", on) void RuntimeSecurity::PatchDebugFunctions() { - WRAP_IF_RELEASE(VM_EAGLE_WHITE_START); - WRAP_IF_RELEASE(STR_ENCRYPT_START); - HMODULE Module = GetModuleHandleA("ntdll.dll"); if(!Module) @@ -199,26 +173,19 @@ namespace Security ERROR_ASSERT("[000F:00001A00] Failed to initialize. Please contact an administrator."); // Patch to __asm { jmp oExitProcess; }; - *(uint8_t *)It = 0xE9; - *(uint32_t *)(It + 1) = (uintptr_t)oExitProcess; + *(uint8_t *)It = 0xE9; + *(uintptr_t *)(It + 1) = (uintptr_t)oExitProcess; VirtualProtect((void *)It, sizeof uintptr_t + 1, OldProtection, &OldProtection); } - - WRAP_IF_RELEASE(STR_ENCRYPT_END); - WRAP_IF_RELEASE(VM_EAGLE_WHITE_END); } void RuntimeSecurity::DispatchSecurityThreads() { - WRAP_IF_RELEASE(MUTATE_START); - std::thread DebugThread (&RuntimeSecurity::CheckForDebugger, this); DebugThread.detach(); std::thread VMThread (&RuntimeSecurity::CheckForVirtualMachine, this); VMThread.detach(); std::thread DriverThread(&RuntimeSecurity::CheckForDrivers, this); DriverThread.detach(); std::thread TamperThread(&RuntimeSecurity::CheckForTampering, this); TamperThread.detach(); - - WRAP_IF_RELEASE(MUTATE_END); } // The following functions are only called internally. @@ -230,35 +197,15 @@ namespace Security void RuntimeSecurity::CheckForVirtualMachine() { - WRAP_IF_RELEASE(VM_EAGLE_BLACK_START); - for(;;) { - // Yeah, um, your code did absolutely fuck all in my analysis VM. - int32_t VirtualMachineChecksum = 0x4000; - - WRAP_IF_RELEASE( - CHECK_VIRTUAL_PC(VirtualMachineChecksum, 0x2000); - - WRAP_IF_RELEASE(STR_ENCRYPT_START); - if(VirtualMachineChecksum != 0x2000) - SecurityCallback(__FUNCSIG__); - WRAP_IF_RELEASE(STR_ENCRYPT_END); - ); - // Don't put too much stress on the CPU. - Sleep(VirtualMachineChecksum); + Sleep(1); } - - - WRAP_IF_RELEASE(VM_EAGLE_BLACK_END); } void RuntimeSecurity::CheckForDebugger() { - WRAP_IF_RELEASE(VM_EAGLE_BLACK_START); - WRAP_IF_RELEASE(STR_ENCRYPT_START); - for(;;) { // Read the PEB from the TIB. @@ -303,67 +250,73 @@ namespace Security // size_t Index = std::distance(...); if(FindWindowA(It.first, It.second)) - SecurityCallback(__FUNCSIG__); + SecurityCallback("Malicious activity [Debugging attempt]."); } // Don't put too much stress on the CPU. - Sleep(150); + Sleep(1); } - - WRAP_IF_RELEASE(STR_ENCRYPT_END); - WRAP_IF_RELEASE(VM_EAGLE_BLACK_END); } void RuntimeSecurity::CheckForDrivers() { - WRAP_IF_RELEASE(VM_EAGLE_BLACK_START); - - // TODO: Check if test-signing mode is on - // TODO: Check if safe-mode is on - // TODO: Check for disallowed drivers for(;;) { + static const char *BlackListedDrivers[] = { + "Sbie", // Sandboxie + "NPF", // WireShark / WinPCAP + "acker", // Process Hacker + "CEDRI" // Cheat Engine + "VBox", // VirtualBox + }; + + static const char *BlackListReasons[] = { + "Please uninstall Sandboxie.", + "Please uninstall WireShark.", + "Please close Process Hacker.", + "Please close Cheat Engine.", + "Please uninstall VirtualBox." + }; + + uint16_t Length = sizeof BlackListedDrivers / sizeof(BlackListedDrivers[0]); + + void *DriverList[1024]; + DWORD Needed; + + if(K32EnumDeviceDrivers(DriverList, sizeof DriverList, &Needed)) + { + if(Needed > sizeof DriverList) + ERROR_ASSERT("[00DF:00001CFF] A security thread has failed. Contact an administrator."); + + char DriverName[1024]; + uint32_t DriverCount = Needed / sizeof DriverList[0]; + + for(size_t n{}; n < DriverCount; ++n) + { + if(K32GetDeviceDriverBaseNameA(DriverList[n], DriverName, sizeof DriverName / sizeof DriverList[0])) + { + for(size_t j{}; j < Length; ++j) + { + if(strstr(DriverName, BlackListedDrivers[j])) + ERROR_ASSERT(BlackListReasons[j]); + } + } + } + } // Don't put too much stress on the CPU. - Sleep(150); + Sleep(1); } - - WRAP_IF_RELEASE(VM_EAGLE_BLACK_END); } void RuntimeSecurity::CheckForTampering() { - WRAP_IF_RELEASE(VM_EAGLE_BLACK_START); - for(;;) { - int32_t CodeIntegrityChecksum = 0x2000; - - WRAP_IF_RELEASE( - CHECK_CODE_INTEGRITY(CodeIntegrityChecksum, 0x4000); - - WRAP_IF_RELEASE(STR_ENCRYPT_START); - if(CodeIntegrityChecksum != 0x4000) - SecurityCallback(__FUNCSIG__); - WRAP_IF_RELEASE(STR_ENCRYPT_END); - ); - - WRAP_IF_RELEASE( - CHECK_PROTECTION(CodeIntegrityChecksum, 0x4000); - - WRAP_IF_RELEASE(STR_ENCRYPT_START); - if(CodeIntegrityChecksum != 0x4000) - SecurityCallback(__FUNCSIG__); - WRAP_IF_RELEASE(STR_ENCRYPT_END); - ); - // Don't put too much stress on the CPU. - Sleep(CodeIntegrityChecksum); + Sleep(1); } - - - WRAP_IF_RELEASE(VM_EAGLE_BLACK_END); } #pragma optimize("", on) @@ -387,32 +340,43 @@ namespace Security return true; } + constexpr uintptr_t KUSER_SHARED_DATA = 0x7FFE0000; + HardwareIdentifier RuntimeSecurity::GetHardwareId() { + HardwareIdentifier Identifier{}; + + // CPU information + Identifier.m_CpuCount = *(uint32_t *)(KUSER_SHARED_DATA + 0x3C0); + Identifier.m_CpuArchitecture = *(uint16_t *)(KUSER_SHARED_DATA + 0x26A); + + // CPU features + + // Safe-mode + Identifier.m_SpecialMode[0] = *(uint8_t *)(KUSER_SHARED_DATA + 0x2EC); + + // Test-signing mode + return HardwareIdentifier{}; } #pragma optimize("", off) - MEMORY_BASIC_INFORMATION RuntimeSecurity::QueryMemory(void *Address) + __declspec(noinline) MEMORY_BASIC_INFORMATION RuntimeSecurity::QueryMemory(void *Address) { - static auto ZwQueryVirtualMemory = Syscalls->Find(FNV("ZwQueryVirtualMemory")); - MEMORY_BASIC_INFORMATION Result{}; - NTSTATUS Status = ZwQueryVirtualMemory((HANDLE)-1, Address, 0, &Result, sizeof Result, nullptr); + + // VirtualQuery is also referenced in MinHook lib, will be a pain to find anyway + // especially if I have VMP encrypt all this shit. + bool Success = VirtualQuery(Address, &Result, sizeof Result); - if(NT_ERROR(Status)) + if(!Success) { - char ReasonParameter[64]; + char ReasonParameter[64]; + uint32_t Status = GetLastError(); - WRAP_IF_DEBUG(sprintf_s(ReasonParameter, "[QueryMemory] NTSTATUS: %08x", Status)); - WRAP_IF_RELEASE( - sprintf_s(ReasonParameter, "[00DF:%08x] There was an error with accessing a process.", Status); - ERROR_ASSERT(ReasonParameter); - ); - - // yeet - SecurityCallback(ReasonParameter); + sprintf_s(ReasonParameter, "[00DF:%08x] There was an error with accessing a process.", Status); + ERROR_ASSERT(ReasonParameter); } return Result; @@ -420,13 +384,10 @@ namespace Security void RuntimeSecurity::SecurityCallback(const char *Reason) { - WRAP_IF_RELEASE(VM_FISH_WHITE_START); - static bool TriggeredCallback = false; if(!TriggeredCallback) { - WRAP_IF_RELEASE(STR_ENCRYPT_START); // You can use the reason parameters to debug the security in case // something weird starts going on with it. @@ -443,10 +404,7 @@ namespace Security ); TriggeredCallback = true; - WRAP_IF_RELEASE(STR_ENCRYPT_END); } - - WRAP_IF_RELEASE(VM_FISH_WHITE_END); } #pragma optimize("", on) diff --git a/csgo-loader/csgo-client/Security/RuntimeSecurity.hpp b/csgo-loader/csgo-client/Security/RuntimeSecurity.hpp index f74e778..9fe5c51 100644 --- a/csgo-loader/csgo-client/Security/RuntimeSecurity.hpp +++ b/csgo-loader/csgo-client/Security/RuntimeSecurity.hpp @@ -10,13 +10,17 @@ #include #include +// EnumDeviceDrivers +#include + // WinInet #include #pragma comment(lib, "wininet.lib") -// Required for the SDK from Themida which offers multiple -// virtual machines and string encryption, as well as debug/VM checks. -#include +// Required for the SDK from VMP which offers +// virtual machines and string encryption, as +// well as debug/VM checks. + // Required for MinHook. #include @@ -35,9 +39,6 @@ // Sick macros, retard. #define WRAP_IF_RELEASE( s ) { s; } #define WRAP_IF_DEBUG( s ) - - // Link against Themida's SecureEngine. - #pragma comment(lib, "SecureEngine.lib") #endif namespace Security @@ -50,11 +51,14 @@ namespace Security uint16_t m_CpuArchitecture; uint32_t m_CpuCount; - // String-literal - contains list of CPU features. + // Contains list of CPU features. char m_CpuFeatures[64]; // Hash of the hard disk serial identifier. uint32_t m_HardDiskSerialHash; + + // Safe-mode/Test-signing mode status + uint8_t m_SpecialMode[2]; }; // This class implements the runtime security system. -- cgit v1.2.3