This commit is contained in:
Oscar
2025-07-25 22:49:56 +03:00
parent 03af6d458c
commit 860be9ac4c
470 changed files with 308020 additions and 436 deletions

View File

@@ -0,0 +1,131 @@
#include "../pointer/pointer.hpp"
#include "cmodule.hpp"
#include "../fnv1a.hpp"
#include <wtypes.h>
#include <Psapi.h>
CModule::CModule(const char* name) {
m_Name = name;
m_Hash = fnv1a::Hash(name);
m_Handle = nullptr;
m_Begin = m_Size = 0;
}
CModule::~CModule() {
if (!m_Handle) {
return;
}
#ifndef _WIN32
dlclose(m_Handle);
#endif
}
bool CModule::Retrieve() {
if (m_Handle) {
return true;
}
InitializeHandle();
InitializeBounds();
return m_Handle != nullptr;
}
uintptr_t CModule::GetInterface(const char* version) {
uintptr_t rv = 0;
if (m_Handle) {
CPointer pCreateInterface = GetProcAddress("CreateInterface");
if (!pCreateInterface.IsValid()) {
return rv;
}
// Used internally to register classes.
struct InterfaceReg {
std::add_pointer_t<uintptr_t()> m_CreateFn;
const char* m_pName;
InterfaceReg* m_pNext; // For the global list.
};
InterfaceReg* s_pInterfaceRegs =
#ifdef _WIN32
pCreateInterface.Absolute(3, 0).Dereference(1).Get<InterfaceReg*>()
#elif __linux__
pCreateInterface.Absolute(1, 0).Absolute(19, 0).Dereference(1).Get<InterfaceReg*>()
#endif
;
uint32_t versionHash = fnv1a::Hash(version);
for (; s_pInterfaceRegs; s_pInterfaceRegs = s_pInterfaceRegs->m_pNext) {
if (fnv1a::Hash(s_pInterfaceRegs->m_pName) == versionHash) {
rv = s_pInterfaceRegs->m_CreateFn();
break;
}
}
}
return rv;
}
uintptr_t CModule::GetProcAddress(const char* procName) {
uintptr_t rv = 0;
if (m_Handle) {
rv = reinterpret_cast<uintptr_t>(::GetProcAddress(static_cast<HMODULE>(m_Handle), procName));
}
return rv;
}
uintptr_t CModule::FindPattern(const std::span<const int>& pattern) const {
uintptr_t rv = 0;
if (m_Handle) {
uint8_t* bytes = reinterpret_cast<uint8_t*>(m_Begin);
// Faster than pattern[] in debug builds because of _STL_VERIFY.
const int* patternData = pattern.data();
const size_t patternSize = pattern.size();
for (size_t i = 0; i < m_Size - patternSize; ++i) {
bool found = true;
for (size_t j = 0; j < patternSize; ++j) {
if (bytes[i + j] != patternData[j] && patternData[j] != -1) {
found = false;
break;
}
}
if (found) {
rv = reinterpret_cast<uintptr_t>(&bytes[i]);
break;
}
}
}
return rv;
}
void CModule::InitializeHandle() {
#ifdef _WIN32
m_Handle = GetModuleHandle(GetName());
#else
m_Handle = dlopen(GetName(), RTLD_LAZY | RTLD_NOLOAD);
#endif
}
void CModule::InitializeBounds() {
if (!m_Handle) {
return;
}
MODULEINFO mi;
BOOL status = GetModuleInformation(GetCurrentProcess(), static_cast<HMODULE>(m_Handle), &mi, sizeof(mi));
if (status != 0) {
SetBounds(reinterpret_cast<uintptr_t>(m_Handle), mi.SizeOfImage);
}
}
void CModule::SetBounds(uintptr_t begin, uintptr_t size) {
m_Begin = begin;
m_Size = size;
}

View File

@@ -0,0 +1,38 @@
#pragma once
#include <cstdint>
#include <span>
#include <string>
class CModule {
public:
CModule(const char* name);
~CModule();
auto GetHash() const { return m_Hash; }
auto GetHandle() const { return m_Handle; }
auto GetName() const { return m_Name.c_str(); }
// Returns false if module not loaded.
bool Retrieve();
uintptr_t GetInterface(const char* version);
uintptr_t GetProcAddress(const char* procName);
uintptr_t FindPattern(const std::span<const int>& pattern) const;
private:
void InitializeHandle();
void InitializeBounds();
void SetBounds(uintptr_t begin, uintptr_t size);
// Module name.
std::string m_Name;
// Module name fnv1a hash.
uint32_t m_Hash;
// Module handle.
void* m_Handle;
// Used for pattern scanning.
uintptr_t m_Begin, m_Size;
};

View File

@@ -0,0 +1,58 @@
#include "../memory/memadd.h"
#include "../csig/sigscan.hpp"
#include "../fnv1a.hpp"
void CMemory::Initialize() {
for (CSigScan* it : m_ScheduledScans) {
it->FindSignature();
it->FreeData();
}
std::vector<CSigScan*>().swap(m_ScheduledScans);
}
ModulePtr_t& CMemory::GetModuleInternal(const char* libName) {
auto hash = fnv1a::Hash(libName);
auto it = m_CachedModules.find(hash);
if (it != m_CachedModules.end()) {
return it->second;
}
auto module = std::make_unique<CModule>(libName);
if (module->Retrieve()) {
return m_CachedModules.emplace(hash, std::move(module)).first->second;
}
static ModulePtr_t null{};
return null;
}
CPointer CMemory::GetInterfaceInternal(const char* libName, const char* version) {
CPointer rv = 0;
auto& library = CMemory::GetModuleInternal(libName);
if (!library) {
return rv;
}
rv = library->GetInterface(version);
return rv;
}
CPointer CMemory::GetProcAddressInternal(const char* libName, const char* procName) {
CPointer rv = 0;
auto& library = CMemory::GetModuleInternal(libName);
if (!library) {
return rv;
}
rv = library->GetProcAddress(procName);
return rv;
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include "../memory/cmodule.hpp"
#include "../pointer/pointer.hpp"
#include <memory>
#include <vector>
#include <unordered_map>
class CSigScan;
using ModulePtr_t = std::unique_ptr<CModule>;
class CMemory {
public:
static CMemory& Get() {
static CMemory inst;
return inst;
}
static auto& GetModule(const char* libName) { return Get().GetModuleInternal(libName); }
static auto GetInterface(const char* libName, const char* version) { return Get().GetInterfaceInternal(libName, version); }
static auto GetProcAddress(const char* libName, const char* procName) { return Get().GetProcAddressInternal(libName, procName); }
// Used internally.
static auto ScheduleScan(CSigScan* sigScan) { Get().m_ScheduledScans.emplace_back(sigScan); }
void Initialize();
private:
ModulePtr_t& GetModuleInternal(const char* libName);
CPointer GetInterfaceInternal(const char* libName, const char* version);
CPointer GetProcAddressInternal(const char* libName, const char* procName);
std::unordered_map<uint32_t, ModulePtr_t> m_CachedModules;
std::vector<CSigScan*> m_ScheduledScans;
};