From edc56b1c98beac5f19a273695f66b8bc58722938 Mon Sep 17 00:00:00 2001 From: manuel Date: Sat, 9 Mar 2013 15:28:20 +0100 Subject: add signature scanner --- ModuleScanner.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 ModuleScanner.cpp (limited to 'ModuleScanner.cpp') diff --git a/ModuleScanner.cpp b/ModuleScanner.cpp new file mode 100644 index 0000000..831f87a --- /dev/null +++ b/ModuleScanner.cpp @@ -0,0 +1,99 @@ +#include "ModuleScanner.h" +#include +#include +#include +#include + +CModuleScanner::CModuleScanner(void *addr) + : m_addr(addr) +{} + +void *CModuleScanner::FindSignature(const char *sig, const char *pattern) +{ + DynLibInfo lib; + bool found; + char *ptr, *end; + size_t len = strlen(pattern); + + memset(&lib, 0, sizeof(DynLibInfo)); + + if (!GetLibraryInfo(m_addr, lib)) + return NULL; + + ptr = reinterpret_cast(lib.baseAddress); + end = ptr + lib.memorySize; + + while (ptr < end) + { + found = true; + for (register size_t i = 0; i < len; i++) + { + if (pattern[i] != '?' && sig[i] != ptr[i]) + { + found = false; + break; + } + } + + if (found) + return ptr; + + ptr++; + } + + return NULL; +} + +bool CModuleScanner::GetLibraryInfo(const void *libPtr, DynLibInfo &lib) +{ + unsigned long baseAddr; + Dl_info info; + Elf32_Ehdr *file; + Elf32_Phdr *phdr; + uint16_t phdrCount; + + if (libPtr == NULL) + return false; + + if (!dladdr(libPtr, &info)) + return false; + + if (!info.dli_fbase || !info.dli_fname) + return false; + + /* This is for our insane sanity checks :o */ + baseAddr = reinterpret_cast(info.dli_fbase); + file = reinterpret_cast(baseAddr); + + /* Check ELF magic */ + if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0) + return false; + + /* Check ELF version */ + if (file->e_ident[EI_VERSION] != EV_CURRENT) + return false; + + /* Check ELF architecture, which is 32-bit/x86 right now + * Should change this for 64-bit if Valve gets their act together + */ + if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB) + return false; + + /* For our purposes, this must be a dynamic library/shared object */ + if (file->e_type != ET_DYN) + return false; + + phdrCount = file->e_phnum; + phdr = reinterpret_cast(baseAddr + file->e_phoff); + + /* Add up the memory sizes of segments marked as PT_LOAD as those are the only ones that should be in memory */ + for (uint16_t i = 0; i < phdrCount; i++) + { + Elf32_Phdr &hdr = phdr[i]; + if (hdr.p_type == PT_LOAD) + lib.memorySize += hdr.p_memsz; + } + + lib.baseAddress = reinterpret_cast(baseAddr); + return true; +} -- cgit v1.2.3