Skip to content

Commit c4092c9

Browse files
committed
prepare
1 parent 298762d commit c4092c9

File tree

12 files changed

+1216
-5
lines changed

12 files changed

+1216
-5
lines changed

CMakeLists.txt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@ include_directories(
1515
./vendor/nlohmann
1616
./vendor/fmt/include
1717
./vendor/polyhook/include
18+
./vendor/safetyhook/include
1819
./vendor/zlib/include
1920
)
2021

2122
file(GLOB SURFTIMER_LIBS
22-
"./vendor/libmem/lib/*${CMAKE_STATIC_LIBRARY_SUFFIX}"
23-
"./vendor/libmodule/lib/*${CMAKE_STATIC_LIBRARY_SUFFIX}"
24-
"./vendor/libhv/lib/*${CMAKE_STATIC_LIBRARY_SUFFIX}"
25-
"./vendor/polyhook/lib/*${CMAKE_STATIC_LIBRARY_SUFFIX}"
26-
"./vendor/zlib/lib/*${CMAKE_STATIC_LIBRARY_SUFFIX}"
23+
"./vendor/libmem/lib/*${CMAKE_STATIC_LIBRARY_SUFFIX}"
24+
"./vendor/libmodule/lib/*${CMAKE_STATIC_LIBRARY_SUFFIX}"
25+
"./vendor/libhv/lib/*${CMAKE_STATIC_LIBRARY_SUFFIX}"
26+
"./vendor/polyhook/lib/*${CMAKE_STATIC_LIBRARY_SUFFIX}"
27+
"./vendor/safetyhook/lib/*${CMAKE_STATIC_LIBRARY_SUFFIX}"
28+
"./vendor/zlib/lib/*${CMAKE_STATIC_LIBRARY_SUFFIX}"
2729
)
2830

