Всем уже давно известно как делать Glow Esp, но сегодня мы посмотрим на проблемы, которые возникли при написании этого чита, для менее популярных игр, таких как Left 4 Dead 2. В погоне за оптимизацией, отрисовка обводки происходит не постоянно, как например, это было в Sniper Elite 4. В Left 4 Dead 2 существует Glow Manager, который пуст. Да-да, если же в CS:GO структура заполнена указателями на свойства подсветки всех сущностей, то здесь же вообще ничего нет. А значит, простым изменением “выключателя” включающего подсветку тут не обойтись.
Для начала найдем указатель на Glow Manager, для этого найдем виртуальную таблицу класса CGlowManager и перейдем по второй виртуальной функции, в ней мы увидим глобальную переменную в которую пишется указатель на структуру Glow Manager.
Теперь необходимо найти функцию, обновляющую отрисовку обводки, в той же виртуальной таблице, под 5 индексом можно её найти. игнорируя nullbytes в таблице. Адрес потребуется для дальнейшего исследования алгоритма работы функции, чтобы c помощью подмены некоторых значений, заставить работать обводку на нас.
После восстановления функции, можем продолжать. Итак, на этом этапе необходимо понять, что нам потребуется в дальнейшем.
Начнем по порядку, итак, под 1 пунктом мы видим, что свойства обводки берутся из массива с сущностями. Далее, 2-й пункт, на котором держится вся работа функции, необходимо точно указывать количество подсвечиваемых сущностей, а как мы видели из первого пункта, что индекс указывает на структуру сущности, из-за чего если укажем значение меньше, чем находится указателей в pEntityArray, то часть из них обводится не будет, если больше, получим исключение Access Violation и вылет из игры.
Как собрать смещения из функций уже не будем обсуждать, раз статья в разделе для взрослых.
Имея все необходимое, можно подумать как код будет работать.
{
// Для начала выделим память в размере 128 байт, этого будет достаточно, движок все равно не сможет рисовать больше 32 сущностей.
auto argh = VirtualAllocEx(this->m_hProcess, 0, 128, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
auto item = 0;
this->m_writeMemory<DWORD, int>(this->m_hProcess, GlowManager + 0x18, item);
// Далее, запишем адрес выделенной памяти в структуру CGlowManager по смещению 0xC.
this->m_writeMemory<DWORD, DWORD>(this->m_hProcess, GlowManager + 0xC, reinterpret_cast<DWORD>(argh));
for (auto i = 0; i <= 4096; i++) {
auto entity = this->m_readMemory<DWORD, DWORD>(this->m_hProcess, EntityList + this->m_getHiddenStruct(i) * 8);
auto pClassID = this->m_readMemory<DWORD, DWORD>(this->m_hProcess, entity, {0x8, 0x4, 0x1, 0x14});
if (entity) {
// Отфильтруем сущности по классу Infected
if (pClassID == Infected) {
// Теперь необходимо получить смещение на свойства обводки
auto t = entity + 0x278;
// Заполняем структуру свойств, цветом, состоянием и включаем все
this->m_writeMemory<DWORD, int>(this->m_hProcess, entity + 0x278 + 0x4, state);
this->m_writeMemory<DWORD, int>(this->m_hProcess, entity + 0x278 + 0x10, activator);
this->m_writeMemory<DWORD, float>(this->m_hProcess, entity + 0x278 + 0x18, color[0]);
this->m_writeMemory<DWORD, float>(this->m_hProcess, entity + 0x278 + 0x18 + 0x4, color[1]);
this->m_writeMemory<DWORD, float>(this->m_hProcess, entity + 0x278 + 0x18 + 0x8, color[2]);
this->m_writeMemory<DWORD, int>(this->m_hProcess, entity + 0x278 + 0x28, activator);
//Поместим адрес свойств в argh и прибавим к количеству предметов в структуре 1
WriteProcessMemory(this->m_hProcess, static_cast<DWORD*>(argh) + item, &t, sizeof t, 0);
item++;
}
}
}
}
//И после того, как все циклы закончили свою работу, запишем количество сущностей в CGlowManager
this->m_writeMemory<DWORD, int>(this->m_hProcess, GlowManager + 0x18, item);
Запускаем, и хоба как два байта обнулить.
Таким образом можно подсвечивать абсолютно любые предметы на локации. Возможно, после статьи по спавну предметов в TES Skyrim доберемся до Sniper Elite 4, вот в этой игре подсветка работает не так просто, и очень интересно, исследовать её было одно удовольствие.