-
-
Save yazzn/4e108ae6e7fb195aa01ed17385c3bcba to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <array> | |
#include <vector> | |
#include <functional> | |
#include <windows.h> | |
namespace memory | |
{ | |
namespace detail | |
{ | |
template <typename... Params> | |
struct parameter_size; | |
template <typename Ty, typename... Params> | |
struct parameter_size<Ty, Params...> | |
{ | |
static std::ptrdiff_t count(std::size_t size, Ty param, Params... params) | |
{ | |
return parameter_size<Params...>::count(size + sizeof(Ty), params...); | |
} | |
}; | |
template <int N, typename... Params> | |
struct parameter_size<std::_Ph<N>, Params...> | |
{ | |
static std::ptrdiff_t count(std::size_t size, std::_Ph<N> param, Params... params) | |
{ | |
return parameter_size<Params...>::count(size + N, params...); | |
} | |
}; | |
template <typename Ty, std::size_t N, typename... Params> | |
struct parameter_size<std::array<Ty, N>, Params...> | |
{ | |
static std::ptrdiff_t count(std::size_t size, std::array<Ty, N> ¶m, Params... params) | |
{ | |
return parameter_size<Params...>::count(size + N * sizeof(Ty), params...); | |
} | |
}; | |
template <typename Ty, typename... Params> | |
struct parameter_size<std::vector<Ty>, Params...> | |
{ | |
static std::ptrdiff_t count(std::size_t size, std::vector<Ty> ¶m, Params... params) | |
{ | |
return parameter_size<Params...>::count(size + std::size(param) * sizeof(Ty), params...); | |
} | |
}; | |
template <typename... Params> | |
struct parameter_size<const char *, Params...> | |
{ | |
static std::ptrdiff_t count(std::size_t size, const char *param, Params... params) | |
{ | |
return parameter_size<Params...>::count(size + std::strlen(param), params...); | |
} | |
}; | |
template <typename... Params> | |
struct parameter_size<char *, Params...> | |
{ | |
static std::ptrdiff_t count(std::size_t size, char *param, Params... params) | |
{ | |
return parameter_size<Params...>::count(size + std::strlen(param), params...); | |
} | |
}; | |
template <> | |
struct parameter_size<> | |
{ | |
static std::ptrdiff_t count(std::size_t size) | |
{ | |
return size; | |
} | |
}; | |
template <typename... Pattern> | |
struct pattern_helper; | |
template <int N, typename... Pattern> | |
struct pattern_helper<std::_Ph<N>, Pattern...> | |
{ | |
static bool match(std::uintptr_t pointer, std::_Ph<N> ph, Pattern... pattern) | |
{ | |
return pattern_helper<Pattern...>::match(pointer + N, pattern...); | |
} | |
}; | |
template <typename... Pattern> | |
struct pattern_helper<char *, Pattern...> | |
{ | |
static bool match(std::uintptr_t pointer, char *value, Pattern... pattern) | |
{ | |
std::size_t size = std::strlen(value); | |
return !memcmp(reinterpret_cast<char *>(pointer), value, size) && | |
pattern_helper<Pattern...>::match(pointer + size, pattern...); | |
} | |
}; | |
template <typename... Pattern> | |
struct pattern_helper<char const *, Pattern...> | |
{ | |
static bool match(std::uintptr_t pointer, char const *value, Pattern... pattern) | |
{ | |
std::size_t size = std::strlen(value); | |
return !memcmp(reinterpret_cast<char const *>(pointer), value, size) && | |
pattern_helper<Pattern...>::match(pointer + size, pattern...); | |
} | |
}; | |
template <typename Ty, typename... Pattern> | |
struct pattern_helper<Ty, Pattern...> | |
{ | |
static bool match(std::uintptr_t pointer, Ty value, Pattern... pattern) | |
{ | |
return !memcmp(reinterpret_cast<Ty *>(pointer), &value, sizeof(Ty)) && | |
pattern_helper<Pattern...>::match(pointer + sizeof(Ty), pattern...); | |
} | |
}; | |
template <typename Ty, std::size_t N, typename... Pattern> | |
struct pattern_helper<std::array<Ty, N>, Pattern...> | |
{ | |
static bool match(std::uintptr_t pointer, std::array<Ty, N> &value, Pattern... pattern) | |
{ | |
return !memcmp(reinterpret_cast<Ty *>(pointer), std::data(value), N * sizeof(Ty)) && | |
pattern_helper<Pattern...>::match(pointer + N * sizeof(Ty), pattern...); | |
} | |
}; | |
template <typename Ty, typename... Pattern> | |
struct pattern_helper<std::vector<Ty>, Pattern...> | |
{ | |
static bool match(std::uintptr_t pointer, std::vector<Ty> &value, Pattern... pattern) | |
{ | |
return !memcmp(reinterpret_cast<Ty *>(pointer), std::data(value), std::size(value) * sizeof(Ty)) && | |
pattern_helper<Pattern...>::match(pointer + std::size(value) * sizeof(Ty), pattern...); | |
} | |
}; | |
template <> | |
struct pattern_helper<> | |
{ | |
static bool match(std::uintptr_t pointer) | |
{ return true; } | |
}; | |
std::pair<std::uintptr_t, std::uintptr_t> module_base_info(const char *module) | |
{ | |
PIMAGE_DOS_HEADER image_dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(GetModuleHandleA(module)); | |
if (image_dos_header->e_magic == IMAGE_DOS_SIGNATURE) | |
{ | |
PIMAGE_NT_HEADERS image_nt_header = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<std::uint8_t *>(image_dos_header) + image_dos_header->e_lfanew); | |
if (image_nt_header->Signature == IMAGE_NT_SIGNATURE) | |
{ | |
return std::make_pair(image_nt_header->OptionalHeader.ImageBase, image_nt_header->OptionalHeader.SizeOfImage); | |
} | |
} | |
return std::make_pair(0, 0); | |
} | |
} | |
template <typename... Params> | |
std::ptrdiff_t count_parameter_size(Params... params) | |
{ | |
return detail::parameter_size<Params...>::count(0, params...); | |
} | |
template <typename... Pattern> | |
bool matches_pattern(std::uintptr_t pointer, Pattern... pattern) | |
{ | |
return detail::pattern_helper<Pattern...>::match(pointer, pattern...); | |
} | |
template <typename... Pattern> | |
std::uintptr_t find_pattern_range(std::uintptr_t first, std::ptrdiff_t length, Pattern... pattern) | |
{ | |
for (std::uintptr_t pointer = first; pointer + count_parameter_size(pattern...) < (first + length); ++pointer) | |
{ | |
if (matches_pattern(pointer, pattern...)) | |
return pointer; | |
} | |
return 0; | |
} | |
template <typename... Pattern> | |
std::uintptr_t find_pattern(const char *module, Pattern... pattern) | |
{ | |
auto base_info = detail::module_base_info(module); | |
return find_pattern_range(base_info.first, base_info.second, pattern...); | |
} | |
template <typename... Pattern> | |
std::vector<std::uintptr_t> find_pattern_all(std::uintptr_t first, std::ptrdiff_t length, Pattern... pattern) | |
{ | |
std::vector<std::uintptr_t> results; | |
for (std::uintptr_t pointer = first; pointer + count_parameter_size(pattern...) < (first + length); ++pointer) | |
{ | |
if (matches_pattern(pointer, pattern...)) | |
results.push_back(pointer); | |
} | |
return results; | |
} | |
template <typename... Pattern> | |
std::vector<std::uintptr_t> find_pattern_all(const char *module, Pattern... pattern) | |
{ | |
auto base_info = detail::module_base_info(module); | |
return find_pattern_all(base_info.first, base_info.second, pattern...); | |
} | |
template <std::size_t N> | |
using u8a = std::array<std::uint8_t, N>; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment