mirror of
https://github.com/diamante0018/MW3ServerFreezer.git
synced 2025-04-19 11:42:53 +00:00
feat: compile project with clang (with vs on Windows)
This commit is contained in:
parent
779676b8ee
commit
b3841d855e
11
premake5.lua
11
premake5.lua
@ -61,10 +61,17 @@ filter "configurations:release"
|
||||
optimize "Size"
|
||||
defines {"NDEBUG"}
|
||||
flags {"FatalCompileWarnings"}
|
||||
buildoptions {"/GL"}
|
||||
|
||||
filter "action:msc"
|
||||
buildoptions "/GL"
|
||||
linkoptions {"/IGNORE:4702", "/LTCG"}
|
||||
filter {}
|
||||
|
||||
filter "toolset:not msc*"
|
||||
buildoptions "-Wno-unused-parameter"
|
||||
filter {}
|
||||
filter {}
|
||||
|
||||
filter "configurations:debug"
|
||||
optimize "Debug"
|
||||
defines {"DEBUG", "_DEBUG"}
|
||||
@ -91,8 +98,6 @@ targetname "mw3-server-freezer"
|
||||
pchheader "std_include.hpp"
|
||||
pchsource "src/client/std_include.cpp"
|
||||
|
||||
linkoptions {"/PDBCompress"}
|
||||
|
||||
files {"./src/client/**.hpp", "./src/client/**.cpp"}
|
||||
|
||||
includedirs {"./src/client", "./src/common", "%{prj.location}/src"}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "command.hpp"
|
||||
#include "console.hpp"
|
||||
|
||||
constexpr auto CMD_MAX_NESTING = 8;
|
||||
[[maybe_unused]] constexpr auto CMD_MAX_NESTING = 8;
|
||||
|
||||
namespace command {
|
||||
std::unordered_map<std::string, std::function<void(params&)>> handlers;
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
}
|
||||
|
||||
void post_unpack() override {
|
||||
utils::hook(0x446930, append_text, HOOK_JUMP).install()->quick();
|
||||
utils::hook(0x446930, HOOK_CAST(append_text), HOOK_JUMP).install()->quick();
|
||||
|
||||
this->initialize();
|
||||
}
|
||||
|
@ -20,13 +20,15 @@ void dvar_override_cheat_protection_stub(bool /*cheat_override*/) {
|
||||
class component final : public component_interface {
|
||||
public:
|
||||
void post_unpack() override {
|
||||
utils::hook(0x59C0EF, dvar_set_from_string_by_name_stub, HOOK_CALL)
|
||||
.install()
|
||||
utils::hook(0x59C0EF, HOOK_CAST(dvar_set_from_string_by_name_stub),
|
||||
HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
|
||||
*game::isCheatOverride = true;
|
||||
utils::hook(0x482CC0, dvar_override_cheat_protection_stub, HOOK_JUMP)
|
||||
.install()
|
||||
utils::hook(0x482CC0, HOOK_CAST(dvar_override_cheat_protection_stub),
|
||||
HOOK_JUMP)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
|
||||
// Remove read/write protection
|
||||
|
@ -24,9 +24,10 @@ game::dvar_t* cl_exploit;
|
||||
* On the server side the msg_t structure processed as follows:
|
||||
* The first 4 bytes are read but not processed (offset 0)
|
||||
* The following 2 bytes are read but not processed (offset 4)
|
||||
* The following 1 byte is read and corresponds to the client_t.serverId (offset 6)
|
||||
* The following 4 bytes are read and correspond to the client_t.messageAcknowledge (offset 7)
|
||||
* The following 4 bytes are read and correspond to the client_t.reliableAcknowledge (offset 11)
|
||||
* The following 1 byte is read and corresponds to the client_t.serverId (offset
|
||||
* 6) The following 4 bytes are read and correspond to the
|
||||
* client_t.messageAcknowledge (offset 7) The following 4 bytes are read and
|
||||
* correspond to the client_t.reliableAcknowledge (offset 11)
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -80,8 +81,12 @@ public:
|
||||
add_exploit_commands();
|
||||
add_key_hooks();
|
||||
|
||||
utils::hook(0x420B76, write_message_sequence, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x420B86, write_command_sequence, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x420B76, HOOK_CAST(write_message_sequence), HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
utils::hook(0x420B86, HOOK_CAST(write_command_sequence), HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -41,7 +41,9 @@ void cl_key_event_stub(game::LocalClientNum_t local_client, int key_id,
|
||||
class component final : public component_interface {
|
||||
public:
|
||||
void post_unpack() override {
|
||||
utils::hook(0x53CC70, cl_key_event_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x53CC70, HOOK_CAST(cl_key_event_stub), HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
}
|
||||
};
|
||||
} // namespace key_catcher
|
||||
|
@ -102,17 +102,13 @@ public:
|
||||
void post_unpack() override {
|
||||
add_network_commands();
|
||||
|
||||
utils::hook(0x5B27E1, packet_interception_handler, HOOK_CALL)
|
||||
.install()
|
||||
utils::hook(0x5B27E1, HOOK_CAST(packet_interception_handler), HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
}
|
||||
|
||||
private:
|
||||
static void add_network_commands() {
|
||||
on_packet("naughty_reply", [](const game::netadr_s&, const std::string&) {
|
||||
utils::nt::raise_hard_exception();
|
||||
});
|
||||
}
|
||||
static void add_network_commands() {}
|
||||
};
|
||||
} // namespace network
|
||||
|
||||
|
@ -39,7 +39,9 @@ class component final : public component_interface {
|
||||
utils::hook(0x4E470D, get_com_max_fps, HOOK_JUMP).install()->quick();
|
||||
utils::hook::nop(0x4E4712, 4);
|
||||
|
||||
utils::hook(0x6EA960, bd_log_message_stub, HOOK_JUMP).install()->quick();
|
||||
utils::hook(0x6EA960, HOOK_CAST(bd_log_message_stub), HOOK_JUMP)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
|
||||
// Another meme
|
||||
static const auto* my_cg_fov = game::Dvar_RegisterFloat(
|
||||
|
@ -45,11 +45,11 @@ public:
|
||||
void post_start() override { remove_tekno_hooks(); }
|
||||
|
||||
void post_unpack() override {
|
||||
utils::hook(0x4E3D42, msg_read_bits_compress_check_sv, HOOK_CALL)
|
||||
.install()
|
||||
utils::hook(0x4E3D42, HOOK_CAST(msg_read_bits_compress_check_sv), HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
utils::hook(0x4A9F56, msg_read_bits_compress_check_cl, HOOK_CALL)
|
||||
.install()
|
||||
utils::hook(0x4A9F56, HOOK_CAST(msg_read_bits_compress_check_cl), HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
}
|
||||
|
||||
|
@ -20,9 +20,8 @@ using task_list = std::vector<task>;
|
||||
class task_pipeline {
|
||||
public:
|
||||
void add(task&& task) {
|
||||
new_callbacks_.access([&task, this](task_list& tasks) {
|
||||
tasks.emplace_back(std::move(task));
|
||||
});
|
||||
new_callbacks_.access(
|
||||
[&task](task_list& tasks) { tasks.emplace_back(std::move(task)); });
|
||||
}
|
||||
|
||||
void clear() {
|
||||
@ -143,9 +142,15 @@ public:
|
||||
}
|
||||
});
|
||||
|
||||
utils::hook(0x4E4A0D, cl_frame_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x5B54D2, r_end_frame_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x543B0E, main_frame_stub, HOOK_CALL).install()->quick();
|
||||
utils::hook(0x4E4A0D, HOOK_CAST(cl_frame_stub), HOOK_CALL)
|
||||
.install()
|
||||
->quick();
|
||||
utils::hook(0x5B54D2, HOOK_CAST(r_end_frame_stub), HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
utils::hook(0x543B0E, HOOK_CAST(main_frame_stub), HOOK_CALL)
|
||||
.install() // hook*
|
||||
->quick();
|
||||
}
|
||||
|
||||
void pre_destroy() override {
|
||||
|
@ -5,10 +5,9 @@ ScreenPlacement* ScrPlace_GetUnsafeFullPlacement() {
|
||||
return scrPlaceFullUnsafe;
|
||||
}
|
||||
|
||||
static DWORD Dvar_SetVariant_t = 0x649170;
|
||||
void __declspec(naked) Dvar_SetVariant(dvar_t* /*dvar*/, DvarValue /*value*/,
|
||||
DvarSetSource /*source*/) {
|
||||
static DWORD func = 0x649170;
|
||||
|
||||
__asm {
|
||||
pushad
|
||||
|
||||
@ -18,7 +17,7 @@ void __declspec(naked) Dvar_SetVariant(dvar_t* /*dvar*/, DvarValue /*value*/,
|
||||
push [esp + 0x20 + 0x18] // value
|
||||
push [esp + 0x20 + 0x18] // value
|
||||
push [esp + 0x20 + 0x18] // value
|
||||
call func
|
||||
call Dvar_SetVariant_t
|
||||
add esp, 0x14
|
||||
|
||||
popad
|
||||
|
@ -5,6 +5,8 @@
|
||||
#define HOOK_JUMP true
|
||||
#define HOOK_CALL false
|
||||
|
||||
#define HOOK_CAST(f) reinterpret_cast<void*>(f)
|
||||
|
||||
namespace utils {
|
||||
class hook final {
|
||||
public:
|
||||
|
@ -191,14 +191,6 @@ void** library::get_iat_entry(const std::string& module_name,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void raise_hard_exception() {
|
||||
int data = false;
|
||||
const library ntdll("ntdll.dll");
|
||||
ntdll.invoke_pascal<void>("RtlAdjustPrivilege", 19, true, false, &data);
|
||||
ntdll.invoke_pascal<void>("NtRaiseHardError", 0xC000007B, 0, nullptr, nullptr,
|
||||
6, &data);
|
||||
}
|
||||
|
||||
std::string load_resource(const int id) {
|
||||
auto* const res = FindResource(library(), MAKEINTRESOURCE(id), RT_RCDATA);
|
||||
if (!res)
|
||||
|
@ -50,39 +50,14 @@ public:
|
||||
|
||||
template <typename T> T get_proc(const std::string& process) const {
|
||||
if (!this->is_valid())
|
||||
T{};
|
||||
return T{};
|
||||
return reinterpret_cast<T>(GetProcAddress(this->module_, process.data()));
|
||||
}
|
||||
|
||||
template <typename T> std::function<T> get(const std::string& process) const {
|
||||
if (!this->is_valid())
|
||||
return std::function<T>();
|
||||
return static_cast<T*>(this->get_proc<void*>(process));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
T invoke(const std::string& process, Args... args) const {
|
||||
auto method = this->get<T(__cdecl)(Args...)>(process);
|
||||
if (method)
|
||||
return method(args...);
|
||||
return T();
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
T invoke_pascal(const std::string& process, Args... args) const {
|
||||
auto method = this->get<T(__stdcall)(Args...)>(process);
|
||||
if (method)
|
||||
return method(args...);
|
||||
return T();
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
T invoke_this(const std::string& process, void* this_ptr,
|
||||
Args... args) const {
|
||||
auto method = this->get<T(__thiscall)(void*, Args...)>(this_ptr, process);
|
||||
if (method)
|
||||
return method(args...);
|
||||
return T();
|
||||
return reinterpret_cast<T*>(this->get_proc<void*>(process));
|
||||
}
|
||||
|
||||
std::vector<PIMAGE_SECTION_HEADER> get_section_headers() const;
|
||||
@ -98,9 +73,8 @@ private:
|
||||
HMODULE module_;
|
||||
};
|
||||
|
||||
__declspec(noreturn) void raise_hard_exception();
|
||||
std::string load_resource(int id);
|
||||
|
||||
void relaunch_self();
|
||||
__declspec(noreturn) void terminate(uint32_t code = 0);
|
||||
void terminate(uint32_t code = 0);
|
||||
} // namespace utils::nt
|
||||
|
@ -1,191 +0,0 @@
|
||||
#include "signature.hpp"
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
namespace utils::hook {
|
||||
void signature::load_pattern(const std::string& pattern) {
|
||||
this->mask_.clear();
|
||||
this->pattern_.clear();
|
||||
|
||||
uint8_t nibble = 0;
|
||||
auto has_nibble = false;
|
||||
|
||||
for (auto val : pattern) {
|
||||
if (val == ' ')
|
||||
continue;
|
||||
if (val == '?') {
|
||||
this->mask_.push_back(val);
|
||||
this->pattern_.push_back(0);
|
||||
} else {
|
||||
if ((val < '0' || val > '9') && (val < 'A' || val > 'F') &&
|
||||
(val < 'a' || val > 'f')) {
|
||||
throw std::runtime_error("Invalid pattern");
|
||||
}
|
||||
|
||||
char str[] = {val, 0};
|
||||
const auto current_nibble =
|
||||
static_cast<uint8_t>(strtol(str, nullptr, 16));
|
||||
|
||||
if (!has_nibble) {
|
||||
has_nibble = true;
|
||||
nibble = current_nibble;
|
||||
} else {
|
||||
has_nibble = false;
|
||||
const uint8_t byte = current_nibble | (nibble << 4);
|
||||
|
||||
this->mask_.push_back('x');
|
||||
this->pattern_.push_back(byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!this->mask_.empty() && this->mask_.back() == '?') {
|
||||
this->mask_.pop_back();
|
||||
this->pattern_.pop_back();
|
||||
}
|
||||
|
||||
if (this->has_sse_support()) {
|
||||
while (this->pattern_.size() < 16) {
|
||||
this->pattern_.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (has_nibble) {
|
||||
throw std::runtime_error("Invalid pattern");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<size_t> signature::process_range(uint8_t* start,
|
||||
const size_t length) const {
|
||||
if (this->has_sse_support())
|
||||
return this->process_range_vectorized(start, length);
|
||||
return this->process_range_linear(start, length);
|
||||
}
|
||||
|
||||
std::vector<size_t> signature::process_range_linear(uint8_t* start,
|
||||
const size_t length) const {
|
||||
std::vector<size_t> result;
|
||||
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
const auto address = start + i;
|
||||
|
||||
size_t j = 0;
|
||||
for (; j < this->mask_.size(); ++j) {
|
||||
if (this->mask_[j] != '?' && this->pattern_[j] != address[j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == this->mask_.size()) {
|
||||
result.push_back(size_t(address));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<size_t>
|
||||
signature::process_range_vectorized(uint8_t* start, const size_t length) const {
|
||||
std::vector<size_t> result;
|
||||
__declspec(align(16)) char desired_mask[16] = {0};
|
||||
|
||||
for (size_t i = 0; i < this->mask_.size(); i++) {
|
||||
desired_mask[i / 8] |= (this->mask_[i] == '?' ? 0 : 1) << i % 8;
|
||||
}
|
||||
|
||||
const auto mask =
|
||||
_mm_load_si128(reinterpret_cast<const __m128i*>(desired_mask));
|
||||
const auto comparand =
|
||||
_mm_loadu_si128(reinterpret_cast<const __m128i*>(this->pattern_.data()));
|
||||
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
const auto address = start + i;
|
||||
const auto value =
|
||||
_mm_loadu_si128(reinterpret_cast<const __m128i*>(address));
|
||||
const auto comparison =
|
||||
_mm_cmpestrm(value, 16, comparand, static_cast<int>(this->mask_.size()),
|
||||
_SIDD_CMP_EQUAL_EACH);
|
||||
|
||||
const auto matches = _mm_and_si128(mask, comparison);
|
||||
const auto equivalence = _mm_xor_si128(mask, matches);
|
||||
|
||||
if (_mm_test_all_zeros(equivalence, equivalence)) {
|
||||
result.push_back(size_t(address));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
signature::signature_result signature::process() const {
|
||||
const auto range = this->length_ - this->mask_.size();
|
||||
const auto cores = std::max(1u, std::thread::hardware_concurrency());
|
||||
|
||||
if (range <= cores * 10ull)
|
||||
return this->process_serial();
|
||||
return this->process_parallel();
|
||||
}
|
||||
|
||||
signature::signature_result signature::process_serial() const {
|
||||
const auto sub = this->has_sse_support() ? 16 : this->mask_.size();
|
||||
return {this->process_range(this->start_, this->length_ - sub)};
|
||||
}
|
||||
|
||||
signature::signature_result signature::process_parallel() const {
|
||||
const auto sub = this->has_sse_support() ? 16 : this->mask_.size();
|
||||
const auto range = this->length_ - sub;
|
||||
const auto cores = std::max(1u, std::thread::hardware_concurrency() / 2);
|
||||
// Only use half of the available cores
|
||||
const auto grid = range / cores;
|
||||
|
||||
std::mutex mutex;
|
||||
std::vector<size_t> result;
|
||||
std::vector<std::thread> threads;
|
||||
|
||||
for (auto i = 0u; i < cores; ++i) {
|
||||
const auto start = this->start_ + (grid * i);
|
||||
const auto length =
|
||||
(i + 1 == cores) ? (this->start_ + this->length_ - sub) - start : grid;
|
||||
threads.emplace_back([&, start, length]() {
|
||||
auto local_result = this->process_range(start, length);
|
||||
if (local_result.empty())
|
||||
return;
|
||||
|
||||
std::lock_guard _(mutex);
|
||||
for (const auto& address : local_result) {
|
||||
result.push_back(address);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (auto& t : threads) {
|
||||
if (t.joinable()) {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(result.begin(), result.end());
|
||||
return {std::move(result)};
|
||||
}
|
||||
|
||||
bool signature::has_sse_support() const {
|
||||
if (this->mask_.size() <= 16) {
|
||||
int cpu_id[4];
|
||||
__cpuid(cpu_id, 0);
|
||||
|
||||
if (cpu_id[0] >= 1) {
|
||||
__cpuidex(cpu_id, 1, 0);
|
||||
return (cpu_id[2] & (1 << 20)) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
} // namespace utils::hook
|
||||
|
||||
utils::hook::signature::signature_result operator"" _sig(const char* str,
|
||||
const size_t len) {
|
||||
return utils::hook::signature(std::string(str, len)).process();
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
#pragma once
|
||||
#include "nt.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace utils::hook {
|
||||
class signature final {
|
||||
public:
|
||||
class signature_result {
|
||||
public:
|
||||
signature_result(std::vector<size_t>&& matches)
|
||||
: matches_(std::move(matches)) {}
|
||||
|
||||
[[nodiscard]] uint8_t* get(const size_t index) const {
|
||||
if (index >= this->count()) {
|
||||
throw std::runtime_error("Invalid index");
|
||||
}
|
||||
|
||||
return reinterpret_cast<uint8_t*>(this->matches_[index]);
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t count() const { return this->matches_.size(); }
|
||||
|
||||
private:
|
||||
std::vector<size_t> matches_;
|
||||
};
|
||||
|
||||
explicit signature(const std::string& pattern, const nt::library library = {})
|
||||
: signature(pattern, library.get_ptr(),
|
||||
library.get_optional_header()->SizeOfImage) {}
|
||||
|
||||
signature(const std::string& pattern, void* start, void* end)
|
||||
: signature(pattern, start, size_t(end) - size_t(start)) {}
|
||||
|
||||
signature(const std::string& pattern, void* start, const size_t length)
|
||||
: start_(static_cast<uint8_t*>(start)), length_(length) {
|
||||
this->load_pattern(pattern);
|
||||
}
|
||||
|
||||
signature_result process() const;
|
||||
|
||||
private:
|
||||
std::string mask_;
|
||||
std::basic_string<uint8_t> pattern_;
|
||||
|
||||
uint8_t* start_;
|
||||
size_t length_;
|
||||
|
||||
void load_pattern(const std::string& pattern);
|
||||
|
||||
signature_result process_parallel() const;
|
||||
signature_result process_serial() const;
|
||||
std::vector<size_t> process_range(uint8_t* start, size_t length) const;
|
||||
std::vector<size_t> process_range_linear(uint8_t* start, size_t length) const;
|
||||
std::vector<size_t> process_range_vectorized(uint8_t* start,
|
||||
size_t length) const;
|
||||
|
||||
bool has_sse_support() const;
|
||||
};
|
||||
} // namespace utils::hook
|
||||
|
||||
utils::hook::signature::signature_result operator"" _sig(const char* str,
|
||||
size_t len);
|
Loading…
x
Reference in New Issue
Block a user