Files
native_invoker_v2/src/detail/rage.hpp
2025-11-13 20:56:11 +01:00

218 lines
8.0 KiB
C++

#pragma once
#include <cstdint>
using u32 = std::uint32_t;
using u64 = std::uint64_t;
namespace fxn::detail::rage
{
namespace sysObfuscatedTypes
{
__forceinline u32 obfRand()
{
static u32 next = 0xCB536E6A;
next = next * 214013 + 2531011;
return next;
}
}
template<typename T, bool TMutate = true>
class sysObfuscated
{
public:
sysObfuscated() { CompileTimeAssert((sizeof(T) & 3) == 0); Init(); }
sysObfuscated(const sysObfuscated<T, TMutate>& rhs) { Init(); Set(rhs.Get()); }
template<bool TMutateOther> sysObfuscated(const sysObfuscated<T, TMutateOther>& rhs) { Init(); Set(rhs.Get()); }
explicit sysObfuscated(const T& data) { Init(); Set(data); }
~sysObfuscated() {}
public:
__forceinline T Get() const;
__forceinline void Set(const T& data);
__forceinline operator T() const { return Get(); }
public:
template<bool TMutateOther> bool operator==(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() == rhs.Get(); }
template<bool TMutateOther> bool operator!=(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() != rhs.Get(); }
template<bool TMutateOther> bool operator<(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() < rhs.Get(); }
template<bool TMutateOther> bool operator<=(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() <= rhs.Get(); }
template<bool TMutateOther> bool operator>(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() > rhs.Get(); }
template<bool TMutateOther> bool operator>=(const sysObfuscated<T, TMutateOther>& rhs) const { return Get() >= rhs.Get(); }
public:
template<bool TMutateOther> sysObfuscated<T, TMutate>& operator=(const sysObfuscated<T, TMutateOther>& rhs) { Set(rhs.Get()); return *this; }
sysObfuscated<T, TMutate>& operator=(const T& data) { Set(data); return *this; }
public:
template<bool TMutateOther> sysObfuscated<T, TMutate>& operator+=(const sysObfuscated<T, TMutateOther>& rhs) { Set(Get()+rhs.Get()); return *this; }
sysObfuscated<T, TMutate>& operator+=(const T& data) { Set(Get()+data); return *this; }
template<bool TMutateOther> sysObfuscated<T, TMutate>& operator-=(const sysObfuscated<T, TMutateOther>& rhs) { Set(Get()-rhs.Get()); return *this; }
sysObfuscated<T, TMutate>& operator-=(const T& data) { Set(Get()-data); return *this; }
template<bool TMutateOther> sysObfuscated<T, TMutate>& operator*=(const sysObfuscated<T, TMutateOther>& rhs) { Set(Get()*rhs.Get()); return *this; }
sysObfuscated<T, TMutate>& operator*=(const T& data) { Set(Get()*data); return *this; }
template<bool TMutateOther> sysObfuscated<T, TMutate>& operator/=(const sysObfuscated<T, TMutateOther>& rhs) { Set(Get()/rhs.Get()); return *this; }
sysObfuscated<T, TMutate>& operator/=(const T& data) { Set(Get()/data); return *this; }
private:
void Init();
mutable u32 m_data[(TMutate ? sizeof(T)*2 : sizeof(T)) / sizeof(u32)];
mutable u32 m_xor;
mutable u32 m_mutate;
};
template<class T, bool TMutate> __forceinline void sysObfuscated<T, TMutate>::Init()
{
m_xor = sysObfuscatedTypes::obfRand();
if(TMutate)
{
m_mutate = sysObfuscatedTypes::obfRand();
}
}
template<class T, bool TMutate> __forceinline T sysObfuscated<T, TMutate>::Get() const
{
u32 xorVal = m_xor ^ (u32)(size_t)this;
u32 ret[sizeof(T)/sizeof(u32)];
u32* src = const_cast<u32*>(&m_data[0]);
u32* dest = (u32*)&ret;
for(size_t i=0; i<sizeof(T)/4; ++i)
{
if(TMutate)
{
// Extract valid data from two words of storage
u32 a = *src & m_mutate;
u32 b = src[sizeof(T)/4] & (~m_mutate);
// Apply entropy in the unused bits: Just flip the two u16's in the u32. We can't do a
// huge amount more without knowledge of the mutation mask.
u32 entropyA = ((*src & (~m_mutate)) << 16) | ((*src & (~m_mutate)) >> 16);
u32 entropyB = ((src[sizeof(T)/4] & m_mutate) << 16) | ((src[sizeof(T)/4] & m_mutate) >> 16);
*src = (*src & m_mutate) | entropyA;
src[sizeof(T)/4] = (src[sizeof(T)/4] & (~m_mutate)) | entropyB;
*dest++ = a | b;
++src;
}
else
{
*dest++ = *src++ ^ xorVal;
}
}
// Call Set() to reset the xor and mutate keys on every call to Get()
if(TMutate)
{
const_cast<sysObfuscated<T, TMutate>*>(this)->Set(*(T*)&ret);
}
return *(T*)&ret;
}
template<class T, bool TMutate> __forceinline void sysObfuscated<T, TMutate>::Set(const T& data)
{
// Reset xor and mutate keys
Init();
u32 xorVal = m_xor ^ (u32)(size_t)this;
u32* src = (u32*)&data;
u32* dest = &m_data[0];
for(size_t i=0; i<sizeof(T)/4; ++i)
{
if(TMutate)
{
u32 a = *src & m_mutate;
u32 b = *src & (~m_mutate);
++src;
*dest = a;
dest[sizeof(T)/4] = b;
++dest;
}
else
{
*dest++ = *src++ ^ xorVal;
}
}
}
template <typename _T>
class scrCommandHash
{
private:
static const int ToplevelSize = 256;
static const int PerBucket = 7;
struct Bucket
{
sysObfuscated<Bucket *, false> obf_Next;
_T Data[PerBucket];
sysObfuscated<u32, false> obf_Count;
sysObfuscated<u64, false> obf_Hashes[PerBucket];
u64 plainText_Hashes[PerBucket];
};
public:
void RegistrationComplete(bool val)
{
m_bRegistrationComplete = val;
}
void Init()
{
m_Occupancy = 0;
m_bRegistrationComplete = false;
for (int i=0; i<ToplevelSize; i++)
m_Buckets[i] = NULL;
}
void Kill()
{
for (int i=0; i<ToplevelSize; i++) {
Bucket *b = m_Buckets[i];
while (b) {
char *old = (char*) b;
b = b->obf_Next.Get();
delete[] old;
}
m_Buckets[i] = NULL;
}
m_Occupancy = 0;
}
void Insert(u64 hashcode,_T cmd)
{
Bucket * b = m_Buckets[hashcode & (ToplevelSize-1)];
// If this chain is empty, or the first bucket is full, allocate and patch in a new bucket
if (!b || b->obf_Count.Get() == PerBucket) {
Bucket *nb = (Bucket*) new char[sizeof(Bucket)];
nb->obf_Next.Set(m_Buckets[hashcode & (ToplevelSize-1)]);
nb->obf_Count.Set(0);
b = m_Buckets[hashcode & (ToplevelSize-1)] = nb;
}
b->obf_Hashes[b->obf_Count.Get()].Set(hashcode);
b->plainText_Hashes[b->obf_Count.Get()] = 0; //hashcode;
b->Data[b->obf_Count] = cmd;
b->obf_Count.Set(b->obf_Count.Get()+1); //inc count
}
_T Lookup(u64 hashcode)
{
Bucket *b = m_Buckets[hashcode & (ToplevelSize-1)];
while (b) {
for (u32 i=0; i<b->obf_Count.Get(); i++)
if (b->obf_Hashes[i].Get() == hashcode)
return b->Data[i];
b = b->obf_Next.Get();
}
return 0;
}
private:
Bucket* m_Buckets[ToplevelSize];
int m_Occupancy;
bool m_bRegistrationComplete;
};
}