Use alternative method for finding 's_pInterfaceRegs' list.

* No longer relies on a pattern scan.

Signed-off-by: aixxe <me@aixxe.net>
This commit is contained in:
aixxe 2017-03-14 19:13:53 +00:00
parent 0eb481e754
commit 713c4b4627
No known key found for this signature in database
GPG Key ID: EF00F521411ACB1F
3 changed files with 39 additions and 11 deletions

View File

@ -19,8 +19,10 @@
*/
#include "Basehook.h"
#include "Hooks/Hooks.h"
#include "Events/TestListener.h"
#include "Utilities/FindPattern.h"
ICvar* cvar = nullptr;
IPanel* panel = nullptr;
@ -66,14 +68,14 @@ extern "C" void __attribute__((constructor)) css_basehook_open() {
engine = GetInterface<IVEngineClient>("bin/engine.so", "VEngineClient0");
modelrender = GetInterface<IVModelRender>("bin/engine.so", "VEngineModel0");
debugoverlay = GetInterface<IVDebugOverlay>("bin/engine.so", "VDebugOverlay0");
clientdll = GetInterface<IBaseClientDLL>("bin/client.so", "VClient0");
clientdll = GetInterface<IBaseClientDLL>("cstrike/bin/client.so", "VClient0");
matsystem = GetInterface<IMaterialSystem>("bin/materialsystem.so", "VMaterialSystem0");
entitylist = GetInterface<IClientEntityList>("bin/client.so", "VClientEntityList0");
entitylist = GetInterface<IClientEntityList>("cstrike/bin/client.so", "VClientEntityList0");
gameevents = GetInterface<IGameEventManager2>("bin/engine.so", "GAMEEVENTSMANAGER002");
// Scan for the 'CRC32_ProcessBuffer' function. (overkill, but why not?)
CRC32_ProcessBuffer = reinterpret_cast<CRC32_ProcessBufferFn>(
FindPattern("bin/client.so", "\x55\x89\xE5\x57\x56\x53\x83\xEC\x08\x8B\x4D\x10", "xxxxxxxxxxxx")
FindPattern("cstrike/bin/client.so", "\x55\x89\xE5\x57\x56\x53\x83\xEC\x08\x8B\x4D\x10", "xxxxxxxxxxxx")
);
// Hook 'FrameStageNotify' and 'CreateMove' from IBaseClientDLL.

View File

@ -7,7 +7,6 @@
#include <vmthook/vmthook.h>
#include "Utilities/Linker.h"
#include "Utilities/FindPattern.h"
#include "Utilities/Interfaces.h"
#include "Utilities/NetVars.h"

View File

@ -1,5 +1,8 @@
#pragma once
#include <iostream>
#include <dlfcn.h>
typedef void* (*InstantiateInterfaceFn) ();
class InterfaceReg {
@ -10,16 +13,40 @@ class InterfaceReg {
};
inline const InterfaceReg* GetInterfaces(const char* library) {
// Find the pointer to the 'InterfaceReg::s_pInterfaceRegs' linked list - same on all game libraries.
uintptr_t interface_list_addr = FindPattern(library, "\x89\x10\x8B\x15\x00\x00\x00\x00\xA3", "xxxx????x");
if (interface_list_addr)
return **reinterpret_cast<InterfaceReg***>(interface_list_addr + 4);
// Open a handle to the library.
void* library_handle = dlopen(library, RTLD_NOLOAD | RTLD_NOW);
return nullptr;
// Check for an exported 's_pInterfaceRegs' symbol. (easy mode)
void* interfaceregs_symbol = dlsym(library_handle, "s_pInterfaceRegs");
if (interfaceregs_symbol) {
// Close the handle to the library.
dlclose(library_handle);
// Return interface list.
return *reinterpret_cast<InterfaceReg**>(interfaceregs_symbol);
}
// Get the address to the exported 'CreateInterface' symbol.
void* createinterface_symbol = dlsym(library_handle, "CreateInterface");
// Close the handle to the library.
dlclose(library_handle);
// Get the jump displacement to the 'CreateInterfaceInternal' function.
uintptr_t jump_instruction = uintptr_t(createinterface_symbol) + 4;
int32_t jump_displacement = *reinterpret_cast<int32_t*>(jump_instruction + 1);
// Calculate the absolute jump address relative to the next instruction.
uintptr_t createinterfaceinternal_addr = (jump_instruction + 5) + jump_displacement;
// Read the address to the 'InterfaceReg::s_pInterfaceRegs' linked list from 11 bytes in.
uintptr_t interface_list = *reinterpret_cast<uintptr_t*>(createinterfaceinternal_addr + 11);
return *reinterpret_cast<InterfaceReg**>(interface_list);
}
template <typename T> inline T* GetInterface(const char* library, const char* partial_version) {
template <typename T = void*> inline T* GetInterface(const char* library, const char* partial_version) {
for (const InterfaceReg* current = GetInterfaces(library); current; current = current->m_pNext) {
if (std::string(current->m_pName).find(partial_version) != std::string::npos) {
return reinterpret_cast<T*>(current->m_CreateFn());