mirror of
https://github.com/ApfelTeeSaft/ps4-fortniteserver.git
synced 2026-08-26 19:33:25 +00:00
119 lines
3.6 KiB
C++
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
|