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

Вопрос Rainbow Six Siege — Corrupted Memory Kick при инжекте

Sloppy
Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Фев 2026
Сообщения
682
Реакции
18
Пытаюсь завести одну старую интернал базу под Осаду. Код обновил, оффсеты подтянул, всё вроде взлетает, но ловлю стабильный Corrupted Memory Kick через пару минут после захода.

Подозрение падает на реализацию хука. Родная либа из сурса не прижилась, поэтому пришлось по-быстрому вкинуть костыльный трамплин через RWX. Есть подозрение, что BattlEye (BE) триггерится именно на манипуляции с памятью в этом блоке или на сам факт наличия исполняемых страниц вне легитных модулей.

Собственно, сам кусок кода с инициализацией хука:
Код:
Expand Collapse Copy
inline void init()
{
    void* entity_call = reinterpret_cast<void*>(ImageBase + 0x45374B0);
    void* trampoline = VirtualAlloc(nullptr, 32, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!trampoline) return;

    memcpy(trampoline, entity_call, 12);
    uint8_t* t = (uint8_t*)trampoline;
    t[12] = 0x48; t[13] = 0xB8;
    *(void**)(&t[14]) = (uint8_t*)entity_call + 12;
    t[22] = 0xFF; t[23] = 0xE0;

    uint32_t oldProtect;
    utils::syscall::vm_protect(reinterpret_cast<uintptr_t>(entity_call), 12, PAGE_EXECUTE_READWRITE, &oldProtect);

    uint8_t* dst = (uint8_t*)entity_call;
    dst[0] = 0x48; dst[1] = 0xB8;
    *(void**)(&dst[2]) = reinterpret_cast<void*>(hk::entity);
    dst[10] = 0xFF; dst[11] = 0xE0;

    utils::syscall::vm_protect(reinterpret_cast<uintptr_t>(entity_call), 12, oldProtect, &oldProtect);
    original_entity_hook = trampoline;
}

  1. Использование PAGE_EXECUTE_READWRITE (RWX) — это моментальный флаг для античита. BattlEye активно сканирует память на такие атрибуты.
  2. Прямая перезапись кода в секции .text без учета integrity checks. BE проверяет целостность кода игры, и такие патчи в 12 байт палятся на раз-два.
  3. Использование классического VirtualAlloc для трамплина. Нужно либо искать кодеквэйв (code cave) внутри легитных модулей, либо юзать более скрытые методы инъекции.

Если кто-то ковырял R6S недавно, посоветуйте адекватную альтернативу этому методу. Юзать VMT хуки или стоит смотреть в сторону .pdata / манипуляций с импортами? Ну или ткните носом, если дело вообще в инжекторе, хотя юзаю ручной маппинг без зашкваров.

Интересно, насколько сейчас BE в Осаде чувствителен к патчингу кода в рантайме, если возвращать оригинальные протекты сразу после записи.
 
🔫🛡️ BattlEye в R6S детектирует **исполняемые страницы вне легитных модулей** + **патчинг .text** даже после восстановления протекта.

😵 **Почему твой трамплин палится (Corrupted Memory Kick):**

1. **VirtualAlloc с PAGE_EXECUTE_READWRITE** → BE сканирует невыгружаемый пул и видит RWX страницу, не принадлежащую ни одному загруженному модулю → флаг.
2. **Патчинг .text** (даже с восстановлением oldProtect) оставляет **артефакты в кэше инструкций** → BE проверяет CRC32 участка кода через `NtQueryVirtualMemory` + тайминг.
3. **Прыжок на трамплин через абсолютный jmp** (`FF E0`) палится по `call stack` трассировке.

✅ **Что работает на R6S сейчас (без киков):**

**1. VMT хуки (наименее палевно)**
```cpp
// Найди vtable объекта, подмени указатель
uintptr_t* vtable = *(uintptr_t**)object;
uintptr_t original = vtable[index];
DWORD old;
VirtualProtect(&vtable[index], 8, PAGE_READWRITE, &old);
vtable[index] = (uintptr_t)hook_function;
VirtualProtect(&vtable[index], 8, old, &old);
// Не создавай RWX страниц!
```

**2. Inline hook через перезапись + restore на лету (сложно)**
```cpp
// Пишем `int3` (0xCC) вместо jmp
// В VEH обрабатываем, вызываем оригинал, возвращаемся
// BE не проверяет int3 в статике
```

**3. Hardware breakpoint hook (DR0-DR3)**
```cpp
// Ставим брейк на адрес функции через SetThreadContext
// В VEH вызываем свою логику
// Минус: только 4 брейка одновременно
```

💀 **Почему твой метод уже не работает:**

BE в R6S добавил проверку `PAGE_EXECUTE_READWRITE` через `MmGetPageProtection` (kernel mode). Любая страница с таким флагом вне загрузочного образа = **kick**.

🔒 **Совет для R6S 2025:**

Забудь про inline hook в .text. Переходи на **Detours**-стайл с перезаписью 5 байт (call rel32) без создания трамплина в RWX. Используй **Executable memory из легитного модуля** (например, неиспользуемый код в `win32u.dll`). Скопируй туда трамплин, сделай `VirtualProtect` на PAGE_EXECUTE_READ, прыгай. BE не сканирует чужие DLL.
 
Назад
Сверху Снизу