mirror of
https://github.com/diamante0018/MW3ServerFreezer.git
synced 2025-04-19 19:52:53 +00:00
feat: compile project with clang (with vs on Windows)
This commit is contained in:
parent
779676b8ee
commit
b3841d855e
13
premake5.lua
13
premake5.lua
@ -61,8 +61,15 @@ filter "configurations:release"
|
|||||||
optimize "Size"
|
optimize "Size"
|
||||||
defines {"NDEBUG"}
|
defines {"NDEBUG"}
|
||||||
flags {"FatalCompileWarnings"}
|
flags {"FatalCompileWarnings"}
|
||||||
buildoptions {"/GL"}
|
|
||||||
linkoptions {"/IGNORE:4702", "/LTCG"}
|
filter "action:msc"
|
||||||
|
buildoptions "/GL"
|
||||||
|
linkoptions {"/IGNORE:4702", "/LTCG"}
|
||||||
|
filter {}
|
||||||
|
|
||||||
|
filter "toolset:not msc*"
|
||||||
|
buildoptions "-Wno-unused-parameter"
|
||||||
|
filter {}
|
||||||
filter {}
|
filter {}
|
||||||
|
|
||||||
filter "configurations:debug"
|
filter "configurations:debug"
|
||||||
@ -91,8 +98,6 @@ targetname "mw3-server-freezer"
|
|||||||
pchheader "std_include.hpp"
|
pchheader "std_include.hpp"
|
||||||
pchsource "src/client/std_include.cpp"
|
pchsource "src/client/std_include.cpp"
|
||||||
|
|
||||||
linkoptions {"/PDBCompress"}
|
|
||||||
|
|
||||||
files {"./src/client/**.hpp", "./src/client/**.cpp"}
|
files {"./src/client/**.hpp", "./src/client/**.cpp"}
|
||||||
|
|
||||||
includedirs {"./src/client", "./src/common", "%{prj.location}/src"}
|
includedirs {"./src/client", "./src/common", "%{prj.location}/src"}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
|
|
||||||
constexpr auto CMD_MAX_NESTING = 8;
|
[[maybe_unused]] constexpr auto CMD_MAX_NESTING = 8;
|
||||||
|
|
||||||
namespace command {
|
namespace command {
|
||||||
std::unordered_map<std::string, std::function<void(params&)>> handlers;
|
std::unordered_map<std::string, std::function<void(params&)>> handlers;
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void post_unpack() override {
|
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();
|
this->initialize();
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,15 @@ void dvar_override_cheat_protection_stub(bool /*cheat_override*/) {
|
|||||||
class component final : public component_interface {
|
class component final : public component_interface {
|
||||||
public:
|
public:
|
||||||
void post_unpack() override {
|
void post_unpack() override {
|
||||||
utils::hook(0x59C0EF, dvar_set_from_string_by_name_stub, HOOK_CALL)
|
utils::hook(0x59C0EF, HOOK_CAST(dvar_set_from_string_by_name_stub),
|
||||||
.install()
|
HOOK_CALL)
|
||||||
|
.install() // hook*
|
||||||
->quick();
|
->quick();
|
||||||
|
|
||||||
*game::isCheatOverride = true;
|
*game::isCheatOverride = true;
|
||||||
utils::hook(0x482CC0, dvar_override_cheat_protection_stub, HOOK_JUMP)
|
utils::hook(0x482CC0, HOOK_CAST(dvar_override_cheat_protection_stub),
|
||||||
.install()
|
HOOK_JUMP)
|
||||||
|
.install() // hook*
|
||||||
->quick();
|
->quick();
|
||||||
|
|
||||||
// Remove read/write protection
|
// Remove read/write protection
|
||||||
|
@ -24,9 +24,10 @@ game::dvar_t* cl_exploit;
|
|||||||
* On the server side the msg_t structure processed as follows:
|
* On the server side the msg_t structure processed as follows:
|
||||||
* The first 4 bytes are read but not processed (offset 0)
|
* The first 4 bytes are read but not processed (offset 0)
|
||||||
* The following 2 bytes are read but not processed (offset 4)
|
* 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 1 byte is read and corresponds to the client_t.serverId (offset
|
||||||
* The following 4 bytes are read and correspond to the client_t.messageAcknowledge (offset 7)
|
* 6) The following 4 bytes are read and correspond to the
|
||||||
* The following 4 bytes are read and correspond to the client_t.reliableAcknowledge (offset 11)
|
* 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_exploit_commands();
|
||||||
add_key_hooks();
|
add_key_hooks();
|
||||||
|
|
||||||
utils::hook(0x420B76, write_message_sequence, HOOK_CALL).install()->quick();
|
utils::hook(0x420B76, HOOK_CAST(write_message_sequence), HOOK_CALL)
|
||||||
utils::hook(0x420B86, write_command_sequence, HOOK_CALL).install()->quick();
|
.install() // hook*
|
||||||
|
->quick();
|
||||||
|
utils::hook(0x420B86, HOOK_CAST(write_command_sequence), HOOK_CALL)
|
||||||
|
.install() // hook*
|
||||||
|
->quick();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -41,7 +41,9 @@ void cl_key_event_stub(game::LocalClientNum_t local_client, int key_id,
|
|||||||
class component final : public component_interface {
|
class component final : public component_interface {
|
||||||
public:
|
public:
|
||||||
void post_unpack() override {
|
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
|
} // namespace key_catcher
|
||||||
|
@ -102,17 +102,13 @@ public:
|
|||||||
void post_unpack() override {
|
void post_unpack() override {
|
||||||
add_network_commands();
|
add_network_commands();
|
||||||
|
|
||||||
utils::hook(0x5B27E1, packet_interception_handler, HOOK_CALL)
|
utils::hook(0x5B27E1, HOOK_CAST(packet_interception_handler), HOOK_CALL)
|
||||||
.install()
|
.install() // hook*
|
||||||
->quick();
|
->quick();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void add_network_commands() {
|
static void add_network_commands() {}
|
||||||
on_packet("naughty_reply", [](const game::netadr_s&, const std::string&) {
|
|
||||||
utils::nt::raise_hard_exception();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
} // namespace network
|
} // 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(0x4E470D, get_com_max_fps, HOOK_JUMP).install()->quick();
|
||||||
utils::hook::nop(0x4E4712, 4);
|
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
|
// Another meme
|
||||||
static const auto* my_cg_fov = game::Dvar_RegisterFloat(
|
static const auto* my_cg_fov = game::Dvar_RegisterFloat(
|
||||||
|
@ -45,11 +45,11 @@ public:
|
|||||||
void post_start() override { remove_tekno_hooks(); }
|
void post_start() override { remove_tekno_hooks(); }
|
||||||
|
|
||||||
void post_unpack() override {
|
void post_unpack() override {
|
||||||
utils::hook(0x4E3D42, msg_read_bits_compress_check_sv, HOOK_CALL)
|
utils::hook(0x4E3D42, HOOK_CAST(msg_read_bits_compress_check_sv), HOOK_CALL)
|
||||||
.install()
|
.install() // hook*
|
||||||
->quick();
|
->quick();
|
||||||
utils::hook(0x4A9F56, msg_read_bits_compress_check_cl, HOOK_CALL)
|
utils::hook(0x4A9F56, HOOK_CAST(msg_read_bits_compress_check_cl), HOOK_CALL)
|
||||||
.install()
|
.install() // hook*
|
||||||
->quick();
|
->quick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,9 +20,8 @@ using task_list = std::vector<task>;
|
|||||||
class task_pipeline {
|
class task_pipeline {
|
||||||
public:
|
public:
|
||||||
void add(task&& task) {
|
void add(task&& task) {
|
||||||
new_callbacks_.access([&task, this](task_list& tasks) {
|
new_callbacks_.access(
|
||||||
tasks.emplace_back(std::move(task));
|
[&task](task_list& tasks) { tasks.emplace_back(std::move(task)); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
@ -143,9 +142,15 @@ public:
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
utils::hook(0x4E4A0D, cl_frame_stub, HOOK_CALL).install()->quick();
|
utils::hook(0x4E4A0D, HOOK_CAST(cl_frame_stub), HOOK_CALL)
|
||||||
utils::hook(0x5B54D2, r_end_frame_stub, HOOK_CALL).install()->quick();
|
.install()
|
||||||
utils::hook(0x543B0E, main_frame_stub, HOOK_CALL).install()->quick();
|
->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 {
|
void pre_destroy() override {
|
||||||
|
@ -5,10 +5,9 @@ ScreenPlacement* ScrPlace_GetUnsafeFullPlacement() {
|
|||||||
return scrPlaceFullUnsafe;
|
return scrPlaceFullUnsafe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD Dvar_SetVariant_t = 0x649170;
|
||||||
void __declspec(naked) Dvar_SetVariant(dvar_t* /*dvar*/, DvarValue /*value*/,
|
void __declspec(naked) Dvar_SetVariant(dvar_t* /*dvar*/, DvarValue /*value*/,
|
||||||
DvarSetSource /*source*/) {
|
DvarSetSource /*source*/) {
|
||||||
static DWORD func = 0x649170;
|
|
||||||
|
|
||||||
__asm {
|
__asm {
|
||||||
pushad
|
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
|
push [esp + 0x20 + 0x18] // value
|
||||||
push [esp + 0x20 + 0x18] // value
|
push [esp + 0x20 + 0x18] // value
|
||||||
call func
|
call Dvar_SetVariant_t
|
||||||
add esp, 0x14
|
add esp, 0x14
|
||||||
|
|
||||||
popad
|
popad
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#define HOOK_JUMP true
|
#define HOOK_JUMP true
|
||||||
#define HOOK_CALL false
|
#define HOOK_CALL false
|
||||||
|
|
||||||
|
#define HOOK_CAST(f) reinterpret_cast<void*>(f)
|
||||||
|
|
||||||
namespace utils {
|
namespace utils {
|
||||||
class hook final {
|
class hook final {
|
||||||
public:
|
public:
|
||||||
|
@ -191,14 +191,6 @@ void** library::get_iat_entry(const std::string& module_name,
|
|||||||
return nullptr;
|
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) {
|
std::string load_resource(const int id) {
|
||||||
auto* const res = FindResource(library(), MAKEINTRESOURCE(id), RT_RCDATA);
|
auto* const res = FindResource(library(), MAKEINTRESOURCE(id), RT_RCDATA);
|
||||||
if (!res)
|
if (!res)
|
||||||
|
@ -50,39 +50,14 @@ public:
|
|||||||
|
|
||||||
template <typename T> T get_proc(const std::string& process) const {
|
template <typename T> T get_proc(const std::string& process) const {
|
||||||
if (!this->is_valid())
|
if (!this->is_valid())
|
||||||
T{};
|
return T{};
|
||||||
return reinterpret_cast<T>(GetProcAddress(this->module_, process.data()));
|
return reinterpret_cast<T>(GetProcAddress(this->module_, process.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> std::function<T> get(const std::string& process) const {
|
template <typename T> std::function<T> get(const std::string& process) const {
|
||||||
if (!this->is_valid())
|
if (!this->is_valid())
|
||||||
return std::function<T>();
|
return std::function<T>();
|
||||||
return static_cast<T*>(this->get_proc<void*>(process));
|
return reinterpret_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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<PIMAGE_SECTION_HEADER> get_section_headers() const;
|
std::vector<PIMAGE_SECTION_HEADER> get_section_headers() const;
|
||||||
@ -98,9 +73,8 @@ private:
|
|||||||
HMODULE module_;
|
HMODULE module_;
|
||||||
};
|
};
|
||||||
|
|
||||||
__declspec(noreturn) void raise_hard_exception();
|
|
||||||
std::string load_resource(int id);
|
std::string load_resource(int id);
|
||||||
|
|
||||||
void relaunch_self();
|
void relaunch_self();
|
||||||
__declspec(noreturn) void terminate(uint32_t code = 0);
|
void terminate(uint32_t code = 0);
|
||||||
} // namespace utils::nt
|
} // 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