FindSignature with LRU cache (max: 8192. If the value is above this limit, then the cache is flushed).
I tried to make the best performance.
PHP Code:
#include <iostream>
#include <Windows.h>
#include <Tlhelp32.h>
#include <map>
#include <string>
struct LRU_Record {
std::string module_name;
std::string signature;
void* xAddr;
};
typedef unsigned long long int BigInt;
typedef std::map<size_t, LRU_Record> LRU;
LRU lru_cache;
BigInt FindSignatureCalls = 0;
template <typename T>
T __fastcall FindSignature(const char* module_name, const char* signature)
{
static_assert(std::is_pointer<T>::value, "Pointer only allowed!");
if (!module_name || !signature) {
return nullptr;
}
for (LRU::iterator it = lru_cache.begin(); it != lru_cache.end(); it++) {
if (it->second.module_name == std::string(module_name) && it->second.signature == std::string(signature)) {
return reinterpret_cast<T>(it->second.xAddr);
}
}
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
MODULEENTRY32 xModule = { 0 };
xModule.dwSize = sizeof(MODULEENTRY32);
size_t signature_length = strlen(signature);
unsigned long xModuleBaseSize = 0;
unsigned char* xModuleBaseAddress = nullptr;
unsigned char* xModuleBuffer = nullptr;
unsigned long t1 = 0;
unsigned long t2 = signature_length;
unsigned long j = 0;
unsigned long count = 0;
unsigned char wildcard[UCHAR_MAX + 1] = { 0 };
unsigned long i = 0;
long l = 0;
unsigned char c = 0;
unsigned char w = 0;
bool k = false;
if (Module32First(hSnap, &xModule)) {
while (Module32Next(hSnap, &xModule)) {
if (!strcmp(xModule.szModule, module_name)) {
CloseHandle(hSnap);
xModuleBaseSize = static_cast<unsigned long>(xModule.modBaseSize);
xModuleBuffer = reinterpret_cast<unsigned char*>(xModule.modBaseAddr);
if (!xModuleBuffer) {
return nullptr;
}
for (j = t2; j < signature_length; j++)
{
if (static_cast<unsigned char>(signature[j]) == static_cast<unsigned char>(0x2A)) {
continue;
}
count = strlen(&signature[j]);
if (count > t2)
{
t1 = j;
t2 = count;
}
j += (count - 1);
}
for (i = t1; i < t1 + t2; i++) {
wildcard[static_cast<unsigned char>(signature[i])] = 1;
}
for (l = xModuleBaseSize - signature_length; l >= 0; l--)
{
c = xModuleBuffer[l];
w = wildcard[c];
k = false;
while (w == 0 && static_cast<unsigned long>(l) > t2)
{
l -= t2;
w = wildcard[xModuleBuffer[l]];
k = true;
}
if (k == true)
{
l++;
continue;
}
if (c != static_cast<unsigned char>(signature[t1])) {
continue;
}
if (l - t1 < 0 || l - t1 + signature_length > xModuleBaseSize) {
return nullptr;
}
for (j = 0; j < signature_length - 1; j++)
{
if (j == t1 || static_cast<unsigned char>(signature[j]) == static_cast<unsigned char>(0x2A)) {
continue;
}
if (xModuleBuffer[l - t1 + j] != static_cast<unsigned char>(signature[j])) {
break;
}
if (j + 1 == signature_length - 1) {
if (FindSignatureCalls >= 8192) {
lru_cache.clear();
}
FindSignatureCalls++;
size_t cnt = lru_cache.size() + 1;
lru_cache[cnt].module_name = (module_name);
lru_cache[cnt].signature = (signature);
lru_cache[cnt].xAddr = reinterpret_cast<void*>(xModuleBuffer + l - t1);
return reinterpret_cast<T>(xModuleBuffer + l - t1);
}
}
}
return nullptr;
}
}
}
CloseHandle(hSnap);
return nullptr;
}
#pragma optimize("", off)
int main() {
void* addr = FindSignature<void*>("bla.dll", "\x55\x8B\xEC\x8B\x45\x08\x03\x45\x0C");
printf("addr = 0x%X\n", reinterpret_cast<unsigned long>(addr));
(void)(std::getchar());
return 0;
}
#pragma optimize("", on)