From b9702fe8541e61f27f5c788dc72feaefe5abfc0d Mon Sep 17 00:00:00 2001 From: boris Date: Tue, 1 Jan 2019 14:35:30 +1300 Subject: eeeeeeeeeeeeeeek --- csgo-loader/ThemidaSettings._ini | 13 +- csgo-loader/ThemidaSettings.tmd | Bin 11215 -> 11302 bytes csgo-loader/csgo-client/Client.cpp | 40 +++-- .../csgo-client/Security/RuntimeSecurity.cpp | 169 +++++++++++++++------ .../csgo-client/UserExperience/UserInterface.cpp | 2 + .../csgo-client/UserExperience/UserInterface.hpp | 3 + csgo-loader/csgo-client/csgo-client.vcxproj | 12 +- csgo-loader/to-do list.txt | 10 +- 8 files changed, 174 insertions(+), 75 deletions(-) diff --git a/csgo-loader/ThemidaSettings._ini b/csgo-loader/ThemidaSettings._ini index a03ee59..196b83a 100644 --- a/csgo-loader/ThemidaSettings._ini +++ b/csgo-loader/ThemidaSettings._ini @@ -20,7 +20,7 @@ cbBugCheck.Checked="False" cbChangeSectionName.Checked="True" cbCompressApp.Checked="True" cbCompressEngine.Checked="True" -cbCompressResources.Checked="False" +cbCompressResources.Checked="True" cbControlMsgExports.Checked="False" cbCustomEnv.Checked="False" cbCustomFileStore.Checked="False" @@ -111,7 +111,7 @@ cbRefixInitialThunk.Checked="False" cbRefixRuntimeTLS.Checked="False" cbRegistryMonitorBlocker.Checked="False" cbReHookingEnabled.Checked="False" -cbResourceEncrypt.Checked="False" +cbResourceEncrypt.Checked="True" cbRestoreSectionAttributtes.Checked="False" cbRsrcExtraSpace.Checked="False" cbRunWithParams.Checked="False" @@ -261,7 +261,7 @@ InternalMessages.Items=hex:04,44,61,74,61,0A,47,0A,00,00,0C,00,00,00,30,00,\ 79,70,65,72,76,69,73,6F,72,20,2F,20,76,69,72,74,75,61,6C,20,6D,61,63,68,69,\ 6E,65,73,20,79,6F,75,20,6D,69,67,68,74,20,62,65,20,72,75,6E,6E,69,6E,67,2E,00 RzAntidebug.ItemIndex=1 -RzApiWrapping.ItemIndex=1 +RzApiWrapping.ItemIndex=2 SplashFile.AltBtnVisible="False" SplashFile.ButtonVisible="True" SplashMouse.Checked="False" @@ -272,15 +272,18 @@ SplashTime.Checked="True" autoblocks=False blocknumber=0 blockscrc32= -crc32="$29A5CE28" +crc32="$4525A0DA" CustMsgDLLFunction0= CustomVMCpus[0]="1" CustomVMCpus[1]="1" +CustomVMCpus[2]="1" CustomVMId[0]="0xD4A7990A" CustomVMId[1]="0xD4A79901" +CustomVMId[2]="0x84581901" CustomVMIntegrityCheck[0]="True" CustomVMIntegrityCheck[1]="True" -CustomVM_Number=2 +CustomVMIntegrityCheck[2]="True" +CustomVM_Number=3 messages=hex:01,02,00,06,17,4D,73,67,49,44,30,20,3A,20,47,6C,6F,62,61,6C,20,\ 43,61,70,74,69,6F,6E,02,02,02,02,02,00,02,01,06,01,20,02,FF,02,FF,02,00,02,\ 00,06,17,4D,73,67,49,44,31,20,3A,20,44,65,62,75,67,67,65,72,20,66,6F,75,6E,\ diff --git a/csgo-loader/ThemidaSettings.tmd b/csgo-loader/ThemidaSettings.tmd index cedd442..d8dd596 100644 Binary files a/csgo-loader/ThemidaSettings.tmd and b/csgo-loader/ThemidaSettings.tmd differ diff --git a/csgo-loader/csgo-client/Client.cpp b/csgo-loader/csgo-client/Client.cpp index 8c90f66..c41856c 100644 --- a/csgo-loader/csgo-client/Client.cpp +++ b/csgo-loader/csgo-client/Client.cpp @@ -3,14 +3,10 @@ /* TODO: - Finish off security on client: - - Hook OpenProcess, ExitProcess, WSARecv, WSASend and check if function is OOB. [DONE] - - Use VM check that Nave gave me. - Run a thread to check for blacklisted drivers periodically (also blacklist VBox) - Run a thread to check if there is more than X threads running in the loader. - Add dump protection (closes csgo.exe if a handle is detected, probably explorer shellcode) - Add HWID generation - - Hook DbgBreakPoint and DbgUiRemoteBreakin (instead of bytepatching, some debuggers will check that) [DONE] - - Don't forget about the security callback; leave implementation up to Nave. [DONE] - Apply Themida macros inside important functions: - Apply mutation on Security hooks and main function. @@ -25,7 +21,9 @@ - This will probably be the easiest thing to do. - Finish off injection wrapper: - - Allocate a 4KB page for trampoline imports (4096/6) { E8 ? ? ? ? C3 } + - Allocate a 4KB page for trampoline imports (4096/6) { E9 ? ? ? ? C3 } + - Actually, allocate every memory page as a bunch of consecutive 4kb sections + - Trampoline for imports - Everything is already laid out, tbh. - Have the loader inject a .DLL :^) @@ -35,28 +33,31 @@ - Adapt the server to work with your backend. */ + +#pragma optimize("", off) + int __stdcall WinMain(HINSTANCE inst, HINSTANCE prev, char* str, int cmdshow) { WRAP_IF_DEBUG(Utils::OpenConsole()); - // Autistic workaround for Hooked_OpenProcess crashing - // when Device->CreateDevice is invoked... - std::atomic UserInterfaceReady = false; + /////////////////////////////////////////////////////////////// + + WRAP_IF_RELEASE(MUTATE_START); + WRAP_IF_RELEASE(STR_ENCRYPT_START); + + /////////////////////////////////////////////////////////////// // Create a thread to handle UI. - std::thread WindowThread([&UserInterfaceReady] + std::thread WindowThread([] { // Create a window, initialise DirectX context. if(!UserInterface->Start()) ERROR_ASSERT("[000F:00001C00] Failed to initialize. Please contact an administrator."); - - // Signal initialization. - UserInterfaceReady = true; - + UserInterface->RunUiFrame(); }); WindowThread.detach(); - while(!UserInterfaceReady) { Sleep(1); } + while(!UserInterface->m_Data.m_Ready) { Sleep(1); } // Initialize the runtime protection system. WRAP_IF_RELEASE( @@ -83,4 +84,13 @@ int __stdcall WinMain(HINSTANCE inst, HINSTANCE prev, char* str, int cmdshow) // TODO: Add game selection. while(1) { if(GetAsyncKeyState(VK_END) & 0x8000) break; Sleep(1); } -} \ No newline at end of file + + /////////////////////////////////////////////////////////////// + + WRAP_IF_RELEASE(STR_ENCRYPT_END); + WRAP_IF_RELEASE(MUTATE_END); + + /////////////////////////////////////////////////////////////// +} + +#pragma optimize("", on) \ 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 f9825c0..ab2ea87 100644 --- a/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp +++ b/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp @@ -135,8 +135,12 @@ namespace Security #define CheckStatus() if(Status != MH_OK) { return false; } #define SafeCallTo(Function) Status = Function; CheckStatus(); +#pragma optimize("", off) + bool RuntimeSecurity::ApplyApiHooks() { + WRAP_IF_RELEASE(MUTATE_START); + // Make sure that MinHook is initialized properly. CreateMinHook(); CheckStatus(); @@ -155,8 +159,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); @@ -181,7 +189,7 @@ namespace Security uintptr_t Exports[] = { Export_DbgUiRemoteBreakin, Export_DbgBreakPoint, - //Export_NtContinue // This causes a lot of crashes ATM while debugging, leave this out till release. + Export_NtContinue // This causes a lot of crashes ATM while debugging, leave this out till release. }; for(auto &It : Exports) @@ -224,20 +232,24 @@ namespace Security { WRAP_IF_RELEASE(VM_EAGLE_BLACK_START); - // Yeah, um, your code did absolutely fuck all in my analysis VM. - int32_t VirtualMachineChecksum = 0x4000; + 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( + CHECK_VIRTUAL_PC(VirtualMachineChecksum, 0x2000); - WRAP_IF_RELEASE(STR_ENCRYPT_START); + WRAP_IF_RELEASE(STR_ENCRYPT_START); if(VirtualMachineChecksum != 0x2000) SecurityCallback(__FUNCSIG__); - WRAP_IF_RELEASE(STR_ENCRYPT_END); - ); + WRAP_IF_RELEASE(STR_ENCRYPT_END); + ); + + // Don't put too much stress on the CPU. + Sleep(VirtualMachineChecksum); + } - // Don't put too much stress on the CPU. - Sleep(VirtualMachineChecksum); WRAP_IF_RELEASE(VM_EAGLE_BLACK_END); } @@ -245,21 +257,60 @@ namespace Security void RuntimeSecurity::CheckForDebugger() { WRAP_IF_RELEASE(VM_EAGLE_BLACK_START); + WRAP_IF_RELEASE(STR_ENCRYPT_START); - // Read the PEB from the TIB. - // Offset for x86 is 0x30 ; mov ..., dword ptr fs:[0x30] - // Offset for x64 is 0x60 ; mov ..., qword ptr gs:[0x60] - PEB *ProcessEnvBlock = (PEB *)__readgsqword(0x60); - - // if(ProcessEnvBlock->BeingDebugged) - // SecurityCallback(); - - // TODO: Check for x64dbg window? + for(;;) + { + // Read the PEB from the TIB. + // Offset for x86 is 0x30 ; mov ..., dword ptr fs:[0x30] + // Offset for x64 is 0x60 ; mov ..., qword ptr gs:[0x60] + PEB *ProcessEnvBlock = (PEB *)__readgsqword(0x60); + + //if(ProcessEnvBlock->BeingDebugged) + // SecurityCallback(__FUNCSIG__); + + // TODO: Check for x64dbg window? + /* + ------------------------------ + HWND: 000305A4 + HWND->m_Class = "ID" + HWND->m_Text = "Immunity + ------------------------------ + HWND: 00060574 + HWND->m_Class = || NON CONSTANT || + HWND->m_Text = "x64dbg" + ------------------------------ + HWND: 002C0680 + HWND->m_Class = || NON CONSTANT || + HWND->m_Text = "Progress Telerik Fiddler Web Debugger" + ------------------------------ + HWND: 000406E4 + HWND->m_Class = "OLLYDBG" + HWND->m_Text = "OllyDbg" + ------------------------------ + */ + using WindowParams = std::pair; + static std::vector BlackListedWindows = { + {"ID", "Immunity"}, // Immunity Debugger + {"Qt5QWindowIcon", "x64dbg"}, // x64dbg + {"Qt5QWindowIcon", "x32dbg"}, // x32dbg + {"OLLYDBG", "OllyDbg"}, // OllyDbg + {nullptr, "Progress Telerik Fiddler Web Debugger"}, // Telerik Fiddler + }; + + for(auto &It : BlackListedWindows) + { + // size_t Index = std::distance(...); + if(FindWindowA(It.first, It.second)) + SecurityCallback(__FUNCSIG__); + } - // Don't put too much stress on the CPU. - Sleep(150); + // Don't put too much stress on the CPU. + Sleep(150); + } + WRAP_IF_RELEASE(STR_ENCRYPT_END); WRAP_IF_RELEASE(VM_EAGLE_BLACK_END); } @@ -267,10 +318,16 @@ namespace Security { WRAP_IF_RELEASE(VM_EAGLE_BLACK_START); - // TODO: + // TODO: Check if test-signing mode is on + // TODO: Check if safe-mode is on - // Don't put too much stress on the CPU. - Sleep(150); + // TODO: Check for disallowed drivers + for(;;) + { + + // Don't put too much stress on the CPU. + Sleep(150); + } WRAP_IF_RELEASE(VM_EAGLE_BLACK_END); } @@ -279,28 +336,32 @@ namespace Security { WRAP_IF_RELEASE(VM_EAGLE_BLACK_START); - int32_t CodeIntegrityChecksum = 0x2000; + for(;;) + { + int32_t CodeIntegrityChecksum = 0x2000; - WRAP_IF_RELEASE( - CHECK_CODE_INTEGRITY(CodeIntegrityChecksum, 0x4000); + WRAP_IF_RELEASE( + CHECK_CODE_INTEGRITY(CodeIntegrityChecksum, 0x4000); - WRAP_IF_RELEASE(STR_ENCRYPT_START); + WRAP_IF_RELEASE(STR_ENCRYPT_START); if(CodeIntegrityChecksum != 0x4000) SecurityCallback(__FUNCSIG__); - WRAP_IF_RELEASE(STR_ENCRYPT_END); - ); + WRAP_IF_RELEASE(STR_ENCRYPT_END); + ); - WRAP_IF_RELEASE( - CHECK_PROTECTION(CodeIntegrityChecksum, 0x4000); + WRAP_IF_RELEASE( + CHECK_PROTECTION(CodeIntegrityChecksum, 0x4000); - WRAP_IF_RELEASE(STR_ENCRYPT_START); - if(CodeIntegrityChecksum != 0x4000) - SecurityCallback(__FUNCSIG__); - WRAP_IF_RELEASE(STR_ENCRYPT_END); - ); + 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); + } - // Don't put too much stress on the CPU. - Sleep(CodeIntegrityChecksum); WRAP_IF_RELEASE(VM_EAGLE_BLACK_END); } @@ -331,21 +392,24 @@ namespace Security return HardwareIdentifier{}; } +#pragma optimize("", off) + MEMORY_BASIC_INFORMATION RuntimeSecurity::QueryMemory(void *Address) { static auto ZwQueryVirtualMemory = Syscalls->Find(FNV("ZwQueryVirtualMemory")); - MEMORY_BASIC_INFORMATION Result; - - NTSTATUS Status = ZwQueryVirtualMemory(GetCurrentProcess(), Address, 0, &Result, sizeof Result, nullptr); + MEMORY_BASIC_INFORMATION Result{}; + NTSTATUS Status = ZwQueryVirtualMemory((HANDLE)-1, Address, 0, &Result, sizeof Result, nullptr); if(NT_ERROR(Status)) { - char ReasonParameter[64]; 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)); + WRAP_IF_RELEASE( + sprintf_s(ReasonParameter, "[00DF:%08x] There was an error with accessing a process.", Status); + ERROR_ASSERT(ReasonParameter); + ); // yeet SecurityCallback(ReasonParameter); @@ -358,21 +422,32 @@ namespace Security { WRAP_IF_RELEASE(VM_FISH_WHITE_START); - // TODO: Implement something that bans the user or notifies - // you if someone tampers with the loader. 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. char Buffer[2048]; sprintf_s(Buffer, "Security callback was called. Reason parameter: \"%s\"\n", Reason); - + MessageBoxA(0, Buffer, "Information", MB_ICONINFORMATION | MB_OK); + + + // The process will straight up die on Release mode. + // Compile with FuckMSVC to debug this. + WRAP_IF_RELEASE( + ExitProcess(rand() % RAND_MAX); + ); + TriggeredCallback = true; WRAP_IF_RELEASE(STR_ENCRYPT_END); } WRAP_IF_RELEASE(VM_FISH_WHITE_END); } + +#pragma optimize("", on) } \ No newline at end of file diff --git a/csgo-loader/csgo-client/UserExperience/UserInterface.cpp b/csgo-loader/csgo-client/UserExperience/UserInterface.cpp index 75b79b2..24f92c4 100644 --- a/csgo-loader/csgo-client/UserExperience/UserInterface.cpp +++ b/csgo-loader/csgo-client/UserExperience/UserInterface.cpp @@ -65,6 +65,8 @@ namespace UserExperience g_window.add_on_frame(&OnDirectXFrame); } + m_Data.m_Ready = result; + return result; } diff --git a/csgo-loader/csgo-client/UserExperience/UserInterface.hpp b/csgo-loader/csgo-client/UserExperience/UserInterface.hpp index d4a3dc4..aaa4b10 100644 --- a/csgo-loader/csgo-client/UserExperience/UserInterface.hpp +++ b/csgo-loader/csgo-client/UserExperience/UserInterface.hpp @@ -35,6 +35,9 @@ namespace UserExperience // Structure that holds global data that will be used by the UI. struct UserExperienceData { + // Is the user interface initialised? + bool m_Ready = false; + // Holds the current execution state of the loader. ExecutionState m_ExecutionState = EXECUTION_WAITING; diff --git a/csgo-loader/csgo-client/csgo-client.vcxproj b/csgo-loader/csgo-client/csgo-client.vcxproj index f6f1787..40af0a8 100644 --- a/csgo-loader/csgo-client/csgo-client.vcxproj +++ b/csgo-loader/csgo-client/csgo-client.vcxproj @@ -172,6 +172,8 @@ $(ExecutablePath) $(SolutionDir)shared\include;$(DXSDK_DIR)\Include;$(ProjectDir);$(VC_IncludePath);$(WindowsSDK_IncludePath); $(SolutionDir)shared\lib;$(DXSDK_DIR)\Lib\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + + $(SolutionDir)bin\$(Configuration)\ @@ -242,7 +244,7 @@ true true _WINSOCK_DEPRECATED_NO_WARNINGS;WIN32_LEAN_AND_MEAN;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - true + false stdcpp17 4100;4189;4244;4267;4522;4714;4838;4307;4706;4702 @@ -253,6 +255,12 @@ Windows kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + B:\Themida 2.4.6.0\Themida64.exe $(SolutionDir)ThemidaSettings.tmd + + + Protecting file with Themida... + @@ -263,7 +271,7 @@ true true DEBUG;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32_LEAN_AND_MEAN;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - true + false stdcpp17 4100;4189;4244;4267;4522;4714;4838;4307;4706;4702 diff --git a/csgo-loader/to-do list.txt b/csgo-loader/to-do list.txt index d6470b5..e93062e 100644 --- a/csgo-loader/to-do list.txt +++ b/csgo-loader/to-do list.txt @@ -104,11 +104,9 @@ If the problem persists, please download the latest version from here. [0005:xxxxxxxx] The server does not recognize your subscription as valid. -This could be due to numerous factors including: - - You do not have a subscription. - - You have attempted to tamper with the loader. - - Your machine is infected with malware that triggered a loader integrity check. - - You have another account on the same IP address/hardware ID. +This could be due to numerous factors including but not limited to: + - not having a subscription. + - tampering with the loader. To trouble-shoot this issue, try changing your password on the forums to force a database update. @@ -119,6 +117,6 @@ The server does not recognize your credentials as valid. To trouble-shoot this issue, please take note of the following: - CAPS LOCK is not parsed as valid input by the loader. - - Pressing TAB will insert a character into the text input field. + - Pressing TAB will insert an invalid character into the text input field. If the issue persists, contact an administrator. \ No newline at end of file -- cgit v1.2.3