#pragma once #include "Windows.h" #include "string" #include "vector" #include "cVector.h" #include "../qAngles.h" #include "Defines.h" #ifndef DEG2RAD #define DEG2RAD(x) ((x) * (M_PI / 180.0f)) #endif class CUtlBuffer; namespace M { inline void* GetModuleBaseHandle(const wchar_t* wszModuleName) { if (wszModuleName == nullptr) return GetModuleHandle(nullptr); HMODULE hModule = GetModuleHandleW(wszModuleName); return hModule; } template inline constexpr int StringCompare(const C* tszLeft, const C* tszRight) { if constexpr (std::is_same_v) { return std::strcmp(tszLeft, tszRight); } else if constexpr (std::is_same_v) { return std::wcscmp(tszLeft, tszRight); } } inline void* GetExportAddress(const void* hModuleBase, const char* szProcedureName) { const auto pBaseAddress = static_cast(hModuleBase); const auto pIDH = static_cast(hModuleBase); if (pIDH->e_magic != IMAGE_DOS_SIGNATURE) return nullptr; const auto pINH = reinterpret_cast(pBaseAddress + pIDH->e_lfanew); if (pINH->Signature != IMAGE_NT_SIGNATURE) return nullptr; const IMAGE_OPTIONAL_HEADER64* pIOH = &pINH->OptionalHeader; const std::uintptr_t nExportDirectorySize = pIOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; const std::uintptr_t uExportDirectoryAddress = pIOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; if (nExportDirectorySize == 0U || uExportDirectoryAddress == 0U) { return nullptr; } const auto pIED = reinterpret_cast(pBaseAddress + uExportDirectoryAddress); const auto pNamesRVA = reinterpret_cast(pBaseAddress + pIED->AddressOfNames); const auto pNameOrdinalsRVA = reinterpret_cast(pBaseAddress + pIED->AddressOfNameOrdinals); const auto pFunctionsRVA = reinterpret_cast(pBaseAddress + pIED->AddressOfFunctions); // Perform binary search to find the export by name std::size_t nRight = pIED->NumberOfNames, nLeft = 0U; while (nRight != nLeft) { // Avoid INT_MAX/2 overflow const std::size_t uMiddle = nLeft + ((nRight - nLeft) >> 1U); const int iResult = StringCompare(szProcedureName, reinterpret_cast(pBaseAddress + pNamesRVA[uMiddle])); if (iResult == 0) { const std::uint32_t uFunctionRVA = pFunctionsRVA[pNameOrdinalsRVA[uMiddle]]; // Check if it's a forwarded export if (uFunctionRVA >= uExportDirectoryAddress && uFunctionRVA - uExportDirectoryAddress < nExportDirectorySize) { // Forwarded exports are not supported break; } return const_cast(pBaseAddress) + uFunctionRVA; } if (iResult > 0) nLeft = uMiddle + 1; else nRight = uMiddle; } return nullptr; } inline std::uint8_t* ResolveRelativeAddress(std::uint8_t* nAddressBytes, std::uint32_t nRVAOffset, std::uint32_t nRIPOffset) { std::uint32_t nRVA = *reinterpret_cast(nAddressBytes + nRVAOffset); std::uint64_t nRIP = reinterpret_cast(nAddressBytes) + nRIPOffset; return reinterpret_cast(nRVA + nRIP); } template static inline T CallVFunc(CBaseClass* thisptr, Args_t... argList) { using VirtualFn_t = T(__thiscall*)(const void*, decltype(argList)...); return (*reinterpret_cast(reinterpret_cast(thisptr)))[nIndex](thisptr, argList...); } inline std::vector PatternToBytes(const char* pattern) { std::vector bytes; const char* current = pattern; while (*current) { if (*current == '?') { bytes.push_back(-1); // Wildcard current++; if (*current == '?') current++; // Skip second '?' } else { bytes.push_back(static_cast(std::strtoul(current, nullptr, 16))); current += 2; } if (*current == ' ') current++; // Skip spaces } return bytes; } inline uintptr_t FindPattern(const wchar_t* moduleName, const char* pattern) { HMODULE hModule = GetModuleHandleW(moduleName); if (!hModule) return 0; std::uint8_t* moduleBase = reinterpret_cast(hModule); PIMAGE_NT_HEADERS ntHeaders = reinterpret_cast(moduleBase + reinterpret_cast(moduleBase)->e_lfanew); std::size_t moduleSize = ntHeaders->OptionalHeader.SizeOfImage; std::vector patternBytes = PatternToBytes(pattern); std::size_t patternLength = patternBytes.size(); for (std::size_t i = 0; i <= moduleSize - patternLength; i++) { bool found = true; for (std::size_t j = 0; j < patternLength; j++) { if (patternBytes[j] != -1 && patternBytes[j] != moduleBase[i + j]) { found = false; break; } } if (found) return reinterpret_cast(moduleBase + i); } return 0; } template T GetAbsoluteAddress(T pRelativeAddress, int nPreOffset = 0x0, int nPostOffset = 0x0) { std::int32_t relativeOffset = *reinterpret_cast(reinterpret_cast(pRelativeAddress) + nPreOffset); return pRelativeAddress + relativeOffset + sizeof(std::int32_t) + nPreOffset + nPostOffset; } inline void** CopyVirtualTable(void** Original) { constexpr int Entries = 8192 / sizeof(void*); void** NewVTable = new void* [Entries]; for (int i = 0; i < Entries; ++i) NewVTable[i] = Original[i]; return NewVTable; } inline Vector_t AngleToDirection(const QAngle_t& Angles) { Vector_t Direction; float Pitch = DEG2RAD(Angles.x); float Yaw = DEG2RAD(Angles.y); Direction.x = cos(Pitch) * cos(Yaw); Direction.y = cos(Pitch) * sin(Yaw); Direction.z = -sin(Pitch); return Direction; } inline void(__fastcall* fnUtlBufferInit)(CUtlBuffer*, int, int, int); inline void(__fastcall* fnUtlBufferPutString)(CUtlBuffer*, const char*); inline void(__fastcall* fnUtlBufferEnsureCapacity)(CUtlBuffer*, int); }