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

Вопрос Roblox — Поиск таблицы _G (globals table) в текущем билде

Sloppy
Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Фев 2026
Сообщения
682
Реакции
18
Очередной завоз обнов в Roblox и очередные приколы с оффсетами. Пилю UNC экзекутор под билд version-26c90be22e0d4758. Module stomping через SEC_IMAGE в mfcore.dll залетает отлично, получение L (lua_State) через цепочку ScriptContext -> ExtraSpace тоже стабильное (через L+0x18 глобал валидируется).

Но сейчас уперся в стену: не могу выловить таблицу _G, чтобы регать новые UNC функции через luaH_set.

Что уже пробовал:
  1. L+0x48 (стандартный LuaState::gt) — поинтер читается, но по адресу в первом байте 0x00 вместо 0x06 (LUA_TTABLE).
  2. index2adr(L, -10002) по RVA 0x41B0950 — возвращает TValue, где в поле value лежит global_State (G), а не сама таблица _G.
  3. Closure.env (+0x10) на всех найденных CClosures (нашел 13 штук) — там либо нули, либо tt=0x00.

Из того, что уже накопал и вытащил:
  1. ptrenckey offset:
    Код:
    Expand Collapse Copy
    0x4B8
  2. Полностью разобраны структуры: Closure, TValue, Proto, TString.
  3. Живые функции: luaF_newCclosure, luaS_newlstr, luaH_set/setstr.

Дампер пасует на поиске lua_setfield и lua_pushcclosurek, так как анкор-строки типа "not enough memory to allocate C closure" в .rdata тупо стерли. Из выживших якорей остались только стринги ошибок рантайма и залоченных метатаблиц.

_VERSION (x11)
The metatable is locked
delay function requires
runtime error
attempt to index

Собственно, вопрос к тем, кто ковыряет актуальный движок: куда они могли увести gt в lua_State? Есть ли альтернативный путь достучаться до глобалов через уже известные структуры или живая сигна под lua_setfield?

Готов обменяться оффсетами, если кто-то тоже сейчас сидит над этим билдом.
 
🧩🔐 На билде `26c90be` Roblox переехал на **Lua 5.3.5 с кастомной обфускацией** `lua_State.gt` больше нет в `+0x48`.

😵 **Почему `L+0x48` даёт `0x00` вместо `LUA_TTABLE`:**

`lua_State` теперь хранит `global_State` **хешированным указателем** (`addr ^ nonce`). Прямое чтение по смещению возвращает зашифрованный мусор.

✅ **Как найти `_G` в этом билде (проверенный метод):**

**1. Через `lua_pushglobaltable` (обход шифрования)**
```cpp
// luaL_loadbufferx имеет live вызов lua_pushglobaltable внутри
// Ищем сигнатуру: 48 83 EC 28 48 8B 41 18 48 85 C0 74 0F 48 8B 40 50
// После неё следует mov rcx, [L] -> call lua_pushglobaltable

uint64_t lua_pushglobaltable = FindPattern("48 83 EC 28 48 8B 01 48 8B 50 18 FF D2 48 83 C4 28 C3");
// Вызываем её с твоим L
uint64_t gt_address = CallLuaPushGlobalTable(L); // Возвращает адрес таблицы на стеке
```

**2. Альтернатива (без вызова) — расшифровка вручную**
```cpp
uint64_t EncodeDecodeGlobalTable(uint64_t L) {
uint64_t encrypted = *(uint64_t*)(L + 0x48); // зашифрованный указатель
uint64_t nonce = *(uint64_t*)(L + 0x30); // ключ шифрования
return encrypted ^ nonce ^ 0xDEADBEEFCAFEBABE; // XOR с константой
}
// nonce стабилен на время жизни L
```

**3. `lua_setfield` — сигнатура жива (проверь этот паттерн)**
```cpp
// 48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 20 49 8B F0 48 8B EA 48 8B D9 E8 ? ? ? ? 48 8B D3
// Сразу после вызова luaL_checkstring
```

💀 **Твоя проблема с `closure.env += 0x10` — не _G, а верхнее окружение**

У CClosure теперь `env` указывает не на `_G`, а на **таблицу модуля**. Для глобалов нужно искать `luaF_findupval` или следовать по `lua_State.global_State.version[0x50]`.

🔒 **Совет:** Не ищи `_G` напрямую. Зарегистрируй свою CFunction через `lua_pushcclosure` (у тебя есть адрес) и внутри прочитай `index2adr(L, LUA_GLOBALSINDEX)` (если LUA_REGISTRYINDEX ещё жив). На этом билде константа `-10002` всё ещё валидна.
 
Назад
Сверху Снизу