Skip to content

Instantly share code, notes, and snippets.

@DavinciPG
Last active April 4, 2023 15:48
Show Gist options
  • Save DavinciPG/68975a87b31ebadf5929992cffe8ae22 to your computer and use it in GitHub Desktop.
Save DavinciPG/68975a87b31ebadf5929992cffe8ae22 to your computer and use it in GitHub Desktop.
Simple caching system for CModule
class CModule {
public:
CModule(CModule&&) = delete;
CModule(const CModule&) = delete;
explicit CModule(const char* name, bool shouldLoad) {
this->m_name = name;
if (shouldLoad) Load();
}
void Load() {
InitializeHandle();
InitializeBounds();
}
template <typename T = void*>
auto GetProcAddress(const char* procName) const {
T rv = nullptr;
if (this->IsLoaded()) {
rv = reinterpret_cast<T>(::GetProcAddress(
static_cast<HMODULE>(this->m_handle), procName));
}
return rv;
}
template <typename T = void*>
T FindInterface(const char* version) const {
void* rv = nullptr;
if (this->IsLoaded()) {
UTILPtr pCreateInterface = this->GetProcAddress("CreateInterface");
InterfaceReg* s_pInterfaceRegs = pCreateInterface.ToAbsolute(3, 0)
.Dereference(1)
.Get<InterfaceReg*>();
for (; s_pInterfaceRegs;
s_pInterfaceRegs = s_pInterfaceRegs->m_pNext) {
if (strcmp(version, s_pInterfaceRegs->m_pName) == 0) {
rv = s_pInterfaceRegs->m_CreateFn();
break;
}
}
}
return reinterpret_cast<T>(rv);
}
template <size_t N>
UTILPtr FindPattern(const std::array<int, N>& signature) const {
UTILPtr rv = 0;
if (this->IsLoaded()) {
const int* pSigData = signature.data();
uint8_t* pBytes = reinterpret_cast<uint8_t*>(this->m_start);
for (size_t i = 0; i < this->m_end - N; ++i) {
bool found = true;
for (size_t j = 0; j < N; ++j) {
if (pBytes[i + j] != pSigData[j] && pSigData[j] != -1) {
found = false;
break;
}
}
if (found) {
rv = reinterpret_cast<uintptr_t>(&pBytes[i]);
break;
}
}
}
return rv;
}
const char* GetName() const { return this->m_name.c_str(); }
bool IsLoaded() const { return this->m_handle != 0; }
private:
void InitializeHandle() {
if (m_isCached) {
this->m_handle = m_cachedHandle;
}
else {
this->m_handle = static_cast<void*>(GetModuleHandle(this->GetName()));
this->m_cachedHandle = this->m_handle;
}
}
void InitializeBounds() {
if (!this->IsLoaded()) return;
if (m_isCached) {
this->m_start = this->m_cachedStart;
this->m_end = this->m_cachedEnd;
}
else {
MODULEINFO mi;
BOOL status = GetModuleInformation(GetCurrentProcess(),
static_cast<HMODULE>(this->m_handle),
&mi, sizeof(mi));
if (status != 0) {
this->m_start = reinterpret_cast<uintptr_t>(this->m_handle);
this->m_end = static_cast<uintptr_t>(mi.SizeOfImage);
this->m_cachedStart = this->m_start;
this->m_cachedEnd = this->m_end;
this->m_isCached = true;
}
}
}
void* m_handle = nullptr;
uintptr_t m_start = 0, m_end = 0;
std::string m_name = "";
/// Caching
bool m_isCached = false;
void* m_cachedHandle = nullptr;
uintptr_t m_cachedStart = 0, m_cachedEnd = 0;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment