#pragma once
/**
* @author ANZO
*/
class MemoryUtils
{
public:
/// Find specified pattern address in memory
/// @param pattern hex pattern to search
/// @param handle module handle to search
/// @param skip_count skip count for cases when few matches found
/// @return memory pointer
static uint8_t* find_sig(const char* pattern, HMODULE handle = nullptr, const uint32_t skip_count = 0)
{
static auto pattern_to_byte = [](const char* pattern_signature)
{
auto bytes = std::vector<int>{};
const auto start = const_cast<char*>(pattern_signature);
const auto end = const_cast<char*>(pattern_signature) + std::strlen(pattern_signature);
for (auto current = start; current < end; ++current)
{
if (*current == '?')
{
++current;
if (*current == '?')
{
++current;
}
bytes.push_back(-1);
}
else
{
bytes.push_back(std::strtoul(current, ¤t, 16));
}
}
return bytes;
};
const auto dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(handle);
const auto nt_headers =
reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<std::uint8_t*>(handle) + dos_header->e_lfanew);
const auto memory_size = nt_headers->OptionalHeader.SizeOfImage;
const auto signature_bytes = pattern_to_byte(pattern);
const auto memory_bytes = reinterpret_cast<std::uint8_t*>(handle);
const auto signature_size = signature_bytes.size();
const auto signature_data = signature_bytes.data();
uint32_t found_count = 0;
for (auto i = 0ul; i < memory_size - signature_size; ++i)
{
bool found = true;
for (auto j = 0ul; j < signature_size; ++j)
{
if (memory_bytes[i + j] != signature_data[j] && signature_data[j] != -1)
{
found = false;
break;
}
}
if (found)
{
if (found_count == skip_count)
{
return &memory_bytes[i];
}
found_count++;
}
}
return nullptr;
}
/// Find specified pattern address in memory
/// @param pattern hex pattern to search
/// @param module_name module handle name to search
/// @param skip_count skip count for cases when few matches found
/// @return memory pointer
static uint8_t* find_sig(const char* pattern, LPCWSTR module_name = nullptr, const uint32_t skip_count = 0)
{
auto handle = ::GetModuleHandle(module_name);
while (handle == nullptr)
{
handle = ::GetModuleHandle(module_name);
}
return find_sig(pattern, handle, skip_count);
}
/// Read bytes from specified process memory address
/// @param process_handle process handle
/// @param address memory address
/// @param size bytes count to read
/// @return byte array if read successfully, {@code nullptr} otherwise
static uint8_t* read_bytes(const HANDLE process_handle, const DWORD64 address, const size_t size)
{
const auto address_pointer = reinterpret_cast<LPVOID>(address);
const auto memory = new byte[size];
memcpy(memory, address_pointer, size);
return memory;
}
};