2931
file(GLOB_RECURSE SDK_SOURCES

src/cs2surf.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include <vendor/MultiAddonManager/public/imultiaddonmanager.h>
2121

22+
#include <safetyhook.hpp>
23+
2224
IMultiAddonManager* g_pMultiAddonManager;
2325

2426
CSurfPlugin g_SurfPlugin;
@@ -29,6 +31,11 @@ CSurfPlugin* SurfPlugin() {
2931
return &g_SurfPlugin;
3032
}
3133

34+
SafetyHookInline g_HkSurfPlugin{};
35+
CSurfPlugin* HkSurfPlugin() {
36+
return g_HkSurfPlugin.call<CSurfPlugin*>();
37+
}
38+
3239
bool CSurfPlugin::Load(PluginId id, ISmmAPI* ismm, char* error, size_t maxlen, bool late) {
3340
PLUGIN_SAVEVARS();
3441

@@ -45,6 +52,8 @@ bool CSurfPlugin::Load(PluginId id, ISmmAPI* ismm, char* error, size_t maxlen, b
4552

4653
g_SMAPI->AddListener(this, this);
4754

55+
g_HkSurfPlugin = safetyhook::create_inline(SurfPlugin, HkSurfPlugin);
56+
4857
ADMIN::AddAdmin(76561198083290027, AdminFlag::Root);
4958

5059
return true;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
3+
#include "safetyhook/os.hpp"
4+
#include "safetyhook/easy.hpp"
5+
#include "safetyhook/inline_hook.hpp"
6+
#include "safetyhook/mid_hook.hpp"
7+
#include "safetyhook/vmt_hook.hpp"
8+
9+
using SafetyHookContext = safetyhook::Context;
10+
using SafetyHookInline = safetyhook::InlineHook;
11+
using SafetyHookMid = safetyhook::MidHook;
12+
using SafetyInlineHook [[deprecated("Use SafetyHookInline instead.")]] = safetyhook::InlineHook;
13+
using SafetyMidHook [[deprecated("Use SafetyHookMid instead.")]] = safetyhook::MidHook;
14+
using SafetyHookVmt = safetyhook::VmtHook;
15+
using SafetyHookVm = safetyhook::VmHook;
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/// @file safetyhook/allocator.hpp
2+
/// @brief Allocator for allocating memory near target addresses.
3+
4+
#pragma once
5+
6+
#ifndef SAFETYHOOK_USE_CXXMODULES
7+
#include <cstdint>
8+
#include <expected>
9+
#include <memory>
10+
#include <mutex>
11+
#include <vector>
12+
#else
13+
import std.compat;
14+
#endif
15+
16+
#include "safetyhook/common.hpp"
17+
18+
namespace safetyhook {
19+
class Allocator;
20+
21+
/// @brief A memory allocation.
22+
class SAFETYHOOK_API Allocation final {
23+
public:
24+
Allocation() = default;
25+
Allocation(const Allocation&) = delete;
26+
Allocation(Allocation&& other) noexcept;
27+
Allocation& operator=(const Allocation&) = delete;
28+
Allocation& operator=(Allocation&& other) noexcept;
29+
~Allocation();
30+
31+
/// @brief Frees the allocation.
32+
/// @note This is called automatically when the Allocation object is destroyed.
33+
void free();
34+
35+
/// @brief Returns a pointer to the data of the allocation.
36+
/// @return Pointer to the data of the allocation.
37+
[[nodiscard]] uint8_t* data() const noexcept { return m_address; }
38+
39+
/// @brief Returns the address of the allocation.
40+
/// @return The address of the allocation.
41+
[[nodiscard]] uintptr_t address() const noexcept { return reinterpret_cast<uintptr_t>(m_address); }
42+
43+
/// @brief Returns the size of the allocation.
44+
/// @return The size of the allocation.
45+
[[nodiscard]] size_t size() const noexcept { return m_size; }
46+
47+
/// @brief Tests if the allocation is valid.
48+
/// @return True if the allocation is valid, false otherwise.
49+
explicit operator bool() const noexcept { return m_address != nullptr && m_size != 0; }
50+
51+
protected:
52+
friend Allocator;
53+
54+
Allocation(std::shared_ptr<Allocator> allocator, uint8_t* address, size_t size) noexcept;
55+
56+
private:
57+
std::shared_ptr<Allocator> m_allocator{};
58+
uint8_t* m_address{};
59+
size_t m_size{};
60+
};
61+
62+
/// @brief Allocates memory near target addresses.
63+
class SAFETYHOOK_API Allocator final : public std::enable_shared_from_this<Allocator> {
64+
public:
65+
/// @brief Returns the global Allocator.
66+
/// @return The global Allocator.
67+
[[nodiscard]] static std::shared_ptr<Allocator> global();
68+
69+
/// @brief Creates a new Allocator.
70+
/// @return The new Allocator.
71+
[[nodiscard]] static std::shared_ptr<Allocator> create();
72+
73+
Allocator(const Allocator&) = delete;
74+
Allocator(Allocator&&) noexcept = delete;
75+
Allocator& operator=(const Allocator&) = delete;
76+
Allocator& operator=(Allocator&&) noexcept = delete;
77+
~Allocator() = default;
78+
79+
/// @brief The error type returned by the allocate functions.
80+
enum class Error : uint8_t {
81+
BAD_VIRTUAL_ALLOC, ///< VirtualAlloc failed.
82+
NO_MEMORY_IN_RANGE, ///< No memory in range.
83+
};
84+
85+
/// @brief Allocates memory.
86+
/// @param size The size of the allocation.
87+
/// @return The Allocation or an Allocator::Error if the allocation failed.
88+
[[nodiscard]] std::expected<Allocation, Error> allocate(size_t size);
89+
90+
/// @brief Allocates memory near a target address.
91+
/// @param desired_addresses The target address.
92+
/// @param size The size of the allocation.
93+
/// @param max_distance The maximum distance from the target address.
94+
/// @return The Allocation or an Allocator::Error if the allocation failed.
95+
[[nodiscard]] std::expected<Allocation, Error> allocate_near(
96+
const std::vector<uint8_t*>& desired_addresses, size_t size, size_t max_distance = 0x7FFF'FFFF);
97+
98+
protected:
99+
friend Allocation;
100+
101+
void free(uint8_t* address, size_t size);
102+
103+
private:
104+
struct FreeNode {
105+
std::unique_ptr<FreeNode> next{};
106+
uint8_t* start{};
107+
uint8_t* end{};
108+
};
109+
110+
struct Memory {
111+
uint8_t* address{};
112+
size_t size{};
113+
std::unique_ptr<FreeNode> freelist{};
114+
115+
~Memory();
116+
};
117+
118+
std::vector<std::unique_ptr<Memory>> m_memory{};
119+
std::mutex m_mutex{};
120+
121+
Allocator() = default;
122+
123+
[[nodiscard]] std::expected<Allocation, Error> internal_allocate_near(
124+
const std::vector<uint8_t*>& desired_addresses, size_t size, size_t max_distance = 0x7FFF'FFFF);
125+
void internal_free(uint8_t* address, size_t size);
126+
127+
static void combine_adjacent_freenodes(Memory& memory);
128+
[[nodiscard]] static std::expected<uint8_t*, Error> allocate_nearby_memory(
129+
const std::vector<uint8_t*>& desired_addresses, size_t size, size_t max_distance);
130+
[[nodiscard]] static bool in_range(
131+
uint8_t* address, const std::vector<uint8_t*>& desired_addresses, size_t max_distance);
132+
};
133+
} // namespace safetyhook
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#pragma once
2+
3+
#if defined(_MSC_VER)
4+
#define SAFETYHOOK_COMPILER_MSVC 1
5+
#define SAFETYHOOK_COMPILER_GCC 0
6+
#define SAFETYHOOK_COMPILER_CLANG 0
7+
#elif defined(__GNUC__)
8+
#define SAFETYHOOK_COMPILER_MSVC 0
9+
#define SAFETYHOOK_COMPILER_GCC 1
10+
#define SAFETYHOOK_COMPILER_CLANG 0
11+
#elif defined(__clang__)
12+
#define SAFETYHOOK_COMPILER_MSVC 0
13+
#define SAFETYHOOK_COMPILER_GCC 0
14+
#define SAFETYHOOK_COMPILER_CLANG 1
15+
#else
16+
#error "Unsupported compiler"
17+
#endif
18+
19+
#if SAFETYHOOK_COMPILER_MSVC
20+
#if defined(_M_IX86)
21+
#define SAFETYHOOK_ARCH_X86_32 1
22+
#define SAFETYHOOK_ARCH_X86_64 0
23+
#elif defined(_M_X64)
24+
#define SAFETYHOOK_ARCH_X86_32 0
25+
#define SAFETYHOOK_ARCH_X86_64 1
26+
#else
27+
#error "Unsupported architecture"
28+
#endif
29+
#elif SAFETYHOOK_COMPILER_GCC || SAFETYHOOK_COMPILER_CLANG
30+
#if defined(__i386__)
31+
#define SAFETYHOOK_ARCH_X86_32 1
32+
#define SAFETYHOOK_ARCH_X86_64 0
33+
#elif defined(__x86_64__)
34+
#define SAFETYHOOK_ARCH_X86_32 0
35+
#define SAFETYHOOK_ARCH_X86_64 1
36+
#else
37+
#error "Unsupported architecture"
38+
#endif
39+
#endif
40+
41+
#if defined(_WIN32)
42+
#define SAFETYHOOK_OS_WINDOWS 1
43+
#define SAFETYHOOK_OS_LINUX 0
44+
#elif defined(__linux__)
45+
#define SAFETYHOOK_OS_WINDOWS 0
46+
#define SAFETYHOOK_OS_LINUX 1
47+
#else
48+
#error "Unsupported OS"
49+
#endif
50+
51+
#if SAFETYHOOK_OS_WINDOWS
52+
#if SAFETYHOOK_COMPILER_MSVC
53+
#define SAFETYHOOK_CCALL __cdecl
54+
#define SAFETYHOOK_STDCALL __stdcall
55+
#define SAFETYHOOK_FASTCALL __fastcall
56+
#define SAFETYHOOK_THISCALL __thiscall
57+
#elif SAFETYHOOK_COMPILER_GCC || SAFETYHOOK_COMPILER_CLANG
58+
#define SAFETYHOOK_CCALL __attribute__((cdecl))
59+
#define SAFETYHOOK_STDCALL __attribute__((stdcall))
60+
#define SAFETYHOOK_FASTCALL __attribute__((fastcall))
61+
#define SAFETYHOOK_THISCALL __attribute__((thiscall))
62+
#endif
63+
#else
64+
#define SAFETYHOOK_CCALL
65+
#define SAFETYHOOK_STDCALL
66+
#define SAFETYHOOK_FASTCALL
67+
#define SAFETYHOOK_THISCALL
68+
#endif
69+
70+
#if SAFETYHOOK_COMPILER_MSVC
71+
#define SAFETYHOOK_NOINLINE __declspec(noinline)
72+
#elif SAFETYHOOK_COMPILER_GCC || SAFETYHOOK_COMPILER_CLANG
73+
#define SAFETYHOOK_NOINLINE __attribute__((noinline))
74+
#endif
75+
76+
#if SAFETYHOOK_COMPILER_MSVC
77+
#define SAFETYHOOK_DLLEXPORT __declspec(dllexport)
78+
#define SAFETYHOOK_DLLIMPORT __declspec(dllimport)
79+
#elif SAFETYHOOK_COMPILER_GCC || SAFETYHOOK_COMPILER_CLANG
80+
#define SAFETYHOOK_DLLEXPORT __attribute__((visibility("default")))
81+
#define SAFETYHOOK_DLLIMPORT
82+
#endif
83+
84+
#if SAFETYHOOK_SHARED_LIB && SAFETYHOOK_BUILDING
85+
#define SAFETYHOOK_API SAFETYHOOK_DLLEXPORT
86+
#elif SAFETYHOOK_SHARED_LIB
87+
#define SAFETYHOOK_API SAFETYHOOK_DLLIMPORT
88+
#else
89+
#define SAFETYHOOK_API
90+
#endif
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/// @file safetyhook/context.hpp
2+
/// @brief Context structure for MidHook.
3+
4+
#pragma once
5+
6+
#ifndef SAFETYHOOK_USE_CXXMODULES
7+
#include <cstdint>
8+
#else
9+
import std.compat;
10+
#endif
11+
12+
#include "safetyhook/common.hpp"
13+
14+
namespace safetyhook {
15+
union Xmm {
16+
uint8_t u8[16];
17+
uint16_t u16[8];
18+
uint32_t u32[4];
19+
uint64_t u64[2];
20+
float f32[4];
21+
double f64[2];
22+
};
23+
24+
/// @brief Context structure for 64-bit MidHook.
25+
/// @details This structure is used to pass the context of the hooked function to the destination allowing full access
26+
/// to the 64-bit registers at the moment the hook is called.
27+
/// @note rip will point to a trampoline containing the replaced instruction(s).
28+
/// @note rsp is read-only. Modifying it will have no effect. Use trampoline_rsp to modify rsp if needed but make sure
29+
/// the top of the stack is the rip you want to resume at.
30+
struct Context64 {
31+
Xmm xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
32+
uintptr_t rflags, r15, r14, r13, r12, r11, r10, r9, r8, rdi, rsi, rdx, rcx, rbx, rax, rbp, rsp, trampoline_rsp, rip;
33+
};
34+
35+
/// @brief Context structure for 32-bit MidHook.
36+
/// @details This structure is used to pass the context of the hooked function to the destination allowing full access
37+
/// to the 32-bit registers at the moment the hook is called.
38+
/// @note eip will point to a trampoline containing the replaced instruction(s).
39+
/// @note esp is read-only. Modifying it will have no effect. Use trampoline_esp to modify esp if needed but make sure
40+
/// the top of the stack is the eip you want to resume at.
41+
struct Context32 {
42+
Xmm xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7;
43+
uintptr_t eflags, edi, esi, edx, ecx, ebx, eax, ebp, esp, trampoline_esp, eip;
44+
};
45+
46+
/// @brief Context structure for MidHook.
47+
/// @details This structure is used to pass the context of the hooked function to the destination allowing full access
48+
/// to the registers at the moment the hook is called.
49+
/// @note The structure is different depending on architecture.
50+
/// @note The structure only provides access to integer registers.
51+
#if SAFETYHOOK_ARCH_X86_64
52+
using Context = Context64;
53+
#elif SAFETYHOOK_ARCH_X86_32
54+
using Context = Context32;
55+
#endif
56+
57+
} // namespace safetyhook

0 commit comments

Comments
 (0)