Начинающий
- Статус
- Оффлайн
- Регистрация
- 13 Фев 2026
- Сообщения
- 126
- Реакции
- 3
Очередные декрипторы GObjects подлетели, теперь можно перестать ныть на тему обновлений игры и самостоятельно фиксить UEDumper для генерации нормального СДК.
Видел, как многие новички на YouGame пытаются спастить что-то вменяемое под последние апдейты, но отлетают из-за кривых оффсетов или неверной дешифровки. Этот код — база для тех, кто понимает, как работают сигнатуры и реверс памяти.
Что внутри:
Используйте с головой. Если не понимаете, как применить это в своем проекте, лучше не лезьте, чтобы не отлететь в бан по железу после первого же запуска.
Видел, как многие новички на YouGame пытаются спастить что-то вменяемое под последние апдейты, но отлетают из-за кривых оффсетов или неверной дешифровки. Этот код — база для тех, кто понимает, как работают сигнатуры и реверс памяти.
Что внутри:
- Pattern Scanning: Автоматический поиск сигнатур для извлечения ключа и стейта.
- Bit Manipulation: Реализованы функции для реверса бит и сдвигов, чтобы корректно достать адрес из зашифрованного стейта.
- Branch Logic: Свитч-кейс, который обрабатывает хэши и вычисляет итоговый адрес.
Код:
#if GOBJECTS_DECRYPTION
// gobjects pointer decryption
static inline uint64_t decryptGObjectsAddress(uint64_t baseAddr)
{
const char sigBytes[] = "\x41\x8B\xF7\x48\xC1\xEE\x00\x48\x33\xF2";
const uint64_t sigMatch = Memory::patternScan(0, sigBytes, "xxxxxx?xxx");
uint64_t keyAddr = 0;
uint64_t stateBase = 0;
if (sigMatch)
{
const uint64_t keyInstr = sigMatch - 59;
const int32_t keyRipOff = Memory::read<int32_t>(keyInstr + 3);
keyAddr = keyInstr + 7 + keyRipOff;
const uint64_t leaInstr = sigMatch + 59;
const int32_t leaRipOff = Memory::read<int32_t>(leaInstr + 3);
stateBase = leaInstr + 7 + leaRipOff;
windows::LogWindow::Log(windows::LogWindow::logLevels::LOGLEVEL_INFO, "OBJECTSMANAGER",
"GObjects sig found, key@0x%p, state@0x%p", keyAddr, stateBase);
}
else
{
windows::LogWindow::Log(windows::LogWindow::logLevels::LOGLEVEL_WARNING, "OBJECTSMANAGER",
"GObjects sig not found, using OFFSET_GOBJECTS");
keyAddr = baseAddr + 0x78;
stateBase = baseAddr;
}
const uint32_t key = Memory::read<uint32_t>(keyAddr);
uint64_t state[7];
Memory::read(reinterpret_cast<void*>(stateBase + 0x40), state, sizeof(state));
const uint64_t hash = 0x2545F4914F6CDD1DULL *
(key ^ ((key ^ (key >> 15)) >> 12) ^ (key << 25));
const uint64_t idx = hash % 7;
uint64_t val = state[idx];
const uint32_t hi = static_cast<uint32_t>(hash >> 32);
auto bit_reverse_1 = [](uint64_t v) -> uint64_t {
uint64_t a = v >> 1;
uint64_t b = (v << 1) ^ a;
return (b & 0xAAAAAAAAAAAAAAAAULL) ^ a;
};
auto full_reverse = [&bit_reverse_1](uint64_t v) -> uint64_t {
v = bit_reverse_1(v);
uint64_t a = v >> 2;
uint64_t b = (v << 2) ^ a;
v = (b & 0xCCCCCCCCCCCCCCCCULL) ^ a;
a = v >> 4;
b = (v << 4) ^ a;
v = (b & 0xF0F0F0F0F0F0F0F0ULL) ^ a;
a = v >> 8;
b = (v << 8) ^ a;
v = (b & 0xFF00FF00FF00FF00ULL) ^ a;
v = (v >> 32) | (v << 32);
return ~v;
};
auto shift_amounts = [](uint32_t x) -> std::pair<uint8_t, uint8_t> {
uint64_t prod = static_cast<uint64_t>(x) * 0x4104105ULL;
uint32_t q = static_cast<uint32_t>(prod >> 32);
uint32_t q2 = ((x - q) >> 1) + q;
q2 >>= 5;
uint32_t rem = x - q2 * 63;
uint8_t shift_a = static_cast<uint8_t>((rem + 1) & 0x3F);
uint8_t shift_b = static_cast<uint8_t>((q2 * 63 - x + 63) & 0x3F);
return { shift_a, shift_b };
};
// pick branch based on hash
uint64_t result;
switch (idx) {
case 0: {
uint64_t r = (~static_cast<uint64_t>((hi - 1) & 0xFFFFFFFF));
r ^= val;
result = r + hi;
break;
}
case 1: {
result = ~bit_reverse_1(val);
break;
}
case 2: {
uint64_t br = bit_reverse_1(val);
auto [sa, sb] = shift_amounts(hi + static_cast<uint32_t>(idx));
result = (br << sb) | (br >> sa);
break;
}
case 3: {
result = full_reverse(val);
break;
}
case 4: {
uint32_t x = hi + 2 * static_cast<uint32_t>(idx);
uint64_t v = val - x;
uint64_t a = v >> 1;
uint64_t b = (v << 1) ^ a;
result = (b & 0xAAAAAAAAAAAAAAAAULL) ^ a;
break;
}
case 5: {
auto [sa, sb] = shift_amounts(hi + 2 * static_cast<uint32_t>(idx));
uint64_t rot = (val >> sb) | (val << sa);
result = rot + (hi + static_cast<uint32_t>(idx));
break;
}
case 6: {
result = ~bit_reverse_1(val);
break;
}
default:
result = val;
break;
}
uint64_t decrypted = result ^ static_cast<uint64_t>(key);
return decrypted;
}
#endif
Используйте с головой. Если не понимаете, как применить это в своем проекте, лучше не лезьте, чтобы не отлететь в бан по железу после первого же запуска.