From b0a41328ed842ea2644c07dc503f04841f8c7e9a Mon Sep 17 00:00:00 2001 From: RektInator Date: Tue, 17 Jul 2018 14:30:29 +0200 Subject: [PATCH] [General] Added VMProtect libraries (I own a license, feel free to DM), Fixed empty name vuln, Fixed javelin glitch. --- lib/bin/VMProtectSDK32.dll | Bin 0 -> 100864 bytes lib/bin/VMProtectSDK32.lib | Bin 0 -> 7714 bytes lib/include/VMProtect/VMProtectSDK.h | 102 ++++++++++++++++++++++++++ premake5.lua | 4 + src/Components/Modules/AntiCheat.cpp | 52 +++++++++++++ src/Components/Modules/QuickPatch.cpp | 64 ++++++++++++++++ src/Components/Modules/QuickPatch.hpp | 5 ++ src/Components/Modules/Script.cpp | 26 +++++++ src/Game/Functions.cpp | 4 +- src/Game/Functions.hpp | 6 ++ src/STDInclude.hpp | 12 +++ 11 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 lib/bin/VMProtectSDK32.dll create mode 100644 lib/bin/VMProtectSDK32.lib create mode 100644 lib/include/VMProtect/VMProtectSDK.h diff --git a/lib/bin/VMProtectSDK32.dll b/lib/bin/VMProtectSDK32.dll new file mode 100644 index 0000000000000000000000000000000000000000..5b32d087eac70205af6e7c6959fec68b8287ea5b GIT binary patch literal 100864 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 literal 0 HcmV?d00001 diff --git a/lib/bin/VMProtectSDK32.lib b/lib/bin/VMProtectSDK32.lib new file mode 100644 index 0000000000000000000000000000000000000000..1111795a21ea53f83ca3166db4778f67afaaf80e GIT binary patch literal 7714 zcmcH;%T60t^cV;v4sncmnO8(rs2X=T7^u`mx|AW|1Gjy=Gr#zy0z5~xxl z)>XtJQlu!WtgCzjAJIh@{eZ5!j+C4`kITJt@60fj8R;;dbII1Q0z2==%UL{=kI(R{#VCUz#w`1z^BA z-VuiInZUqD6XFp70%Pw?m>2~hF#gtr;TV7c7kEdAqYMHQ?@btsBOk)(YZKxqmq0(t zBrt?L1V+wG80|*7?sB=Xwz;vjUCuu#EpHVzw>P%RyK9?TQ&*~bDZe_Kf^vC%r&tu} z-~~@;l5MZ-tgn{yi`$EEC8*G{Br3IB0tKo^$7R=5Ds@RYP#d{9fu7=d%3W2{Pbziw ztfH$;S3Z%7m$G)Ed-AjEJm*eb*D7x2(nX$!x2D*v{@gV2r8tQz-iBwd| zlZNa~Sy)O{XyujXCkF?Lwy7yCrJ+jnBIg6-~k@p`hG9^V}tLc|~$qZe(t9@)f<3n-}8MA;zX+r7WLl8oJNQ(?VV@z(GKH z7puDZ8(Lpft4gD#{FYh04nxDhOJkFbIqM*%+c0X!H7c-0T^auA?v0N@;FFK?phm(RVTx$o2+!D~pFIKkOo-`J%A(v07ek#e{QG~ujD`T~ znsJ4uYou+SDw&S}EBNCN`@y>BAi6ZI*080TO4&e=S5O-gA(+wCFMx8tWuh zRMcnF5qu6NFFWu)f_0T#F>#|0p+DM#OGGTWu;#;?XR$T4sx@29eSPxlt#2lah4ocq z)$yknp9v!ofc=2+3mXQk=L9DzLyM}-qhmDv&9hMG(@fIa+ilk;#;FG{7ej2CqnUUZ2znzn<~ zi)y&eUW^yb+IZp}f7%b$op=$EdsE(Vop+7xA)dd>$A-W$m|75H@E_FRb$T8#n6?he z@N5!;?8U_3oQ)@b{I~sJ-EZQQuXD0fsNXkd2F!7pdCNH`$yYEEzr_&Aa|vUwy-Y7F z>9r;4AZT>Z;Be^w3iXF@O1NsO>=sC(G_Y4?((+w@hgv&CtxSW}7VWl6JNAs9A2AOK zd$!v*iRz%IolVO3O_EBNi)OZslb8_r?7eKbCE6f#p6#$9JmLAR)+CnlzVmnSFlaYJHG+J=mVS(e@nnZoz{d;J?y$S(t;`pgrs2>EGj7-*amB7_ua$1bzqe zE}8HLv?bzV3ynW+glmU2UODl;(;9a4vj)Vr*x=%oq!o&K*K5+efpr;CS>T-e9i zAe(I^1_btt%&a^Yev1~w92T&Xb6a%VgMym__{q XPW>)Ze>?2Rc$~u^XNUMrL8kvRjTZbd literal 0 HcmV?d00001 diff --git a/lib/include/VMProtect/VMProtectSDK.h b/lib/include/VMProtect/VMProtectSDK.h new file mode 100644 index 00000000..3368ddac --- /dev/null +++ b/lib/include/VMProtect/VMProtectSDK.h @@ -0,0 +1,102 @@ +#pragma once + +#if defined(__APPLE__) || defined(__unix__) +#define VMP_IMPORT +#define VMP_API +#define VMP_WCHAR unsigned short +#else +#define VMP_IMPORT __declspec(dllimport) +#define VMP_API __stdcall +#define VMP_WCHAR wchar_t +#ifdef _WIN64 + #pragma comment(lib, "VMProtectSDK64.lib") +#else + #pragma comment(lib, "VMProtectSDK32.lib") +#endif // _WIN64 +#endif // __APPLE__ || __unix__ + +#ifdef __cplusplus +extern "C" { +#endif + +// protection +VMP_IMPORT void VMP_API VMProtectBegin(const char *); +VMP_IMPORT void VMP_API VMProtectBeginVirtualization(const char *); +VMP_IMPORT void VMP_API VMProtectBeginMutation(const char *); +VMP_IMPORT void VMP_API VMProtectBeginUltra(const char *); +VMP_IMPORT void VMP_API VMProtectBeginVirtualizationLockByKey(const char *); +VMP_IMPORT void VMP_API VMProtectBeginUltraLockByKey(const char *); +VMP_IMPORT void VMP_API VMProtectEnd(void); + +// utils +VMP_IMPORT bool VMP_API VMProtectIsProtected(); +VMP_IMPORT bool VMP_API VMProtectIsDebuggerPresent(bool); +VMP_IMPORT bool VMP_API VMProtectIsVirtualMachinePresent(void); +VMP_IMPORT bool VMP_API VMProtectIsValidImageCRC(void); +VMP_IMPORT const char * VMP_API VMProtectDecryptStringA(const char *value); +VMP_IMPORT const VMP_WCHAR * VMP_API VMProtectDecryptStringW(const VMP_WCHAR *value); +VMP_IMPORT bool VMP_API VMProtectFreeString(const void *value); + +// licensing +enum VMProtectSerialStateFlags +{ + SERIAL_STATE_SUCCESS = 0, + SERIAL_STATE_FLAG_CORRUPTED = 0x00000001, + SERIAL_STATE_FLAG_INVALID = 0x00000002, + SERIAL_STATE_FLAG_BLACKLISTED = 0x00000004, + SERIAL_STATE_FLAG_DATE_EXPIRED = 0x00000008, + SERIAL_STATE_FLAG_RUNNING_TIME_OVER = 0x00000010, + SERIAL_STATE_FLAG_BAD_HWID = 0x00000020, + SERIAL_STATE_FLAG_MAX_BUILD_EXPIRED = 0x00000040, +}; + +#pragma pack(push, 1) +typedef struct +{ + unsigned short wYear; + unsigned char bMonth; + unsigned char bDay; +} VMProtectDate; + +typedef struct +{ + int nState; // VMProtectSerialStateFlags + VMP_WCHAR wUserName[256]; // user name + VMP_WCHAR wEMail[256]; // email + VMProtectDate dtExpire; // date of serial number expiration + VMProtectDate dtMaxBuild; // max date of build, that will accept this key + int bRunningTime; // running time in minutes + unsigned char nUserDataLength; // length of user data in bUserData + unsigned char bUserData[255]; // up to 255 bytes of user data +} VMProtectSerialNumberData; +#pragma pack(pop) + +VMP_IMPORT int VMP_API VMProtectSetSerialNumber(const char *serial); +VMP_IMPORT int VMP_API VMProtectGetSerialNumberState(); +VMP_IMPORT bool VMP_API VMProtectGetSerialNumberData(VMProtectSerialNumberData *data, int size); +VMP_IMPORT int VMP_API VMProtectGetCurrentHWID(char *hwid, int size); + +// activation +enum VMProtectActivationFlags +{ + ACTIVATION_OK = 0, + ACTIVATION_SMALL_BUFFER, + ACTIVATION_NO_CONNECTION, + ACTIVATION_BAD_REPLY, + ACTIVATION_BANNED, + ACTIVATION_CORRUPTED, + ACTIVATION_BAD_CODE, + ACTIVATION_ALREADY_USED, + ACTIVATION_SERIAL_UNKNOWN, + ACTIVATION_EXPIRED, + ACTIVATION_NOT_AVAILABLE +}; + +VMP_IMPORT int VMP_API VMProtectActivateLicense(const char *code, char *serial, int size); +VMP_IMPORT int VMP_API VMProtectDeactivateLicense(const char *serial); +VMP_IMPORT int VMP_API VMProtectGetOfflineActivationString(const char *code, char *buf, int size); +VMP_IMPORT int VMP_API VMProtectGetOfflineDeactivationString(const char *serial, char *buf, int size); + +#ifdef __cplusplus +} +#endif diff --git a/premake5.lua b/premake5.lua index 2625578c..2781c9e0 100644 --- a/premake5.lua +++ b/premake5.lua @@ -284,6 +284,10 @@ workspace "iw4x" includedirs { "%{prj.location}/src", "./src", + "./lib/include", + } + syslibdirs { + "./lib/bin", } resincludedirs { "$(ProjectDir)src" -- fix for VS IDE diff --git a/src/Components/Modules/AntiCheat.cpp b/src/Components/Modules/AntiCheat.cpp index 7223896d..da9af5ee 100644 --- a/src/Components/Modules/AntiCheat.cpp +++ b/src/Components/Modules/AntiCheat.cpp @@ -36,6 +36,7 @@ namespace Components void AntiCheat::CrashClient() { + __VMProtectBeginUltra(""); #ifdef DEBUG_DETECTIONS Logger::Flush(); MessageBoxA(nullptr, "Check the log for more information!", "AntiCheat triggered", MB_ICONERROR); @@ -51,10 +52,12 @@ namespace Components }); } #endif + __VMProtectEnd; } void AntiCheat::AssertCalleeModule(void* callee) { + __VMProtectBeginUltra(""); HMODULE hModuleSelf = nullptr, hModuleTarget = nullptr, hModuleProcess = GetModuleHandleA(nullptr); GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast(callee), &hModuleTarget); GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast(AntiCheat::AssertCalleeModule), &hModuleSelf); @@ -70,10 +73,12 @@ namespace Components AntiCheat::CrashClient(); } + __VMProtectEnd; } void AntiCheat::InitLoadLibHook() { + __VMProtectBeginUltra(""); static uint8_t kernel32Str[] = { 0xB4, 0x9A, 0x8D, 0xB1, 0x9A, 0x93, 0xCC, 0xCD, 0xD1, 0x9B, 0x93, 0x93 }; // KerNel32.dll static uint8_t loadLibAStr[] = { 0xB3, 0x90, 0x9E, 0x9B, 0xB3, 0x96, 0x9D, 0x8D, 0x9E, 0x8D, 0x86, 0xBE }; // LoadLibraryA static uint8_t loadLibWStr[] = { 0xB3, 0x90, 0x9E, 0x9B, 0xB3, 0x96, 0x9D, 0x8D, 0x9E, 0x8D, 0x86, 0xA8 }; // LoadLibraryW @@ -133,10 +138,13 @@ namespace Components Utils::Hook::Signature signature(ntdll, Utils::GetModuleSize(ntdll)); signature.add(container); //signature.process(); + + __VMProtectEnd; } void AntiCheat::ReadIntegrityCheck() { + __VMProtectBeginUltra(""); #ifdef PROCTECT_PROCESS static Utils::Time::Interval check; @@ -158,10 +166,12 @@ namespace Components // Set the integrity flag AntiCheat::Flags |= AntiCheat::IntergrityFlag::READ_INTEGRITY_CHECK; #endif + __VMProtectEnd; } void AntiCheat::FlagIntegrityCheck() { + __VMProtectBeginUltra(""); static Utils::Time::Interval check; if (check.elapsed(30s)) @@ -179,10 +189,12 @@ namespace Components AntiCheat::CrashClient(); } } + __VMProtectEnd; } void AntiCheat::ScanIntegrityCheck() { + __VMProtectBeginUltra(""); // If there was no check within the last 40 seconds, crash! if (AntiCheat::LastCheck.elapsed(40s)) { @@ -195,10 +207,12 @@ namespace Components // Set the integrity flag AntiCheat::Flags |= AntiCheat::IntergrityFlag::SCAN_INTEGRITY_CHECK; + __VMProtectEnd; } void AntiCheat::PerformScan() { + __VMProtectBeginUltra(""); static std::optional hashVal; // Perform check only every 20 seconds @@ -229,10 +243,12 @@ namespace Components // Set the memory scan flag AntiCheat::Flags |= AntiCheat::IntergrityFlag::MEMORY_SCAN; + __VMProtectEnd; } void AntiCheat::QuickCodeScanner1() { + __VMProtectBeginUltra(""); static Utils::Time::Interval interval; static std::optional hashVal; @@ -251,10 +267,12 @@ namespace Components } hashVal.emplace(hash); + __VMProtectEnd; } void AntiCheat::QuickCodeScanner2() { + __VMProtectBeginUltra(""); static Utils::Time::Interval interval; static std::optional hashVal; @@ -269,6 +287,7 @@ namespace Components } hashVal.emplace(hash); + __VMProtectEnd; } #ifdef DEBUG_LOAD_LIBRARY @@ -414,6 +433,7 @@ namespace Components bool AntiCheat::IsPageChangeAllowed(void* callee, void* addr, size_t len) { + __VMProtectBeginUltra(""); HMODULE hModuleSelf = nullptr, hModuleTarget = nullptr, hModuleMain = GetModuleHandle(nullptr); GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast(callee), &hModuleTarget); GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast(AntiCheat::IsPageChangeAllowed), &hModuleSelf); @@ -430,34 +450,41 @@ namespace Components } } + __VMProtectEnd; return true; } BOOL WINAPI AntiCheat::VirtualProtectStub(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect) { + __VMProtectBeginUltra(""); if (!AntiCheat::IsPageChangeAllowed(_ReturnAddress(), lpAddress, dwSize)) return FALSE; AntiCheat::VirtualProtectHook[0].uninstall(false); BOOL result = VirtualProtect(lpAddress, dwSize, flNewProtect, lpflOldProtect); AntiCheat::VirtualProtectHook[0].install(false); + __VMProtectEnd; return result; } BOOL WINAPI AntiCheat::VirtualProtectExStub(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect) { + __VMProtectBeginUltra(""); if (GetCurrentProcessId() == GetProcessId(hProcess) && !AntiCheat::IsPageChangeAllowed(_ReturnAddress(), lpAddress, dwSize)) return FALSE; AntiCheat::VirtualProtectHook[1].uninstall(false); BOOL result = VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect, lpflOldProtect); AntiCheat::VirtualProtectHook[1].install(false); + __VMProtectEnd; return result; } unsigned long AntiCheat::ProtectProcess() { #ifdef PROCTECT_PROCESS + __VMProtectBeginUltra(""); + Utils::Memory::Allocator allocator; HANDLE hToken = nullptr; @@ -584,6 +611,8 @@ namespace Components if (!InitializeSecurityDescriptor(pSecDesc, SECURITY_DESCRIPTOR_REVISION)) return GetLastError(); if (!SetSecurityDescriptorDacl(pSecDesc, TRUE, pDacl, FALSE)) return GetLastError(); + __VMProtectEnd; + return SetSecurityInfo( GetCurrentProcess(), SE_KERNEL_OBJECT, // process object @@ -600,6 +629,8 @@ namespace Components void AntiCheat::AcquireDebugPrivilege(HANDLE hToken) { + __VMProtectBeginUltra(""); + LUID luid; TOKEN_PRIVILEGES tp = { 0 }; DWORD cb = sizeof(TOKEN_PRIVILEGES); @@ -610,16 +641,22 @@ namespace Components tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tp, cb, nullptr, nullptr); //if (GetLastError() != ERROR_SUCCESS) return; + + __VMProtectEnd; } void AntiCheat::PatchVirtualProtect(void* vp, void* vpex) { + __VMProtectBeginUltra(""); AntiCheat::VirtualProtectHook[1].initialize(vpex, AntiCheat::VirtualProtectExStub, HOOK_JUMP)->install(true, true); AntiCheat::VirtualProtectHook[0].initialize(vp, AntiCheat::VirtualProtectStub, HOOK_JUMP)->install(true, true); + __VMProtectEnd; } NTSTATUS NTAPI AntiCheat::NtCreateThreadExStub(PHANDLE phThread, ACCESS_MASK desiredAccess, LPVOID objectAttributes, HANDLE processHandle, LPTHREAD_START_ROUTINE startAddress, LPVOID parameter, BOOL createSuspended, DWORD stackZeroBits, DWORD sizeOfStackCommit, DWORD sizeOfStackReserve, LPVOID bytesBuffer) { + __VMProtectBeginUltra(""); + HANDLE hThread = nullptr; std::lock_guard _(AntiCheat::ThreadMutex); @@ -634,11 +671,15 @@ namespace Components AntiCheat::OwnThreadIds.push_back(GetThreadId(hThread)); } + __VMProtectEnd; + return result; } void AntiCheat::PatchThreadCreation() { + __VMProtectBeginUltra(""); + HMODULE ntdll = Utils::GetNTDLL(); if (ntdll) { @@ -649,10 +690,13 @@ namespace Components AntiCheat::CreateThreadHook.initialize(createThread, AntiCheat::NtCreateThreadExStub, HOOK_JUMP)->install(); } } + + __VMProtectEnd; } int AntiCheat::ValidateThreadTermination(void* addr) { + __VMProtectBeginUltra(""); { std::lock_guard _(AntiCheat::ThreadMutex); @@ -686,6 +730,8 @@ namespace Components std::this_thread::sleep_for(10ms); } + __VMProtectEnd; + return 0; // Don't kill } @@ -727,6 +773,7 @@ namespace Components void AntiCheat::VerifyThreadIntegrity() { + __VMProtectBeginUltra(""); bool kill = true; { std::lock_guard _(AntiCheat::ThreadMutex); @@ -774,10 +821,13 @@ namespace Components } } } + __VMProtectEnd; } AntiCheat::AntiCheat() { + __VMProtectBeginUltra(""); + time(nullptr); AntiCheat::Flags = NO_FLAG; @@ -817,6 +867,8 @@ namespace Components // Set the integrity flag AntiCheat::Flags |= AntiCheat::IntergrityFlag::INITIALIZATION; #endif + + __VMProtectEnd; } AntiCheat::~AntiCheat() diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index c9a1af42..ce11e613 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -100,6 +100,64 @@ namespace Components Game::CL_SelectStringTableEntryInDvar_f(); } + __declspec(naked) void QuickPatch::JavelinResetHookStub() + { + __asm + { + mov eax, 577A10h; + call eax; + pop edi; + mov dword ptr [esi+34h], 0; + pop esi; + pop ebx; + retn; + } + } + + int QuickPatch::InvalidNameCheck(char *dest, char *source, int size) + { + strncpy(dest, source, size - 1); + dest[size - 1] = 0; + + for (int i = 0; i < size - 1; i++) + { + if (dest[i] > 125 || dest[i] < 32) + { + return false; + } + } + + return true; + + } + + __declspec(naked) void QuickPatch::InvalidNameStub() + { + static char* kick_reason = "Invalid name detected."; + + __asm + { + call InvalidNameCheck; + cmp eax, 1; + + jne invalidName; + + invalidName: + pushad; + push 1; + push kick_reason; + push edi; + mov eax, 0x004D1600; + call eax; + add esp, 12; + popad; + + // return + push 0x00401988; + retn; + } + } + QuickPatch::QuickPatch() { QuickPatch::FrameTime = 0; @@ -108,6 +166,12 @@ namespace Components QuickPatch::FrameTime = Game::Sys_Milliseconds(); }); + // Disallow invalid player names + Utils::Hook(0x401983, QuickPatch::InvalidNameStub, HOOK_JUMP).install()->quick(); + + // Javelin fix + Utils::Hook(0x578F52, QuickPatch::JavelinResetHookStub, HOOK_JUMP).install()->quick(); + // Make sure preDestroy is called when the game shuts down Scheduler::OnShutdown(Loader::PreDestroy); diff --git a/src/Components/Modules/QuickPatch.hpp b/src/Components/Modules/QuickPatch.hpp index 22c57758..99ed8e6a 100644 --- a/src/Components/Modules/QuickPatch.hpp +++ b/src/Components/Modules/QuickPatch.hpp @@ -22,5 +22,10 @@ namespace Components static int MsgReadBitsCompressCheckSV(const char *from, char *to, int size); static int MsgReadBitsCompressCheckCL(const char *from, char *to, int size); + + static void JavelinResetHookStub(); + + static int QuickPatch::InvalidNameCheck(char *dest, char *source, int size); + static void QuickPatch::InvalidNameStub(); }; } diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index b7a4abd6..204039a8 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -341,6 +341,32 @@ namespace Components { MessageBoxA(nullptr, Game::Scr_GetString(0), "DEBUG", 0); }, true); + + // Script::AddFunction("playviewmodelfx", [](Game::scr_entref_t /*index*/) + // { + // /*auto Scr_Error = Utils::Hook::Call(0x42EF40); + // if (index >> 16) + // { + // Scr_Error("not an entity"); + // return; + // }*/ + + // // obtain FX name + // auto fxName = Game::Scr_GetString(0); + // auto fx = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_FX, fxName).fx; + + // auto tagName = Game::Scr_GetString(1); + // auto tagIndex = Game::SL_GetString(tagName, 0); + + // /*char boneIndex = -2; + // if (!Game::CG_GetBoneIndex(2048, tagIndex, &boneIndex)) + // { + // Scr_Error(Utils::String::VA("Unknown bone %s.\n", tagName)); + // return; + // }*/ + + // Game::CG_PlayBoltedEffect(0, fx, 2048, tagIndex); + // }); } Script::~Script() diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 5a647d11..07506472 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -15,7 +15,9 @@ namespace Game Cbuf_AddText_t Cbuf_AddText = Cbuf_AddText_t(0x404B20); CG_GetClientNum_t CG_GetClientNum = CG_GetClientNum_t(0x433700); - + CG_PlayBoltedEffect_t CG_PlayBoltedEffect = CG_PlayBoltedEffect_t(0x00430E10); + CG_GetBoneIndex_t CG_GetBoneIndex = CG_GetBoneIndex_t(0x00504F20); + CL_GetClientName_t CL_GetClientName = CL_GetClientName_t(0x4563D0); CL_IsCgameInitialized_t CL_IsCgameInitialized = CL_IsCgameInitialized_t(0x43EB20); CL_ConnectFromParty_t CL_ConnectFromParty = CL_ConnectFromParty_t(0x433D30); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 48d738e0..af4837f4 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -29,6 +29,12 @@ namespace Game typedef int(__cdecl * CG_GetClientNum_t)(); extern CG_GetClientNum_t CG_GetClientNum; + typedef std::int32_t(__cdecl* CG_PlayBoltedEffect_t) (std::int32_t, FxEffectDef*, std::int32_t, std::uint32_t); + extern CG_PlayBoltedEffect_t CG_PlayBoltedEffect; + + typedef std::int32_t(__cdecl* CG_GetBoneIndex_t)(std::int32_t, std::uint32_t name, char* index); + extern CG_GetBoneIndex_t CG_GetBoneIndex; + typedef char*(__cdecl * CL_GetClientName_t)(int localClientNum, int index, char *buf, size_t size); extern CL_GetClientName_t CL_GetClientName; diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 5f5c297a..d44062dd 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -8,6 +8,7 @@ #define _HAS_CXX17 1 #define VC_EXTRALEAN #define WIN32_LEAN_AND_MEAN +#define _CRT_SECURE_NO_WARNINGS // Requires Visual Leak Detector plugin: http://vld.codeplex.com/ #define VLD_FORCE_ENABLE @@ -90,6 +91,17 @@ template class Sizer { }; #undef min #endif +// VMProtect +// #define USE_VMP +#ifdef USE_VMP +#include +#define __VMProtectBeginUltra VMProtectBeginUltra +#define __VMProtectEnd VMProtectEnd() +#else +#define __VMProtectBeginUltra +#define __VMProtectEnd +#endif + // Protobuf #include "proto/network.pb.h" #include "proto/party.pb.h"