Files
ps4-fortniteserver/OrbisHooker/source/hook/pattern.cpp
T
2026-04-23 22:01:27 +02:00

119 lines
3.6 KiB
C++

// OrbisHookah, Copyright @2026 apfelteesaft
#include "pattern.h"
#include <string.h>
namespace Hookah {
// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------
static int HexVal(char c) {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
return -1;
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
int ParsePattern(const char* pattern,
uint8_t* outBytes,
bool* outMask,
int maxLen)
{
int count = 0;
const char* p = pattern;
while (*p != '\0' && count < maxLen) {
// Skip leading whitespace between tokens.
while (*p == ' ' || *p == '\t') p++;
if (*p == '\0') break;
if (p[0] == '?') {
// Wildcard token: accept "?" or "??"
outBytes[count] = 0x00;
outMask[count] = false;
count++;
p++;
if (*p == '?') p++; // consume optional second '?'
} else {
int hi = HexVal(p[0]);
int lo = (p[1] != '\0') ? HexVal(p[1]) : -1;
if (hi < 0 || lo < 0) break; // malformed token — stop parsing
outBytes[count] = static_cast<uint8_t>((hi << 4) | lo);
outMask[count] = true;
count++;
p += 2;
}
}
return count;
}
void* FindPattern(uintptr_t base,
size_t size,
const uint8_t* bytes,
const bool* mask,
int patternLen)
{
if (patternLen <= 0 || size < static_cast<size_t>(patternLen))
return nullptr;
const uint8_t* mem = reinterpret_cast<const uint8_t*>(base);
const size_t limit = size - static_cast<size_t>(patternLen);
for (size_t i = 0; i <= limit; i++) {
bool match = true;
for (int j = 0; j < patternLen; j++) {
// mask[j] == true → this byte must match exactly
// mask[j] == false → wildcard, always matches
if (mask[j] && mem[i + j] != bytes[j]) {
match = false;
break;
}
}
if (match)
return reinterpret_cast<void*>(base + i);
}
return nullptr;
}
void* ScanPattern(uintptr_t base, size_t size, const char* pattern) {
uint8_t bytes[256];
bool mask[256];
int len = ParsePattern(pattern, bytes, mask, 256);
if (len <= 0) return nullptr;
return FindPattern(base, size, bytes, mask, len);
}
void* ScanPatternMask(uintptr_t base,
size_t size,
const char* bytes,
const char* mask,
size_t patternLen)
{
if (!bytes || !mask || patternLen == 0 || size < patternLen)
return nullptr;
const uint8_t* mem = reinterpret_cast<const uint8_t*>(base);
const size_t limit = size - patternLen;
for (size_t i = 0; i <= limit; i++) {
bool match = true;
for (size_t j = 0; j < patternLen; j++) {
if (mask[j] == 'x' && mem[i + j] != static_cast<uint8_t>(bytes[j])) {
match = false;
break;
}
}
if (match)
return reinterpret_cast<void*>(base + i);
}
return nullptr;
}
} // namespace Hookah