-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathXORPattern.hpp
117 lines (110 loc) · 4.24 KB
/
XORPattern.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#pragma once
#include "CompileTimePattern.hpp"
#include <array>
namespace patterns {
namespace detail {
// Used to generate the pattern string hash
constexpr uint32_t fnv1a(const char* s, size_t count) {
return ((count ? fnv1a(s, count - 1) : 2166136261u) ^ s[count]) * 16777619u;
}
template<size_t count>
constexpr __forceinline uint32_t fnv1a(const char(&s)[count]) {
return fnv1a(s, count - 1);
}
template<uint32_t seed>
constexpr __forceinline uint8_t generate_key() {
uint32_t value = 2166136261u + seed;
for (char c : __TIME__)
value = static_cast<uint32_t>((value ^ c) * 16777619ull);
return value;
}
template<uint32_t hash, size_t... Keys>
constexpr auto generate_keys(std::index_sequence<Keys...>) {
return std::array<uint8_t, sizeof...(Keys)>{ detail::generate_key<hash + Keys>()...};
}
}
template<size_t nstr, size_t narr, uint32_t hash>
class XORPattern : public Pattern {
std::array<uint8_t, narr> pattern_;
std::array<uint8_t, narr> mask_;
std::array<uint8_t, narr> keys_;
public:
constexpr XORPattern(const char* p) :
pattern_{}, mask_{}, keys_{ detail::generate_keys<hash>(std::make_index_sequence<narr>()) }
{
length_ = narr;
auto n = 0;
for (auto i = 0; i < nstr; i += 2) {
auto ptr = &p[i];
if (*ptr == '?') {
pattern_[n] = 0 ^ keys_[n];
mask_[n] = 0;
++n;
}
// Capture where we have our offset marker 'X' at
else if (*ptr == 'X' || *ptr == 'x') {
offset_ = n;
if (p[i + 1] != ' ') {
#ifndef __arm64__
insn_len_ = get_inst_len_opt(&p[++i]);
#endif
while (p[i + 1] != ' ')
++i;
}
}
// Break from parsing the pattern, since / at the end starts the flags
else if (*ptr == '/') {
++ptr;
handle_options(ptr);
break;
}
else if (*ptr != ' ') {
pattern_[n] = value(ptr) ^ keys_[n];
mask_[n] = 0xFF;
++n;
}
else --i;
}
}
virtual const uint8_t* pattern() const override {
return pattern_.data();
}
virtual const uint8_t* mask() const override {
return mask_.data();
}
// Override on [] operator to perform XOR for original byte
virtual uint8_t operator[](size_t idx) const override {
return pattern_[idx] ^ keys_[idx];
}
virtual void* find(const uint8_t* bytes, size_t size) const override {
void* result = nullptr;
const auto end = bytes + size - length_;
for (auto i = const_cast<uint8_t*>(bytes); i < end; align_ ? i += align_size_ : ++i) {
bool found = true;
for (auto j = 0U; j < length_; ++j) {
if (mask_[j] == 0xFF && (*this)[j] != i[j]) {
found = false;
break;
}
}
if (found)
return get_result(i, end);
}
return result;
}
template <typename T>
T find(const uint8_t* bytes, size_t size) const {
return reinterpret_cast<T>(find(bytes, size));
}
};
}
#if __cplusplus > 201703L
template<patterns::detail::const_string str>
constexpr auto operator"" _xorpattern() {
return patterns::XORPattern<str.length, patterns::detail::pattern_length(str.data, str.size, false), patterns::detail::fnv1a(str.data, str.length)>(str.data);
}
#else
#ifndef XOR_PATTERN
#define XOR_PATTERN(x) patterns::XORPattern<sizeof(x)-1, patterns::detail::pattern_length(x, false), patterns::detail::fnv1a(x)>(x)
#endif
#endif