summaryrefslogtreecommitdiffstats
path: root/ModuleScanner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ModuleScanner.cpp')
-rw-r--r--ModuleScanner.cpp99
1 files changed, 99 insertions, 0 deletions
diff --git a/ModuleScanner.cpp b/ModuleScanner.cpp
new file mode 100644
index 0000000..831f87a
--- /dev/null
+++ b/ModuleScanner.cpp
@@ -0,0 +1,99 @@
1#include "ModuleScanner.h"
2#include <stdlib.h>
3#include <string.h>
4#include <elf.h>
5#include <dlfcn.h>
6
7CModuleScanner::CModuleScanner(void *addr)
8 : m_addr(addr)
9{}
10
11void *CModuleScanner::FindSignature(const char *sig, const char *pattern)
12{
13 DynLibInfo lib;
14 bool found;
15 char *ptr, *end;
16 size_t len = strlen(pattern);
17
18 memset(&lib, 0, sizeof(DynLibInfo));
19
20 if (!GetLibraryInfo(m_addr, lib))
21 return NULL;
22
23 ptr = reinterpret_cast<char *>(lib.baseAddress);
24 end = ptr + lib.memorySize;
25
26 while (ptr < end)
27 {
28 found = true;
29 for (register size_t i = 0; i < len; i++)
30 {
31 if (pattern[i] != '?' && sig[i] != ptr[i])
32 {
33 found = false;
34 break;
35 }
36 }
37
38 if (found)
39 return ptr;
40
41 ptr++;
42 }
43
44 return NULL;
45}
46
47bool CModuleScanner::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
48{
49 unsigned long baseAddr;
50 Dl_info info;
51 Elf32_Ehdr *file;
52 Elf32_Phdr *phdr;
53 uint16_t phdrCount;
54
55 if (libPtr == NULL)
56 return false;
57
58 if (!dladdr(libPtr, &info))
59 return false;
60
61 if (!info.dli_fbase || !info.dli_fname)
62 return false;
63
64 /* This is for our insane sanity checks :o */
65 baseAddr = reinterpret_cast<unsigned long>(info.dli_fbase);
66 file = reinterpret_cast<Elf32_Ehdr *>(baseAddr);
67
68 /* Check ELF magic */
69 if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
70 return false;
71
72 /* Check ELF version */
73 if (file->e_ident[EI_VERSION] != EV_CURRENT)
74 return false;
75
76 /* Check ELF architecture, which is 32-bit/x86 right now
77 * Should change this for 64-bit if Valve gets their act together
78 */
79 if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB)
80 return false;
81
82 /* For our purposes, this must be a dynamic library/shared object */
83 if (file->e_type != ET_DYN)
84 return false;
85
86 phdrCount = file->e_phnum;
87 phdr = reinterpret_cast<Elf32_Phdr *>(baseAddr + file->e_phoff);
88
89 /* Add up the memory sizes of segments marked as PT_LOAD as those are the only ones that should be in memory */
90 for (uint16_t i = 0; i < phdrCount; i++)
91 {
92 Elf32_Phdr &hdr = phdr[i];
93 if (hdr.p_type == PT_LOAD)
94 lib.memorySize += hdr.p_memsz;
95 }
96
97 lib.baseAddress = reinterpret_cast<void *>(baseAddr);
98 return true;
99}