diff --git a/Source/Helpers.cpp b/Source/Helpers.cpp index f58d697f9f3..5042b9bd4a3 100644 --- a/Source/Helpers.cpp +++ b/Source/Helpers.cpp @@ -155,20 +155,6 @@ std::vector Helpers::loadBinaryFile(const std::string& path) noexcept return result; } -std::size_t Helpers::calculateVmtLength(const std::uintptr_t* vmt) noexcept -{ - std::size_t length = 0; -#if IS_WIN32() - MEMORY_BASIC_INFORMATION memoryInfo; - while (VirtualQuery(LPCVOID(vmt[length]), &memoryInfo, sizeof(memoryInfo)) && memoryInfo.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) - ++length; -#else - while (vmt[length]) - ++length; -#endif - return length; -} - static bool transformWorldPositionToScreenPosition(const csgo::Matrix4x4& matrix, const csgo::Vector& worldPosition, ImVec2& screenPosition) noexcept { const auto w = matrix._41 * worldPosition.x + matrix._42 * worldPosition.y + matrix._43 * worldPosition.z + matrix._44; diff --git a/Source/Helpers.h b/Source/Helpers.h index bd2901ae093..19bdda53d7b 100644 --- a/Source/Helpers.h +++ b/Source/Helpers.h @@ -54,8 +54,6 @@ namespace Helpers template constexpr auto deg2rad(T degrees) noexcept { return degrees * (std::numbers::pi_v / static_cast(180)); } template constexpr auto rad2deg(T radians) noexcept { return radians * (static_cast(180) / std::numbers::pi_v); } - [[nodiscard]] std::size_t calculateVmtLength(const std::uintptr_t* vmt) noexcept; - constexpr auto isKnife(WeaponId id) noexcept { return (id >= WeaponId::Bayonet && id <= WeaponId::SkeletonKnife) || id == WeaponId::KnifeT || id == WeaponId::Knife; diff --git a/Source/Hooks.cpp b/Source/Hooks.cpp index 3aab167878e..bd13b7fbb2c 100644 --- a/Source/Hooks.cpp +++ b/Source/Hooks.cpp @@ -86,15 +86,6 @@ void swapWindow(SDL_Window* window) noexcept; #endif -#if IS_WIN32() || IS_WIN64() - -Hooks::Hooks(HMODULE moduleHandle) noexcept - : windowProcedureHook{ FindWindowW(L"Valve001", nullptr) }, moduleHandle{ moduleHandle } -{ -} - -#endif - void Hooks::install(csgo::ClientPOD* clientInterface, const EngineInterfaces& engineInterfaces, const OtherInterfaces& interfaces, const Memory& memory) noexcept { #if IS_WIN32() diff --git a/Source/Hooks.h b/Source/Hooks.h index 30f31394622..280238a623b 100644 --- a/Source/Hooks.h +++ b/Source/Hooks.h @@ -65,15 +65,47 @@ int pollEvent(SDL_Event* event) noexcept; class Hooks { public: #if IS_WIN32() || IS_WIN64() - Hooks(HMODULE moduleHandle) noexcept; + template + Hooks(HMODULE moduleHandle, DynamicLibrary clientDll, DynamicLibrary engineDll, DynamicLibrary vstdlibDll, DynamicLibrary vguiMatSurfaceDll) noexcept + : windowProcedureHook{ FindWindowW(L"Valve001", nullptr) } + , keyValuesSystemHooks{ vstdlibDll.getCodeSection() } + , engineHooks{ engineDll.getCodeSection() } + , clientHooks{ clientDll.getCodeSection() } + , clientModeHooks{ clientDll.getCodeSection() } + , clientStateHooks{ engineDll.getCodeSection() } + , playerInventoryHooks{ clientDll.getCodeSection() } + , panoramaMarshallHelperHooks{ clientDll.getCodeSection() } + , viewRenderHooks{ clientDll.getCodeSection() } + , inventoryManagerHooks{ clientDll.getCodeSection() } + , bspQueryHooks{ engineDll.getCodeSection() } + , engineSoundHooks{ engineDll.getCodeSection() } + , svCheatsHooks{ engineDll.getCodeSection() } + , modelRenderHooks{ engineDll.getCodeSection() } + , surfaceHooks{ vguiMatSurfaceDll.getCodeSection() } + , moduleHandle{ moduleHandle } + { + } WindowProcedureHook windowProcedureHook; std::add_pointer_t originalPresent; std::add_pointer_t originalReset; #elif IS_LINUX() template - Hooks(PlatformApi) noexcept + Hooks(DynamicLibrary clientDll, DynamicLibrary engineDll, DynamicLibrary vstdlibDll, DynamicLibrary vguiMatSurfaceDll) noexcept : sdlFunctions{ DynamicLibrary{ "libSDL2-2.0.so.0" } } + , engineHooks{ engineDll.getCodeSection() } + , clientHooks{ clientDll.getCodeSection() } + , clientModeHooks{ clientDll.getCodeSection() } + , clientStateHooks{ engineDll.getCodeSection() } + , playerInventoryHooks{ clientDll.getCodeSection() } + , panoramaMarshallHelperHooks{ clientDll.getCodeSection() } + , viewRenderHooks{ clientDll.getCodeSection() } + , inventoryManagerHooks{ clientDll.getCodeSection() } + , bspQueryHooks{ engineDll.getCodeSection() } + , engineSoundHooks{ engineDll.getCodeSection() } + , svCheatsHooks{ engineDll.getCodeSection() } + , modelRenderHooks{ engineDll.getCodeSection() } + , surfaceHooks{ vguiMatSurfaceDll.getCodeSection() } { pollEvent = *reinterpret_cast(sdlFunctions.pollEvent); *reinterpret_cast(sdlFunctions.pollEvent) = ::pollEvent; diff --git a/Source/Hooks/BspQueryHooks.h b/Source/Hooks/BspQueryHooks.h index d145fa61179..5f771fbcd4d 100644 --- a/Source/Hooks/BspQueryHooks.h +++ b/Source/Hooks/BspQueryHooks.h @@ -4,11 +4,17 @@ #include #include #include +#include namespace csgo { struct Vector; } class BspQueryHooks { public: + explicit BspQueryHooks(std::span engineCodeSection) + : hookImpl{ VmtLengthCalculator{ engineCodeSection } } + { + } + void install(void* engineSpatialQuery) { hookImpl.init(engineSpatialQuery); diff --git a/Source/Hooks/CSPlayerInventoryHooks.h b/Source/Hooks/CSPlayerInventoryHooks.h index 8c7f0ec317f..802190fe7a2 100644 --- a/Source/Hooks/CSPlayerInventoryHooks.h +++ b/Source/Hooks/CSPlayerInventoryHooks.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace csgo { @@ -14,6 +15,11 @@ namespace csgo class CSPlayerInventoryHooks { public: + explicit CSPlayerInventoryHooks(std::span clientCodeSection) + : hookImpl{ VmtLengthCalculator{ clientCodeSection } } + { + } + void install(csgo::CSPlayerInventoryPOD* inventory) { hookImpl.init(inventory); diff --git a/Source/Hooks/ClientHooks.h b/Source/Hooks/ClientHooks.h index e197fec3316..e8b40c01f37 100644 --- a/Source/Hooks/ClientHooks.h +++ b/Source/Hooks/ClientHooks.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace csgo { @@ -14,6 +15,11 @@ namespace csgo class ClientHooks { public: + explicit ClientHooks(std::span clientCodeSection) + : hookImpl{ VmtLengthCalculator{ clientCodeSection } } + { + } + void install(csgo::ClientPOD* client) { hookImpl.init(client); diff --git a/Source/Hooks/ClientModeHooks.h b/Source/Hooks/ClientModeHooks.h index ccaa2017984..e7b5efd4f23 100644 --- a/Source/Hooks/ClientModeHooks.h +++ b/Source/Hooks/ClientModeHooks.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace csgo { @@ -14,6 +15,11 @@ namespace csgo class ClientModeHooks { public: + explicit ClientModeHooks(std::span clientCodeSection) + : hookImpl{ VmtLengthCalculator{ clientCodeSection } } + { + } + void install(csgo::ClientMode* clientMode) { hookImpl.init(clientMode); diff --git a/Source/Hooks/ClientStateHooks.h b/Source/Hooks/ClientStateHooks.h index 829a73fd6d2..bfa005c5b8c 100644 --- a/Source/Hooks/ClientStateHooks.h +++ b/Source/Hooks/ClientStateHooks.h @@ -4,11 +4,17 @@ #include #include #include +#include namespace csgo { struct ClientState; } class ClientStateHooks { public: + explicit ClientStateHooks(std::span engineCodeSection) + : hookImpl{ VmtLengthCalculator{ engineCodeSection } } + { + } + void install(csgo::ClientState* clientState) { hookImpl.init(clientState); diff --git a/Source/Hooks/EngineHooks.h b/Source/Hooks/EngineHooks.h index 4f8f9ba33a5..e9a81c3050e 100644 --- a/Source/Hooks/EngineHooks.h +++ b/Source/Hooks/EngineHooks.h @@ -3,12 +3,18 @@ #include #include #include +#include namespace csgo { struct DemoPlaybackParameters; } namespace csgo { struct EnginePOD; } class EngineHooks { public: + explicit EngineHooks(std::span engineCodeSection) + : hookImpl{ VmtLengthCalculator{ engineCodeSection } } + { + } + void install(csgo::EnginePOD* engine) { hookImpl.init(engine); diff --git a/Source/Hooks/EngineSoundHooks.h b/Source/Hooks/EngineSoundHooks.h index 87099bc2d81..419d06f63ca 100644 --- a/Source/Hooks/EngineSoundHooks.h +++ b/Source/Hooks/EngineSoundHooks.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace csgo { @@ -13,6 +14,11 @@ namespace csgo class EngineSoundHooks { public: + explicit EngineSoundHooks(std::span engineCodeSection) + : hookImpl{ VmtLengthCalculator{ engineCodeSection } } + { + } + void install(csgo::EngineSoundPOD* engineSound) { hookImpl.init(engineSound); diff --git a/Source/Hooks/InventoryManagerHooks.h b/Source/Hooks/InventoryManagerHooks.h index 552f7db5fb9..2f602eb6593 100644 --- a/Source/Hooks/InventoryManagerHooks.h +++ b/Source/Hooks/InventoryManagerHooks.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace csgo { @@ -13,6 +14,11 @@ namespace csgo class InventoryManagerHooks { public: + explicit InventoryManagerHooks(std::span clientCodeSection) + : hookImpl{ VmtLengthCalculator{ clientCodeSection } } + { + } + void install(csgo::InventoryManagerPOD* inventoryManager) { hookImpl.init(inventoryManager); diff --git a/Source/Hooks/KeyValuesSystemHooks.h b/Source/Hooks/KeyValuesSystemHooks.h index 930bf72bb05..d2c56de78cb 100644 --- a/Source/Hooks/KeyValuesSystemHooks.h +++ b/Source/Hooks/KeyValuesSystemHooks.h @@ -4,11 +4,17 @@ #include #include #include +#include namespace csgo { struct KeyValuesSystemPOD; } class KeyValuesSystemHooks { public: + explicit KeyValuesSystemHooks(std::span vstdlibCodeSection) + : hookImpl{ VmtLengthCalculator{ vstdlibCodeSection } } + { + } + void install(csgo::KeyValuesSystemPOD* keyValuesSystem) { hookImpl.init(keyValuesSystem); diff --git a/Source/Hooks/MinHook.h b/Source/Hooks/MinHook.h index 1fcaf2bc88d..f3dfc6e8b9c 100644 --- a/Source/Hooks/MinHook.h +++ b/Source/Hooks/MinHook.h @@ -5,9 +5,14 @@ #include #include +#include class MinHook { public: + explicit MinHook(VmtLengthCalculator) + { + } + void init(void* base) noexcept; void restore() noexcept {} std::uintptr_t hookAt(std::size_t index, void* fun) noexcept; diff --git a/Source/Hooks/ModelRenderHooks.h b/Source/Hooks/ModelRenderHooks.h index 7515728fe60..11e4ed59803 100644 --- a/Source/Hooks/ModelRenderHooks.h +++ b/Source/Hooks/ModelRenderHooks.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace csgo { @@ -14,6 +15,11 @@ namespace csgo class ModelRenderHooks { public: + explicit ModelRenderHooks(std::span engineCodeSection) + : hookImpl{ VmtLengthCalculator{ engineCodeSection } } + { + } + void install(csgo::ModelRenderPOD* modelRender) { hookImpl.init(modelRender); diff --git a/Source/Hooks/PanoramaMarshallHelperHooks.h b/Source/Hooks/PanoramaMarshallHelperHooks.h index 47d50089ce6..d7d6db99bb3 100644 --- a/Source/Hooks/PanoramaMarshallHelperHooks.h +++ b/Source/Hooks/PanoramaMarshallHelperHooks.h @@ -4,11 +4,17 @@ #include #include #include +#include namespace csgo { struct PanoramaMarshallHelperPOD; } class PanoramaMarshallHelperHooks { public: + explicit PanoramaMarshallHelperHooks(std::span clientCodeSection) + : hookImpl{ VmtLengthCalculator{ clientCodeSection } } + { + } + void install(csgo::PanoramaMarshallHelperPOD* panoramaMarshallHelper) { hookImpl.init(panoramaMarshallHelper); diff --git a/Source/Hooks/SurfaceHooks.h b/Source/Hooks/SurfaceHooks.h index 916bb5f2a49..276d3a9929d 100644 --- a/Source/Hooks/SurfaceHooks.h +++ b/Source/Hooks/SurfaceHooks.h @@ -5,11 +5,17 @@ #include #include #include +#include namespace csgo { struct SurfacePOD; } class SurfaceHooks { public: + explicit SurfaceHooks(std::span vguiMatSurfaceCodeSection) + : hookImpl{ VmtLengthCalculator{ vguiMatSurfaceCodeSection } } + { + } + void install(csgo::SurfacePOD* surface) { hookImpl.init(surface); diff --git a/Source/Hooks/SvCheatsHooks.h b/Source/Hooks/SvCheatsHooks.h index 4d5cd980773..a5a81b02dbf 100644 --- a/Source/Hooks/SvCheatsHooks.h +++ b/Source/Hooks/SvCheatsHooks.h @@ -4,11 +4,17 @@ #include #include #include +#include namespace csgo { struct ConVarPOD; } class SvCheatsHooks { public: + explicit SvCheatsHooks(std::span engineCodeSection) + : hookImpl{ VmtLengthCalculator{ engineCodeSection } } + { + } + void install(csgo::ConVarPOD* svCheats) { hookImpl.init(svCheats); diff --git a/Source/Hooks/ViewRenderHooks.h b/Source/Hooks/ViewRenderHooks.h index 3767e07ba30..59a20683028 100644 --- a/Source/Hooks/ViewRenderHooks.h +++ b/Source/Hooks/ViewRenderHooks.h @@ -4,11 +4,17 @@ #include #include #include +#include namespace csgo { struct ViewRender; } class ViewRenderHooks { public: + explicit ViewRenderHooks(std::span clientCodeSection) + : hookImpl{ VmtLengthCalculator{ clientCodeSection } } + { + } + void install(csgo::ViewRender* viewRender) { hookImpl.init(viewRender); diff --git a/Source/Hooks/VmtSwap.cpp b/Source/Hooks/VmtSwap.cpp index d01794c6c7f..6b6fb810309 100644 --- a/Source/Hooks/VmtSwap.cpp +++ b/Source/Hooks/VmtSwap.cpp @@ -7,7 +7,7 @@ void VmtSwap::init(void* base) noexcept { this->base = base; oldVmt = *reinterpret_cast(base); - std::size_t length = Helpers::calculateVmtLength(oldVmt) + dynamicCastInfoLength; + length = static_cast(vmtLengthCalculator(oldVmt)) + dynamicCastInfoLength; newVmt = std::make_unique(length); std::copy(oldVmt - dynamicCastInfoLength, oldVmt - dynamicCastInfoLength + length, newVmt.get()); *reinterpret_cast(base) = newVmt.get() + dynamicCastInfoLength; diff --git a/Source/Hooks/VmtSwap.h b/Source/Hooks/VmtSwap.h index d0faa348dea..c49ea64ae4a 100644 --- a/Source/Hooks/VmtSwap.h +++ b/Source/Hooks/VmtSwap.h @@ -6,9 +6,15 @@ #include #include +#include class VmtSwap { public: + explicit VmtSwap(VmtLengthCalculator vmtLengthCalculator) + : vmtLengthCalculator{ vmtLengthCalculator } + { + } + void init(void* base) noexcept; void restore() noexcept { @@ -25,6 +31,7 @@ class VmtSwap { private: static constexpr auto dynamicCastInfoLength = WIN32_LINUX(1, 2); + VmtLengthCalculator vmtLengthCalculator; void* base = nullptr; std::uintptr_t* oldVmt = nullptr; std::unique_ptr newVmt; diff --git a/Source/Osiris.cpp b/Source/Osiris.cpp index e60d232bb26..607e330f5e8 100644 --- a/Source/Osiris.cpp +++ b/Source/Osiris.cpp @@ -45,7 +45,7 @@ BOOL APIENTRY DllEntryPoint(HMODULE moduleHandle, DWORD reason, LPVOID reserved) if (reason == DLL_PROCESS_ATTACH) { std::setlocale(LC_CTYPE, ".utf8"); initializeGlobalContext(); - hooks.emplace(moduleHandle); + hooks.emplace(moduleHandle, DynamicLibrary{ csgo::CLIENT_DLL }, DynamicLibrary{ csgo::ENGINE_DLL }, DynamicLibrary{ csgo::VSTDLIB_DLL }, DynamicLibrary{ csgo::VGUIMATSURFACE_DLL }); } return TRUE; } @@ -55,7 +55,7 @@ BOOL APIENTRY DllEntryPoint(HMODULE moduleHandle, DWORD reason, LPVOID reserved) void __attribute__((constructor)) DllEntryPoint() { initializeGlobalContext(); - hooks.emplace(PlatformApi{}); + hooks.emplace(DynamicLibrary{ csgo::CLIENT_DLL }, DynamicLibrary{ csgo::ENGINE_DLL }, DynamicLibrary{ csgo::VSTDLIB_DLL }, DynamicLibrary{ csgo::VGUIMATSURFACE_DLL }); } #endif diff --git a/Source/Osiris.vcxproj b/Source/Osiris.vcxproj index 4a826dfbb7b..53383c0c190 100644 --- a/Source/Osiris.vcxproj +++ b/Source/Osiris.vcxproj @@ -450,6 +450,8 @@ + + diff --git a/Source/Osiris.vcxproj.filters b/Source/Osiris.vcxproj.filters index 7e0fd1fd753..f8f172a92ec 100644 --- a/Source/Osiris.vcxproj.filters +++ b/Source/Osiris.vcxproj.filters @@ -105,6 +105,9 @@ {725dc9cb-6df9-4b2c-8095-bb88f2061822} + + {cf4fc922-308a-4d3c-8448-4e4002e85dc4} + @@ -1186,6 +1189,12 @@ BytePatterns + + Vmt + + + Vmt + diff --git a/Source/Vmt/VmtLength.h b/Source/Vmt/VmtLength.h new file mode 100644 index 00000000000..b53e05a95f9 --- /dev/null +++ b/Source/Vmt/VmtLength.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +enum class VmtLength : std::size_t {}; diff --git a/Source/Vmt/VmtLengthCalculator.h b/Source/Vmt/VmtLengthCalculator.h new file mode 100644 index 00000000000..52b4361f7c2 --- /dev/null +++ b/Source/Vmt/VmtLengthCalculator.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +#include "VmtLength.h" + +struct VmtLengthCalculator { + explicit VmtLengthCalculator(std::span codeSection) + : codeSection{ codeSection } + { + } + + [[nodiscard]] VmtLength operator()(const std::uintptr_t* vmt) const noexcept + { + std::size_t length = 0; + while (vmt[length] >= std::uintptr_t(codeSection.data()) && vmt[length] < std::uintptr_t(codeSection.data() + codeSection.size())) + ++length; + return VmtLength{ length }; + } + +private: + std::span codeSection; +};