Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Гайд Valorant — Алгоритм дешифровки GObjects для обновления UEDumper (C++)

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Фев 2026
Сообщения
126
Реакции
3
Очередные декрипторы GObjects подлетели, теперь можно перестать ныть на тему обновлений игры и самостоятельно фиксить UEDumper для генерации нормального СДК.

Видел, как многие новички на YouGame пытаются спастить что-то вменяемое под последние апдейты, но отлетают из-за кривых оффсетов или неверной дешифровки. Этот код — база для тех, кто понимает, как работают сигнатуры и реверс памяти.

Что внутри:
  1. Pattern Scanning: Автоматический поиск сигнатур для извлечения ключа и стейта.
  2. Bit Manipulation: Реализованы функции для реверса бит и сдвигов, чтобы корректно достать адрес из зашифрованного стейта.
  3. Branch Logic: Свитч-кейс, который обрабатывает хэши и вычисляет итоговый адрес.

Код:
Expand Collapse Copy
#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

Используйте с головой. Если не понимаете, как применить это в своем проекте, лучше не лезьте, чтобы не отлететь в бан по железу после первого же запуска.
 
Назад
Сверху Снизу