summaryrefslogtreecommitdiff
path: root/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'csgo-loader/csgo-client/Security/RuntimeSecurity.cpp')
-rw-r--r--csgo-loader/csgo-client/Security/RuntimeSecurity.cpp197
1 files changed, 148 insertions, 49 deletions
diff --git a/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp b/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp
index 739ce5d..4551b5d 100644
--- a/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp
+++ b/csgo-loader/csgo-client/Security/RuntimeSecurity.cpp
@@ -1,5 +1,6 @@
#include <Security/RuntimeSecurity.hpp>
-#include <Security/BretHart.hpp>
+#include <Security/SyscallManager.hpp>
+#include <Security/FnvHash.hpp>
#include <UserExperience/UserInterface.hpp>
#include <Networking/TCPClient.hpp>
@@ -13,9 +14,13 @@ namespace Security
// Hooked functions.
///////////////////////////////////////////////////////////
+#pragma optimize("", off)
+
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);
@@ -27,7 +32,9 @@ namespace Security
if(ReturnModule != LoaderModule)
{
- Protection->SecurityCallback();
+ WRAP_IF_RELEASE(STR_ENCRYPT_START);
+ Protection->SecurityCallback(__FUNCSIG__);
+ WRAP_IF_RELEASE(STR_ENCRYPT_END);
[&](decltype(&OpenProcess) A)
{
@@ -39,59 +46,62 @@ 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)
{
- // Determine where the return address of the function actually points.
- void *Address = _ReturnAddress();
- MEMORY_BASIC_INFORMATION Query = Protection->QueryMemory(Address);
-
- // If the return address points outside of the loader module,
- // fail the function.
- HMODULE ReturnModule = (HMODULE)Query.AllocationBase;
- HMODULE LoaderModule = GetModuleHandleA(NULL);
+ WRAP_IF_RELEASE(VM_EAGLE_WHITE_START);
- if(ReturnModule != LoaderModule)
- {
- Protection->SecurityCallback();
+ WRAP_IF_DEBUG(oExitProcess(ExitCode));
+ WRAP_IF_RELEASE(
[&](decltype(&ExitProcess) A)
{
// Again, let's meme anyone who tries to reverse this.
uintptr_t NullPointer = *(uintptr_t *)0x00000000;
A(NullPointer);
}(oExitProcess);
- }
+ );
- // Call original function
- oExitProcess(ExitCode);
+ 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();
+ void *Address = _ReturnAddress();
MEMORY_BASIC_INFORMATION Query = Protection->QueryMemory(Address);
// If the return address points outside of the loader module,
// fail the function.
HMODULE ReturnModule = (HMODULE)Query.AllocationBase;
HMODULE LoaderModule = GetModuleHandleA(NULL);
-
+
+ // Let's meme anyone who tries to reverse this.
if(ReturnModule != LoaderModule)
- // Let's meme anyone who tries to reverse this.
- return []() { Protection->SecurityCallback(); return -1; }();
+ {
+ WRAP_IF_RELEASE(STR_ENCRYPT_START);
+ return []() { Protection->SecurityCallback(__FUNCSIG__); return -1; }();
+ WRAP_IF_RELEASE(STR_ENCRYPT_END);
+ }
// 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();
MEMORY_BASIC_INFORMATION Query = Protection->QueryMemory(Address);
@@ -101,14 +111,22 @@ namespace Security
HMODULE ReturnModule = (HMODULE)Query.AllocationBase;
HMODULE LoaderModule = GetModuleHandleA(NULL);
+ // Let's meme anyone who tries to reverse this.
if(ReturnModule != LoaderModule)
- // Let's meme anyone who tries to reverse this.
- return []() { Protection->SecurityCallback(); return -1; }();
+ {
+ WRAP_IF_RELEASE(STR_ENCRYPT_START);
+ return []() { Protection->SecurityCallback(__FUNCSIG__); return -1; }();
+ WRAP_IF_RELEASE(STR_ENCRYPT_END);
+ }
// Call original function
return oWSASend(Socket, Buffer, Length, Flags);
+
+ WRAP_IF_RELEASE(VM_EAGLE_WHITE_END);
}
+#pragma optimize("", on)
+
// The following functions are only called internally.
///////////////////////////////////////////////////////////
@@ -126,7 +144,7 @@ namespace Security
// Apply any hooks.
SafeCallTo(MH_CreateHook(&OpenProcess, Hooked_OpenProcess, (void **)&oOpenProcess));
SafeCallTo(MH_EnableHook(&OpenProcess));
-
+
SafeCallTo(MH_CreateHook(&ExitProcess, Hooked_ExitProcess, (void **)&oExitProcess));
SafeCallTo(MH_EnableHook(&ExitProcess));
@@ -158,15 +176,7 @@ namespace Security
// This should prevent any such plugins from effectively attaching the debugger.
// NOTE: This does not work on x64dbg for whatever reason..
uintptr_t Export_NtContinue = (uintptr_t)GetProcAddress(Module, "NtContinue");
-
- // Our small shellcode that calls oExitProcess.
- uint8_t Shellcode[] = {
- 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, dword ptr[0]
- 0xFF, 0xE0 // jmp eax
- };
-
- std::memcpy(&Shellcode[1], oExitProcess, sizeof uint32_t);
-
+
// Ensure that the program gets closed if a debugger is attached.
uintptr_t Exports[] = {
Export_DbgUiRemoteBreakin,
@@ -177,14 +187,14 @@ namespace Security
for(auto &It : Exports)
{
DWORD OldProtection;
- if(!VirtualProtect((void *)It, sizeof Shellcode, PAGE_EXECUTE_READWRITE, &OldProtection))
+ if(!VirtualProtect((void *)It, sizeof uintptr_t + 1, PAGE_EXECUTE_READWRITE, &OldProtection))
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;
- VirtualProtect((void *)It, sizeof Shellcode, OldProtection, &OldProtection);
+ VirtualProtect((void *)It, sizeof uintptr_t + 1, OldProtection, &OldProtection);
}
WRAP_IF_RELEASE(STR_ENCRYPT_END);
@@ -195,10 +205,10 @@ namespace Security
{
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::CheckForThreads, this); TamperThread.detach();
+ 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);
}
@@ -208,33 +218,95 @@ namespace Security
// code readability.
///////////////////////////////////////////////////////////
+#pragma optimize("", off)
+
void RuntimeSecurity::CheckForVirtualMachine()
{
+ WRAP_IF_RELEASE(VM_EAGLE_BLACK_START);
+
+ // 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);
+ WRAP_IF_RELEASE(VM_EAGLE_BLACK_END);
}
void RuntimeSecurity::CheckForDebugger()
{
+ WRAP_IF_RELEASE(VM_EAGLE_BLACK_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?
+
+
+ // Don't put too much stress on the CPU.
+ Sleep(150);
- //PEB *ProcessEnvBlock = (PEB *)__readgsqword(0x60);
- //
- //if(ProcessEnvBlock->BeingDebugged)
- // SecurityCallback();
+ WRAP_IF_RELEASE(VM_EAGLE_BLACK_END);
}
void RuntimeSecurity::CheckForDrivers()
{
+ WRAP_IF_RELEASE(VM_EAGLE_BLACK_START);
+
+ // TODO:
+
+ // Don't put too much stress on the CPU.
+ Sleep(150);
+ WRAP_IF_RELEASE(VM_EAGLE_BLACK_END);
}
- void RuntimeSecurity::CheckForThreads()
+ void RuntimeSecurity::CheckForTampering()
{
+ WRAP_IF_RELEASE(VM_EAGLE_BLACK_START);
+
+ 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);
+
+ WRAP_IF_RELEASE(VM_EAGLE_BLACK_END);
}
+#pragma optimize("", on)
+
// The following functions are exposed publicly.
///////////////////////////////////////////////////////////
@@ -261,20 +333,47 @@ namespace Security
MEMORY_BASIC_INFORMATION RuntimeSecurity::QueryMemory(void *Address)
{
+ static auto ZwQueryVirtualMemory = Syscalls->Find<long(__stdcall *)(HANDLE, void *, int, void *, uint32_t, uint32_t *)>(FNV("ZwQueryVirtualMemory"));
+
MEMORY_BASIC_INFORMATION Result;
- VirtualQuery(Address, &Result, sizeof MEMORY_BASIC_INFORMATION);
+ WRAP_IF_RELEASE(MUTATE_START);
+ {
+ NTSTATUS Status = ZwQueryVirtualMemory(GetCurrentProcess(), Address, 0, &Result, sizeof Result, nullptr);
+
+ if(NT_ERROR(Status))
+ {
+ WRAP_IF_RELEASE(STR_ENCRYPT_START);
+
+ char ReasonParameter[64];
+ sprintf_s(ReasonParameter, "ZQVM failed! NTSTATUS: %08x", Status);
+
+ // yeet
+ SecurityCallback(ReasonParameter);
+
+ WRAP_IF_RELEASE(STR_ENCRYPT_END);
+ }
+ }
+ WRAP_IF_RELEASE(MUTATE_END);
return Result;
}
- __forceinline void RuntimeSecurity::SecurityCallback()
+ void RuntimeSecurity::SecurityCallback(const char *Reason)
{
// TODO: Implement something that bans the user or notifies
// you if someone tampers with the loader.
- // For convenience sake, I'll just put a small .WAV file of
- // Bret Hart screaming in here for now :^)
- PlaySoundA((char *)Resource::BretWAV, NULL, SND_MEMORY);
- oExitProcess(0);
+ static bool TriggeredCallback = false;
+
+ if(!TriggeredCallback)
+ {
+ WRAP_IF_RELEASE(STR_ENCRYPT_START);
+ char Buffer[2048];
+ sprintf_s(Buffer, "Security callback was called. Reason parameter: \"%s\"\n", Reason);
+
+ MessageBoxA(0, Buffer, "Information", MB_ICONINFORMATION | MB_OK);
+ TriggeredCallback = true;
+ WRAP_IF_RELEASE(STR_ENCRYPT_END);
+ }
}
} \ No newline at end of file