aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile14
-rw-r--r--README.md2
-rw-r--r--driver-kmem.cpp62
-rw-r--r--ht2.bat27
-rw-r--r--hunt.cpp13
-rw-r--r--hunt2.cpp204
-rw-r--r--memory.cpp71
-rw-r--r--memory.hpp47
8 files changed, 435 insertions, 5 deletions
diff --git a/Makefile b/Makefile
index 01fcaec..4466fb7 100644
--- a/Makefile
+++ b/Makefile
@@ -20,19 +20,25 @@ HUNT_NAME = ht
HUNT_OBJECTS = hunt.o memory.o
HUNT_TARGET = $(HUNT_NAME).sys
+HUNT1896_NAME = ht2
+HUNT1896_OBJECTS = hunt2.o memory.o
+HUNT1896_TARGET = $(HUNT1896_NAME).sys
+
BF4_NAME = bf4
BF4_OBJECTS = bf4.o memory.o
BF4_TARGET = $(BF4_NAME).sys
-all: $(DRIVER_TARGET) $(TARKOV_TARGET) $(HUNT_TARGET) $(BF4_TARGET)
+all: $(DRIVER_TARGET) $(TARKOV_TARGET) $(HUNT_TARGET) $(HUNT1896_TARGET) $(BF4_TARGET)
-install: $(DRIVER_TARGET) $(TARKOV_TARGET) $(HUNT_TARGET) $(BF4_TARGET)
+install: $(DRIVER_TARGET) $(TARKOV_TARGET) $(HUNT_TARGET) $(HUNT1896_TARGET) $(BF4_TARGET)
$(call INSTALL_EXEC_SIGN,$(DRIVER_TARGET))
$(INSTALL) $(DRIVER_NAME).bat $(DESTDIR)
$(call INSTALL_EXEC_SIGN,$(TARKOV_TARGET))
$(INSTALL) $(TARKOV_NAME).bat $(DESTDIR)
$(call INSTALL_EXEC_SIGN,$(HUNT_TARGET))
$(INSTALL) $(HUNT_NAME).bat $(DESTDIR)
+ $(call INSTALL_EXEC_SIGN,$(HUNT1896_TARGET))
+ $(INSTALL) $(HUNT1896_NAME).bat $(DESTDIR)
$(call INSTALL_EXEC_SIGN,$(BF4_TARGET))
$(INSTALL) $(BF4_NAME).bat $(DESTDIR)
@@ -40,6 +46,7 @@ clean:
rm -f $(DRIVER_OBJECTS) $(DRIVER_TARGET)
rm -f $(TARKOV_OBJECTS) $(TARKOV_TARGET)
rm -f $(HUNT_OBJECTS) $(HUNT_TARGET)
+ rm -f $(HUNT1896_OBJECTS) $(HUNT1896_TARGET)
rm -f $(BF4_OBJECTS) $(BF4_TARGET)
memory-experimental.o: memory.cpp
@@ -57,6 +64,9 @@ $(TARKOV_TARGET): $(TARKOV_OBJECTS)
$(HUNT_TARGET): $(HUNT_OBJECTS)
$(call LINK_CPP_KERNEL_TARGET,$(HUNT_OBJECTS),$@)
+$(HUNT1896_TARGET): $(HUNT1896_OBJECTS)
+ $(call LINK_CPP_KERNEL_TARGET,$(HUNT1896_OBJECTS),$@)
+
$(BF4_TARGET): $(BF4_OBJECTS)
$(call LINK_CPP_KERNEL_TARGET,$(BF4_OBJECTS),$@)
diff --git a/README.md b/README.md
index 3d87666..2b1e9c5 100644
--- a/README.md
+++ b/README.md
@@ -34,4 +34,6 @@ Yet another game hack that does nothing but:
## Hunt: Showdown (ht.sys)
+This cheat won't work after 2024-08-15 (CryEngine 5.11 update).
+
* chams
diff --git a/driver-kmem.cpp b/driver-kmem.cpp
index 60f7374..3b8fafe 100644
--- a/driver-kmem.cpp
+++ b/driver-kmem.cpp
@@ -17,6 +17,53 @@ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject,
UNREFERENCED_PARAMETER(DriverObject);
UNREFERENCED_PARAMETER(RegistryPath);
+ const eastl::array<uint8_t, 10> buffer = {0x41, 0xDE, 0xAD, 0xC0, 0xDE,
+ 0xCA, 0xFE, 0xCA, 0xFE, 0x41};
+ const eastl::array<uint8_t, 2> pattern_00 = {0xCA, 0xFE};
+ const eastl::array<uint8_t, 2> pattern_01 = {0xFE, 0x41};
+ const eastl::array<uint8_t, 1> pattern_02 = {0x41};
+ const eastl::array<uint8_t, 10> pattern_03 = {0x41, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x41};
+ eastl::vector<size_t> found_offsets;
+
+ auto found = PatternScanner::SearchWithMask(
+ buffer.data(), eastl::size(buffer), pattern_00.data(),
+ eastl::size(pattern_00), "xx", found_offsets);
+ if (!found) {
+ DbgPrint("%s\n", "First pattern not found!");
+ return STATUS_UNSUCCESSFUL;
+ }
+ found = PatternScanner::SearchWithMask(
+ buffer.data(), eastl::size(buffer), pattern_01.data(),
+ eastl::size(pattern_01), "xx", found_offsets);
+ if (!found) {
+ DbgPrint("%s\n", "Second pattern not found!");
+ return STATUS_UNSUCCESSFUL;
+ }
+ found = PatternScanner::SearchWithMask(
+ buffer.data(), eastl::size(buffer), pattern_02.data(),
+ eastl::size(pattern_02), "x", found_offsets);
+ if (!found) {
+ DbgPrint("%s\n", "Third pattern not found!");
+ return STATUS_UNSUCCESSFUL;
+ }
+ found = PatternScanner::SearchWithMask(buffer, pattern_03, "x????????x",
+ found_offsets);
+ if (!found) {
+ DbgPrint("%s\n", "Fourth pattern not found!");
+ return STATUS_UNSUCCESSFUL;
+ }
+ found = PatternScanner::SearchWithMask(
+ buffer, {0xDE, 0xAD, 0x00, 0x00, 0x00, 0x00, 0xCA, 0xFE}, "xx????xx",
+ found_offsets);
+ if (!found) {
+ DbgPrint("%s\n", "Fifth pattern not found!");
+ return STATUS_UNSUCCESSFUL;
+ }
+ for (const auto offset : found_offsets) {
+ DbgPrint("Offset: %zu\n", offset);
+ }
+
DbgPrint("%s\n", "Starting thread..");
auto args = eastl::make_shared<ThreadArgs>();
thread.Start(
@@ -156,9 +203,24 @@ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject,
DbgPrint("%s\n", page.toString().c_str());
}
+ PatternScanner::ProcessModule scanner(pep, obj, {0x4D, 0x5A, 0x90},
+ "xxx");
+ eastl::vector<size_t> results;
+ auto found = scanner.Scan(L"Explorer.EXE", results);
+ if (!found)
+ DbgPrint("%s\n", "PatternScanner::ProcessModule was unsuccessful");
+ if (results.size() != 1)
+ DbgPrint(
+ "PatternScanner::ProcessModule was unsuccessful: %zu results\n",
+ results.size());
+ else
+ DbgPrint("PatternScanner::ProcessModule found address for 'MZ\\x90': %p\n", results[0]);
+
::CloseProcess(&pep, &obj);
}
+ DbgPrint("%s\n", "Done.");
+
return STATUS_SUCCESS;
},
args);
diff --git a/ht2.bat b/ht2.bat
new file mode 100644
index 0000000..ebe6275
--- /dev/null
+++ b/ht2.bat
@@ -0,0 +1,27 @@
+@echo off
+set SERVICE_NAME=ht2
+set DRIVER="%~dp0\ht2.sys"
+
+net session >nul 2>&1
+if NOT %ERRORLEVEL% EQU 0 (
+ echo ERROR: This script requires Administrator privileges!
+ pause
+ exit /b 1
+)
+
+echo ---------------------------------------
+echo -- Service Name: %SERVICE_NAME%
+echo -- Driver......: %DRIVER%
+echo ---------------------------------------
+
+sc create %SERVICE_NAME% binPath= %DRIVER% type= kernel
+echo ---------------------------------------
+sc start %SERVICE_NAME%
+echo ---------------------------------------
+sc query %SERVICE_NAME%
+echo [PRESS A KEY TO STOP THE DRIVER]
+pause
+sc stop %SERVICE_NAME%
+sc delete %SERVICE_NAME%
+echo Done.
+timeout /t 3
diff --git a/hunt.cpp b/hunt.cpp
index c1125cf..535526a 100644
--- a/hunt.cpp
+++ b/hunt.cpp
@@ -1,3 +1,6 @@
+/*
+ * Won't work after CryEngine 5.11 update (2024-08-15)
+ */
#include <ntddk.h>
#include <EASTL/array.h>
@@ -9,6 +12,9 @@
#include "memory.hpp"
#include "stringify.hpp"
+#define STRNCMP_CR(haystack, needle) \
+ (strncmp(haystack, skCrypt(needle), sizeof(needle) - 1))
+
using namespace DriverThread;
static Thread thread;
@@ -104,7 +110,7 @@ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject,
// Offsets stolen from: https://www.unknowncheats.me/forum/3809820-post343.html
Memory memory(pep);
- auto sys_global_env = memory.Read<uint64_t>(base + 0x5EF2FA0);
+ auto sys_global_env = memory.Read<uint64_t>(base + 0x5EFCF90);
auto entity_system = memory.Read<uint64_t>(sys_global_env + 0xA8);
uint16_t number_of_objects = memory.Read<uint16_t>(entity_system + 0x4006A);
@@ -120,8 +126,9 @@ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject,
char entity_name[128] = {};
memory.ReadString<sizeof(entity_name)>(entity_name_ptr, entity_name);
- if (strncmp(entity_name, skCrypt("ShootingRange_Target"), sizeof("ShootingRange_Target") - 1) == 0 ||
- strncmp(entity_name, skCrypt("HunterBasic"), sizeof("HunterBasic") - 1) == 0) {
+ if (STRNCMP_CR(entity_name, "ShootingRange_Target") == 0 ||
+ STRNCMP_CR(entity_name, "HunterBasic") == 0)
+ {
hunters++;
auto slots_ptr = memory.Read<uint64_t>(entity + 0xA8);
diff --git a/hunt2.cpp b/hunt2.cpp
new file mode 100644
index 0000000..4663973
--- /dev/null
+++ b/hunt2.cpp
@@ -0,0 +1,204 @@
+/*
+ * Won't work after CryEngine 5.11 update (2024-08-15)
+ */
+#include <ntddk.h>
+
+#include <EASTL/array.h>
+#include <EASTL/unordered_map.h>
+#include <eastl_compat.hpp>
+#include <except.h>
+#include <DriverThread.hpp>
+#include <obfuscate.hpp>
+
+#include "memory.hpp"
+#include "stringify.hpp"
+
+#define STRNCMP_CR(haystack, needle) \
+ (strncmp(haystack, skCrypt(needle), sizeof(needle) - 1))
+
+using namespace DriverThread;
+
+static Thread thread;
+static Event shutdown_event;
+static auto targetProcess = skCrypt(L"HuntGame.exe");
+static auto targetModule = skCrypt(L"GameHunt.dll");
+
+enum ColorType : uint32_t {
+ Pink = 0xFFA0FFFF,
+ Red = 0xFF000080,
+ Green = 0x00FF00FF,
+ Blue = 0x0000FF60,
+ Cyan = 0x00FFFFFF,
+ Orange = 0xFFA500FF,
+ Yellow = 0xFFFF0060,
+ White = 0xFFFFFFFF
+};
+
+static uint64_t SearchHuntProcess(void) {
+ const auto &procs = ::GetProcesses();
+ const auto &found = eastl::find_if(procs.begin(), procs.end(),
+ [](const auto &item) {
+ if (item.ProcessName == targetProcess)
+ return true;
+ return false;
+ });
+
+ if (found == procs.end()) {
+ return 0;
+ }
+
+ return found->UniqueProcessId;
+}
+
+extern "C" {
+DRIVER_INITIALIZE DriverEntry;
+DRIVER_UNLOAD DriverUnload;
+
+int mainloop_exception_handler(_In_ EXCEPTION_POINTERS * lpEP)
+{
+ (void)lpEP;
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT *DriverObject,
+ _In_ PUNICODE_STRING RegistryPath) {
+ UNREFERENCED_PARAMETER(DriverObject);
+ UNREFERENCED_PARAMETER(RegistryPath);
+
+ auto args = eastl::make_shared<ThreadArgs>();
+ thread.Start(
+ [](eastl::shared_ptr<ThreadArgs> args) {
+ UNREFERENCED_PARAMETER(args);
+
+ HANDLE hunt_pid = NULL;
+ PEPROCESS pep = NULL;
+ HANDLE obj = NULL;
+ uint64_t base = 0;
+ LONGLONG wait_timeout = (-1LL) * 10LL * 1000LL * 250LL;
+
+ DbgPrint("%s\n", "start");
+ __dpptry(mainloop_exception_handler, mainloop_seh) {
+ while (shutdown_event.Wait(wait_timeout) == STATUS_TIMEOUT) {
+ if (!hunt_pid) {
+ wait_timeout = (-1LL) * 10LL * 1000LL * 1000LL;
+ hunt_pid = reinterpret_cast<HANDLE>(SearchHuntProcess());
+ if (hunt_pid == NULL) {
+ continue;
+ }
+ DbgPrint(skCrypt("pid: %p\n"), hunt_pid);
+
+ if (!NT_SUCCESS(::OpenProcess(hunt_pid, &pep, &obj))) {
+ hunt_pid = NULL;
+ continue;
+ }
+
+ base = 0;
+ while (!base && hunt_pid) {
+ LARGE_INTEGER wait = {.QuadPart = (-1LL) * 10LL * 1000LL * 5000LL};
+ KeDelayExecutionThread(KernelMode, FALSE, &wait);
+
+ const auto mods = ::GetModules(pep, FALSE);
+ for (const auto &mod : mods) {
+ if (mod.BaseDllName == targetModule) {
+ base = mod.DllBase;
+ break;
+ }
+ }
+
+ hunt_pid = reinterpret_cast<HANDLE>(SearchHuntProcess());
+ }
+
+ if (!hunt_pid) {
+ LARGE_INTEGER wait = {.QuadPart = (-1LL) * 10LL * 1000LL * 5000LL};
+ KeDelayExecutionThread(KernelMode, FALSE, &wait);
+ ::CloseProcess(&pep, &obj);
+ continue;
+ }
+ }
+
+ // Offsets stolen from: https://www.unknowncheats.me/forum/other-fps-games/350352-hunt-showdown-51.html
+ Memory memory(pep);
+ auto sys_global_env = memory.Read<uint64_t>(base + 0x23582C0);
+
+ auto entity_system = memory.Read<uint64_t>(sys_global_env + 0xC0);
+ uint16_t number_of_objects = memory.Read<uint16_t>(entity_system + 0x40092);
+ uint64_t entity_list = entity_system + 0x40098;
+
+ for (decltype(number_of_objects) i = 0; i < number_of_objects; ++i) {
+ auto entity = memory.Read<uint64_t>(entity_list + i * sizeof(uint64_t));
+ if (!entity)
+ continue;
+
+ auto entity_name_ptr = memory.Read<uint64_t>(entity + 0x10);
+ char entity_name[128] = {};
+ memory.ReadString<sizeof(entity_name)>(entity_name_ptr, entity_name);
+
+ if (STRNCMP_CR(entity_name, "ShootingRange_Target") == 0 ||
+ STRNCMP_CR(entity_name, "HunterBasic") == 0)
+ {
+ auto slots_ptr = memory.Read<uint64_t>(entity + 0xA8);
+ auto slot_ptr = memory.Read<uint64_t>(slots_ptr + 0);
+ auto render_node_ptr = memory.Read<uint64_t>(slot_ptr + 0xA0);
+
+ auto rgba_color = memory.Read<uint32_t>(render_node_ptr + 0x2C);
+ if (rgba_color != ColorType::Cyan /* team */) {
+ memory.Write<uint32_t>(render_node_ptr + 0x10, 0x80018);
+ memory.Write<uint32_t>(render_node_ptr + 0x2C, ColorType::Pink);
+ }
+ } else if (STRNCMP_CR(entity_name, "Target_Butcher") == 0 ||
+ STRNCMP_CR(entity_name, "Target_Assassin") == 0 ||
+ STRNCMP_CR(entity_name, "Spider_target") == 0 ||
+ STRNCMP_CR(entity_name, "Target_Scrapbeak") == 0 ||
+ STRNCMP_CR(entity_name, "Grunts.specials") == 0 ||
+ STRNCMP_CR(entity_name, "immolator_el") == 0)
+ {
+ auto slots_ptr = memory.Read<uint64_t>(entity + 0xA8);
+ auto slot_ptr = memory.Read<uint64_t>(slots_ptr + 0);
+ auto render_node_ptr = memory.Read<uint64_t>(slot_ptr + 0xA0);
+
+ memory.Write<uint32_t>(render_node_ptr + 0x10, 0x80018);
+ memory.Write<uint32_t>(render_node_ptr + 0x2C, ColorType::Red);
+ } else if (STRNCMP_CR(entity_name, "currency_collection") == 0 ||
+ STRNCMP_CR(entity_name, "cash_register") == 0 ||
+ STRNCMP_CR(entity_name, "cash") == 0)
+ {
+ auto slots_ptr = memory.Read<uint64_t>(entity + 0xA8);
+ auto slot_ptr = memory.Read<uint64_t>(slots_ptr + 0);
+ auto render_node_ptr = memory.Read<uint64_t>(slot_ptr + 0xA0);
+
+ memory.Write<uint32_t>(render_node_ptr + 0x10, 0x80018);
+ memory.Write<uint32_t>(render_node_ptr + 0x2C, ColorType::Yellow);
+ } else if (STRNCMP_CR(entity_name, "TraitCharm") == 0)
+ {
+ auto slots_ptr = memory.Read<uint64_t>(entity + 0xA8);
+ auto slot_ptr = memory.Read<uint64_t>(slots_ptr + 0);
+ auto render_node_ptr = memory.Read<uint64_t>(slot_ptr + 0xA0);
+
+ memory.Write<uint32_t>(render_node_ptr + 0x10, 0x80018);
+ memory.Write<uint32_t>(render_node_ptr + 0x2C, ColorType::Blue);
+ }
+ }
+ }
+ } __dppexcept(mainloop_seh) {
+ return STATUS_UNSUCCESSFUL;
+ } __dpptryend(mainloop_seh);
+
+ return STATUS_SUCCESS;
+ },
+ args);
+
+ return STATUS_SUCCESS;
+}
+
+VOID DriverUnload(_In_ struct _DRIVER_OBJECT *DriverObject) {
+ UNREFERENCED_PARAMETER(DriverObject);
+
+ DbgPrint("%s\n", "Waiting for thread termination..");
+ __dpptry(mainloop_exception_handler, unload_seh)
+ {
+ shutdown_event.Notify();
+ thread.WaitForTermination();
+ } __dppexcept(unload_seh) {
+ } __dpptryend(unload_seh);
+}
+}
diff --git a/memory.cpp b/memory.cpp
index eb13135..af58279 100644
--- a/memory.cpp
+++ b/memory.cpp
@@ -1,4 +1,5 @@
#include <EASTL/finally.h>
+#include <EASTL/shared_ptr.h>
#include <eastl_compat.hpp>
#include <except.h>
@@ -601,3 +602,73 @@ NTSTATUS WriteVirtualMemory(_In_ PEPROCESS pep, _In_ const UCHAR *sourceAddress,
return status;
}
+
+bool PatternScanner::SearchWithMask(const uint8_t *buffer, size_t buffer_size,
+ const uint8_t *pattern, size_t pattern_size,
+ const eastl::string_view &mask,
+ eastl::vector<size_t> &results) {
+ bool found_some = false;
+
+ if (mask.length() != pattern_size)
+ return false;
+
+ for (size_t i = 0; i < buffer_size - pattern_size + 1; ++i) {
+ bool match = true;
+ for (size_t j = 0; j < pattern_size; ++j) {
+ if (mask[j] == 'x' && buffer[i + j] != pattern[j]) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ found_some = true;
+ results.push_back(i);
+ }
+ }
+
+ return found_some;
+}
+
+bool PatternScanner::ProcessModule::Scan(const eastl::wstring_view &module_name,
+ eastl::vector<size_t> &results,
+ size_t max_results) {
+ if (eastl::size(m_pattern) > 64)
+ return false;
+
+ const auto mods = ::GetModules(m_pep, FALSE);
+ const auto mod = eastl::find_if(mods.begin(), mods.end(),
+ [&module_name](const Module &mod) {
+ return mod.BaseDllName == module_name;
+ });
+ if (mod == mods.end())
+ return false;
+
+ auto copy_buffer = eastl::make_shared<eastl::array<uint8_t, 4096 * 8>>();
+ const auto pages = ::GetPages(m_obj, m_max_pages);
+ for (const auto page : pages) {
+ if (page.BaseAddress < mod->DllBase ||
+ page.BaseAddress + page.RegionSize > mod->DllBase + mod->SizeOfImage)
+ continue;
+ SIZE_T offset = 0;
+ while (offset < page.RegionSize - eastl::size(m_pattern) + 1) {
+ SIZE_T in_out_size =
+ eastl::min(eastl::size(*copy_buffer), page.RegionSize - offset);
+ const auto ret =
+ ::ReadVirtualMemory(m_pep, page.BaseAddress + offset,
+ eastl::begin(*copy_buffer), &in_out_size);
+ if (!NT_SUCCESS(ret) || in_out_size == 0)
+ break;
+
+ if (SearchWithMask(eastl::begin(*copy_buffer), in_out_size,
+ m_pattern.begin(), eastl::size(m_pattern), m_mask,
+ results)) {
+ if (results.size() >= max_results)
+ return false;
+ }
+
+ offset += in_out_size - eastl::size(m_pattern) + 1;
+ }
+ }
+
+ return true;
+}
diff --git a/memory.hpp b/memory.hpp
index c8db72c..0e86c00 100644
--- a/memory.hpp
+++ b/memory.hpp
@@ -1,6 +1,8 @@
#ifndef MEMORY_H
#define MEMORY_H 1
+#include <EASTL/array.h>
+#include <EASTL/initializer_list.h>
#include <EASTL/string.h>
#include <EASTL/vector.h>
#include <cstdint>
@@ -175,4 +177,49 @@ private:
NTSTATUS m_last_error;
SIZE_T m_last_size;
};
+
+namespace PatternScanner {
+bool SearchWithMask(const uint8_t *buffer, size_t buffer_size,
+ const uint8_t *pattern, size_t pattern_size,
+ const eastl::string_view &mask,
+ eastl::vector<size_t> &results);
+
+template <size_t PM, size_t N>
+SearchWithMask(const eastl::array<uint8_t, N> &buffer,
+ const eastl::array<uint8_t, PM> &pattern,
+ const eastl::string_view &mask, eastl::vector<size_t> &results) {
+ return SearchWithMask(buffer.data(), eastl::size(buffer), pattern.data(),
+ eastl::size(pattern), mask, results);
+}
+
+template <size_t N>
+SearchWithMask(const eastl::array<uint8_t, N> &buffer,
+ const std::initializer_list<uint8_t> &pattern,
+ const eastl::string_view &mask, eastl::vector<size_t> &results) {
+ return SearchWithMask(buffer.data(), eastl::size(buffer), pattern.begin(),
+ eastl::size(pattern), mask, results);
+}
+
+class ProcessModule {
+public:
+ ProcessModule(_In_ PEPROCESS pep, _In_ HANDLE obj,
+ const std::initializer_list<uint8_t> &pattern,
+ const eastl::string_view &mask)
+ : m_max_pages(8192), m_pep(pep), m_obj(obj), m_pattern(pattern),
+ m_mask(mask), m_offset(0) {}
+ ProcessModule(const ProcessModule &) = delete;
+
+ void SetMaxPages(SIZE_T new_max_pages) { m_max_pages = new_max_pages; }
+ bool Scan(const eastl::wstring_view &module_name,
+ eastl::vector<size_t> &results, size_t max_results = 128);
+
+private:
+ SIZE_T m_max_pages;
+ PEPROCESS m_pep;
+ HANDLE m_obj;
+ const std::initializer_list<uint8_t> &m_pattern;
+ const eastl::string_view &m_mask;
+ size_t m_offset;
+};
+} // namespace PatternScanner
#endif