• Я зарабатываю 100 000 RUB / месяц на этом сайте!

    А знаешь как? Я всего-лишь публикую (создаю темы), а админ мне платит. Трачу деньги на мороженое, робуксы и сервера в Minecraft. А ещё на паль из Китая. 

    Хочешь так же? Пиши и узнавай условия: https://t.me/alex_redact
    Реклама: https://t.me/yougame_official

Гайд Дневник разработчика: проблемы при разработке экстернал читов

Разработчик
Разработчик
Статус
Оффлайн
Регистрация
1 Сен 2018
Сообщения
1,664
Реакции
908
Более форматированная версия -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Всем привет! Уже около шести месяцев я занимаюсь разработкой своего экстернал чита Spurdo как хобби в свободное от работы время. Хочу поделиться с вами проблемами, с которыми я столкнулся, и размышлениями о том, как их решить.

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

Case №1: Проблема поддержки полноэкранного режима
Первый способ
В большинстве масс-маркет читов для Counter-Strike 2 существует проблема поддержки полноэкранного режима. Например, X1 утверждает, что эта проблема подвластна всем внешним читам и предлагает использовать масштабирование с помощью видеокарты.
https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff2be0e4d-16b7-4c34-93c6-de446615b2c6%2Fda6a034a-ddc3-474f-b7bb-2ca6bc9d14b9%2FUntitled.png

https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff2be0e4d-16b7-4c34-93c6-de446615b2c6%2Fd8502e39-c6c0-45a4-b19a-6a28953c73d1%2FScreenshot_2024-05-16_at_06-07-14_%25D0%259A%25D0%25B0%25D0%25BA_%25D0%25B8%25D1%2581%25D0%25BF%25D0%25BE%25D0%25BB%25D1%258C%25D0%25B7%25D0%25BE%25D0%25B2%25D0%25B0%25D1%2582%25D1%258C_External_%25D1%2587%25D0%25B8%25D1%2582%25D1%258B_%25D0%25BD%25D0%25B0_%25D0%259A%25D0%25A1-2_%25D0%25B2_4_3.png


В целом, это был первый вариант решения проблемы, но есть некоторые "но":
  • Он требует специфических действий со стороны пользователя. Вы ведь не думаете, что ему интересно что-то дополнительно исправлять при покупке p2c?
  • Конкретно этот способ подходит только для обладателей видеокарты от Nvidia.
Чужой оверлей
Второй способ решения этой проблемы - это просто перехватить оверлей легитимной компании, которая уже исправила за вас эти проблемы =). Фактически, этот способ является стандартом индустрии и практикуется в большинстве читов (в основном в играх, защищенных EAC / BE).

Перехватить можно как минимум двумя способами:
  • Выполнить так называемый “hijacking” окна игры и рисовать там свой оверлей. При этом подходе вы полностью можете контролировать атрибуты этого окна.
    Пожалуйста, авторизуйтесь для просмотра ссылки.
  • Записывать в IPC (inter-process communication) буфер оверлея, чтобы он позже отрисовал кадр. Плюсы этого подхода в большей стабильности происходящего. Для неразбирающегося в теме человека может показаться, что задержка при использовании оверлея по сравнению с первым подходом уменьшается до минимального, и возникает полная синхронизация ESP с моделью в игре. Мы обсудим это позже. Минусы: придется реверсить(((, вы ограничены функционалом, заложенным разработчиками, структуры могут разниться от версии ПО, и нужно будет заставлять пользователей скачивать новую версию оверлея.
Этот способ имеет похожий минус с предыдущим вариантом - пользователю нужно дополнительно что-то делать и устанавливать.

Злоупотребление DWM
В названии указана страшная аббревиатура DWM. Что же это такое? Desktop Window Manager (DWM) - это часть операционных систем Windows. Он отвечает за управление окнами на рабочем столе. Раньше его функция состояла только в том, чтобы обеспечить сглаживание окон и прочие визуальные эффекты, такие как Aero Glass.

С выходом Windows 8, DWM стал обязательным компонентом Windows, в тот же период времени они добавили полную поддержку глубины окон, т.е. сделали условные слои, как в фотошопе, которые позволяли полноценно накладывать одни окна на другие. Слои поделены на группы по порядку отрисовки на экране.

Вот вам enum с названиями этих групп, они, кстати, называются ZBID:
C++:
Expand Collapse Copy
/*

from the lowest to the highest z-order:

    ZBID_DESKTOP

    ZBID_IMMERSIVE_BACKGROUND

    ZBID_IMMERSIVE_APPCHROME

    ZBID_IMMERSIVE_MOGO

    ZBID_IMMERSIVE_INACTIVEMOBODY

    ZBID_IMMERSIVE_NOTIFICATION

    ZBID_IMMERSIVE_EDGY

    ZBID_SYSTEM_TOOLS

    ZBID_LOCK (Windows 10 only)

    ZBID_ABOVELOCK_UX (Windows 10 only)

    ZBID_IMMERSIVE_IHM

    ZBID_GENUINE_WINDOWS

    ZBID_UIACCESS

*/


// @author: <https://blog.adeltax.com/window-z-order-in-windows-10/>

enum ZBID

{

     ZBID_DEFAULT = 0,

     ZBID_DESKTOP = 1,

     ZBID_UIACCESS = 2,

     ZBID_IMMERSIVE_IHM = 3,

     ZBID_IMMERSIVE_NOTIFICATION = 4,

     ZBID_IMMERSIVE_APPCHROME = 5,

     ZBID_IMMERSIVE_MOGO = 6,

     ZBID_IMMERSIVE_EDGY = 7,

     ZBID_IMMERSIVE_INACTIVEMOBODY = 8,

     ZBID_IMMERSIVE_INACTIVEDOCK = 9,

     ZBID_IMMERSIVE_ACTIVEMOBODY = 10,

     ZBID_IMMERSIVE_ACTIVEDOCK = 11,

     ZBID_IMMERSIVE_BACKGROUND = 12,

     ZBID_IMMERSIVE_SEARCH = 13,

     ZBID_GENUINE_WINDOWS = 14,

     ZBID_IMMERSIVE_RESTRICTED = 15,

     ZBID_SYSTEM_TOOLS = 16,


     //Windows 10+

     ZBID_LOCK = 17,

     ZBID_ABOVELOCK_UX = 18

};

ZBID_DESKTOP - самая первая группа глубины окон, именно в ней рисуются все окна!
1715838190316.png

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

Вы можете воспользоваться недокументированной функцией CreateWindowInBand из user32.dll, которая подозрительно сильно похожа на CreateWindowEx, вот её прототип:
C++:
Expand Collapse Copy
HWND WINAPI CreateWindowInBand(

     DWORD dwExStyle,

     LPCWSTR lpClassName,

     LPCWSTR lpWindowName,

     DWORD dwStyle,

     int x,

     int y,

     int nWidth,

     int nHeight,

     HWND hWndParent,

     HMENU hMenu,

     HINSTANCE hInstance,

     LPVOID lpParam,

     DWORD dwBand);

При разработке я не заметил никаких минусов этого подхода, но в теории их всего 2:
  1. Поддержка только Windows 8+
  2. Чтобы это работало в полноэкранном режиме, нужно пользоваться “оптимизацией полноэкранного режима”, что в целом логично.
Case №2: Оптимизация. Да зачем она вообще нужна?
В какой-то момент вы столкнетесь с проблемой: ваш чит может начать лагать у пользователей. И эти 15 миллиардов кадров, которые вы видите на своем i9-15900k 400w, ваши пользователи могут не увидеть на своем Core 2 Duo. Что же делать? Конечно, оптимизировать. Я ведь не просто так это написал в заголовке кейса. Но нам нужно ознакомиться с мемом про оптимизацию, прежде чем приступить.
1715838245574.png

Теперь можно.

Побольше swap context
У вас же есть свой драйвер, верно??? А может быть, и гипервизор?? Хипстеры. Даже если вы ответили "нет", в любом случае операция изменения памяти (независимо от того, чтение это или запись) занимает очень много процессорного времени. Но знаете что?

Если вы прочтете не 2 байта за один вызов, а 50 тысяч, то операция займет столько же времени. И вот на этом основан простой метод оптимизации. Почему бы нам не объединить чтение каждого оффсета в чтение одного большого класса? В своем чите я использовал преимущества схемы в Counter-Strike 2, написал короткий подсчет размера всех нетворк-классов и написал кодген под них.

В итоге удалось сократить количество вызовов чтения памяти с 60+ до 10-13. А что по цифрам?
До оптимизации: 1300000-1600000ns
После: 70000-110000
Разница: 1454.54% - 1857.14%

И самое главное, что при необходимости взять что-то из класса игрока количество вызовов чтения памяти не будет расти, что очень важно для большого экстернал-чита

Таймеры, часы, где же суть?
Читатель, погружаемся в лор. Представь: ты создаешь свою OC, уже сделал потоки, процессы, но появилась проблема - они все время работают и нагружают систему, даже когда не активны. Тебе нужно добавить механизм, который бы контролировал их состояние. Хорошо, придумали: в процессоре есть прерывания, будем вызывать их через каждый n-интервал и будить потоки, которые находились в спящем режиме. Но возникает проблема: что, если один поток требует одного интервала, а другой - другого? Например, чтобы включать музыку, нужно быстро обрабатывать все и минимальное время на сон, а в автозаварке кофе можно поставить больший таймер.


Если тебе пришло в голову поставить для всей системы самый низкий интервал среди приложений, поздравляю с прохождением теста - ты индус из Microsoft. Подход, казалось бы, работает, но нагружает систему, когда это не нужно.
1715838289146.png

В Windows получить текущий интервал можно с помощью утилиты clockres с System Internals:
https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff2be0e4d-16b7-4c34-93c6-de446615b2c6%2F308a993e-65e1-4840-a60b-d9c83ceaa0c2%2FUntitled.png

Причем здесь вообще экстерналы и оптимизация? Чтобы процессор не нагружался и правильно ограничивать FPS, вы используете Sleep или std::this_thread::sleep_for - не имеет значения. Так вот, когда ваш поток засыпает на n ms, он может проснуться ровно по таймеру, а может и позже, ведь планировщик вызывается интервалами. Если ваш сон дольше, чем один интервал, то он будет перенесен на другой, то есть:
C++:
Expand Collapse Copy
if( currentSleep <= 0.f)
       Resume();

// else ignore. Even with 100 nanoseconds left.
// so it will actually take currentSleep + currentTImer

С этим можно бороться следующими способами:
  • Установить минимальный интервал с помощью timeBeginPeriod, но в большинстве случаев ваш сон не будет соответствовать желаемому.
  • Использовать прерывания, для этого есть метод _mm_pause. Проверять, прошло ли нужное время, можно с помощью QueryPerformanceCounter, или посчитать руками заранее. При этом подходе вы будете ужасным человеком, вы будете мешать планировщику Windows.
  • Вызывать NtDelayExecution с -1, чтобы спать на минимальное количество времени, но для этого нужно просчитывать нужное количество циклов для сна, ну или костыль с QueryPerformanceCounter =)
Case №3: Мой оверлей лагает. Что же не так?
Буду честен, над этой проблемой мы в проекте провели не одну неделю, перепробовали всё: начиная со сменой движка отрисовки, заканчивая переписыванием полностью кодовой базы. В один момент, спустя месяцы, я снова решил попробовать свои силы в этой проблеме. При диалоге и рассуждении с моим хорошо знакомым seniusz, ко мне пришло озарение, что это Windows мне что-то портит. Спустя пару минут гугления обновлений Windows, я нашёл то самое! Чтобы исправить маленький FPS в оверлее, вам нужно сделать две вещи:
  • Отключить Game Mode, он доступен с Windows 10 1809
  • Отключить планирование графического процессора с аппаратным ускорением

К сожалению, проблема до сих пор остается частично. Что-то в Windows обрезает FPS ровно в два раза, выделяя больше ресурсов на игру. Если вы знаете, как это решить - отпишите мне, буду благодарен!

Case №4: Защищайтесь сударь
В этом кейсе нет конкретики. В большинстве внешних читов, которые мне довелось протестировать, я замечал много проблем с безопасностью от анти-чита (например, X1, Pellix, PUSSYCAT, AIMSTAR и т.д.).

Основная проблема: мало кому нужен чит, который не способен обеспечить защиту от анти-чита.
https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff2be0e4d-16b7-4c34-93c6-de446615b2c6%2F84ba9203-fde9-422a-a08c-ba3a7d2d4cb1%2Fpasted-everything-here-is-pasted-and-detected.gif


Вывод
В разработке экстернал читов есть множество проблем, но все они решаемы. Главное думать головой, и пытаться понять что делаешь.
До скорой встречи, Make cheats, not war!

Мой блог ( зачем он здесь?? ) -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Источники:
Пожалуйста, авторизуйтесь для просмотра ссылки.

Пожалуйста, авторизуйтесь для просмотра ссылки.

Пожалуйста, авторизуйтесь для просмотра ссылки.
( фраза Make cheats, not war! )
 
Более форматированная версия -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Всем привет! Уже около шести месяцев я занимаюсь разработкой своего экстернал чита Spurdo как хобби в свободное от работы время. Хочу поделиться с вами проблемами, с которыми я столкнулся, и размышлениями о том, как их решить.

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

Case №1: Проблема поддержки полноэкранного режима
Первый способ
В большинстве масс-маркет читов для Counter-Strike 2 существует проблема поддержки полноэкранного режима. Например, X1 утверждает, что эта проблема подвластна всем внешним читам и предлагает использовать масштабирование с помощью видеокарты.
https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff2be0e4d-16b7-4c34-93c6-de446615b2c6%2Fda6a034a-ddc3-474f-b7bb-2ca6bc9d14b9%2FUntitled.png

https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff2be0e4d-16b7-4c34-93c6-de446615b2c6%2Fd8502e39-c6c0-45a4-b19a-6a28953c73d1%2FScreenshot_2024-05-16_at_06-07-14_%25D0%259A%25D0%25B0%25D0%25BA_%25D0%25B8%25D1%2581%25D0%25BF%25D0%25BE%25D0%25BB%25D1%258C%25D0%25B7%25D0%25BE%25D0%25B2%25D0%25B0%25D1%2582%25D1%258C_External_%25D1%2587%25D0%25B8%25D1%2582%25D1%258B_%25D0%25BD%25D0%25B0_%25D0%259A%25D0%25A1-2_%25D0%25B2_4_3.png


В целом, это был первый вариант решения проблемы, но есть некоторые "но":
  • Он требует специфических действий со стороны пользователя. Вы ведь не думаете, что ему интересно что-то дополнительно исправлять при покупке p2c?
  • Конкретно этот способ подходит только для обладателей видеокарты от Nvidia.
Чужой оверлей
Второй способ решения этой проблемы - это просто перехватить оверлей легитимной компании, которая уже исправила за вас эти проблемы =). Фактически, этот способ является стандартом индустрии и практикуется в большинстве читов (в основном в играх, защищенных EAC / BE).

Перехватить можно как минимум двумя способами:
  • Выполнить так называемый “hijacking” окна игры и рисовать там свой оверлей. При этом подходе вы полностью можете контролировать атрибуты этого окна.
    Пожалуйста, авторизуйтесь для просмотра ссылки.
  • Записывать в IPC (inter-process communication) буфер оверлея, чтобы он позже отрисовал кадр. Плюсы этого подхода в большей стабильности происходящего. Для неразбирающегося в теме человека может показаться, что задержка при использовании оверлея по сравнению с первым подходом уменьшается до минимального, и возникает полная синхронизация ESP с моделью в игре. Мы обсудим это позже. Минусы: придется реверсить(((, вы ограничены функционалом, заложенным разработчиками, структуры могут разниться от версии ПО, и нужно будет заставлять пользователей скачивать новую версию оверлея.
Этот способ имеет похожий минус с предыдущим вариантом - пользователю нужно дополнительно что-то делать и устанавливать.

Злоупотребление DWM
В названии указана страшная аббревиатура DWM. Что же это такое? Desktop Window Manager (DWM) - это часть операционных систем Windows. Он отвечает за управление окнами на рабочем столе. Раньше его функция состояла только в том, чтобы обеспечить сглаживание окон и прочие визуальные эффекты, такие как Aero Glass.

С выходом Windows 8, DWM стал обязательным компонентом Windows, в тот же период времени они добавили полную поддержку глубины окон, т.е. сделали условные слои, как в фотошопе, которые позволяли полноценно накладывать одни окна на другие. Слои поделены на группы по порядку отрисовки на экране.

Вот вам enum с названиями этих групп, они, кстати, называются ZBID:
C++:
Expand Collapse Copy
/*

from the lowest to the highest z-order:

    ZBID_DESKTOP

    ZBID_IMMERSIVE_BACKGROUND

    ZBID_IMMERSIVE_APPCHROME

    ZBID_IMMERSIVE_MOGO

    ZBID_IMMERSIVE_INACTIVEMOBODY

    ZBID_IMMERSIVE_NOTIFICATION

    ZBID_IMMERSIVE_EDGY

    ZBID_SYSTEM_TOOLS

    ZBID_LOCK (Windows 10 only)

    ZBID_ABOVELOCK_UX (Windows 10 only)

    ZBID_IMMERSIVE_IHM

    ZBID_GENUINE_WINDOWS

    ZBID_UIACCESS

*/


// @author: <https://blog.adeltax.com/window-z-order-in-windows-10/>

enum ZBID

{

     ZBID_DEFAULT = 0,

     ZBID_DESKTOP = 1,

     ZBID_UIACCESS = 2,

     ZBID_IMMERSIVE_IHM = 3,

     ZBID_IMMERSIVE_NOTIFICATION = 4,

     ZBID_IMMERSIVE_APPCHROME = 5,

     ZBID_IMMERSIVE_MOGO = 6,

     ZBID_IMMERSIVE_EDGY = 7,

     ZBID_IMMERSIVE_INACTIVEMOBODY = 8,

     ZBID_IMMERSIVE_INACTIVEDOCK = 9,

     ZBID_IMMERSIVE_ACTIVEMOBODY = 10,

     ZBID_IMMERSIVE_ACTIVEDOCK = 11,

     ZBID_IMMERSIVE_BACKGROUND = 12,

     ZBID_IMMERSIVE_SEARCH = 13,

     ZBID_GENUINE_WINDOWS = 14,

     ZBID_IMMERSIVE_RESTRICTED = 15,

     ZBID_SYSTEM_TOOLS = 16,


     //Windows 10+

     ZBID_LOCK = 17,

     ZBID_ABOVELOCK_UX = 18

};

ZBID_DESKTOP - самая первая группа глубины окон, именно в ней рисуются все окна!
Посмотреть вложение 276995
Вы могли заметить, что я к коду приложил порядок отрисовки на экране, и последним на нём рисуется ZBID_UIACCESS. Если мы создадим окно с этим атрибутом, то мы сможем просто взять и нарисовать наш оверлей поверх экрана как системный. Но как же его создать?

Вы можете воспользоваться недокументированной функцией CreateWindowInBand из user32.dll, которая подозрительно сильно похожа на CreateWindowEx, вот её прототип:
C++:
Expand Collapse Copy
HWND WINAPI CreateWindowInBand(

     DWORD dwExStyle,

     LPCWSTR lpClassName,

     LPCWSTR lpWindowName,

     DWORD dwStyle,

     int x,

     int y,

     int nWidth,

     int nHeight,

     HWND hWndParent,

     HMENU hMenu,

     HINSTANCE hInstance,

     LPVOID lpParam,

     DWORD dwBand);

При разработке я не заметил никаких минусов этого подхода, но в теории их всего 2:
  1. Поддержка только Windows 8+
  2. Чтобы это работало в полноэкранном режиме, нужно пользоваться “оптимизацией полноэкранного режима”, что в целом логично.
Case №2: Оптимизация. Да зачем она вообще нужна?
В какой-то момент вы столкнетесь с проблемой: ваш чит может начать лагать у пользователей. И эти 15 миллиардов кадров, которые вы видите на своем i9-15900k 400w, ваши пользователи могут не увидеть на своем Core 2 Duo. Что же делать? Конечно, оптимизировать. Я ведь не просто так это написал в заголовке кейса. Но нам нужно ознакомиться с мемом про оптимизацию, прежде чем приступить.
Посмотреть вложение 276996
Теперь можно.

Побольше swap context
У вас же есть свой драйвер, верно??? А может быть, и гипервизор?? Хипстеры. Даже если вы ответили "нет", в любом случае операция изменения памяти (независимо от того, чтение это или запись) занимает очень много процессорного времени. Но знаете что?

Если вы прочтете не 2 байта за один вызов, а 50 тысяч, то операция займет столько же времени. И вот на этом основан простой метод оптимизации. Почему бы нам не объединить чтение каждого оффсета в чтение одного большого класса? В своем чите я использовал преимущества схемы в Counter-Strike 2, написал короткий подсчет размера всех нетворк-классов и написал кодген под них.

В итоге удалось сократить количество вызовов чтения памяти с 60+ до 10-13. А что по цифрам?
До оптимизации: 1300000-1600000ns
После: 70000-110000
Разница: 1454.54% - 1857.14%

И самое главное, что при необходимости взять что-то из класса игрока количество вызовов чтения памяти не будет расти, что очень важно для большого экстернал-чита

Таймеры, часы, где же суть?
Читатель, погружаемся в лор. Представь: ты создаешь свою OC, уже сделал потоки, процессы, но появилась проблема - они все время работают и нагружают систему, даже когда не активны. Тебе нужно добавить механизм, который бы контролировал их состояние. Хорошо, придумали: в процессоре есть прерывания, будем вызывать их через каждый n-интервал и будить потоки, которые находились в спящем режиме. Но возникает проблема: что, если один поток требует одного интервала, а другой - другого? Например, чтобы включать музыку, нужно быстро обрабатывать все и минимальное время на сон, а в автозаварке кофе можно поставить больший таймер.


Если тебе пришло в голову поставить для всей системы самый низкий интервал среди приложений, поздравляю с прохождением теста - ты индус из Microsoft. Подход, казалось бы, работает, но нагружает систему, когда это не нужно.
Посмотреть вложение 276997
В Windows получить текущий интервал можно с помощью утилиты clockres с System Internals:
https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff2be0e4d-16b7-4c34-93c6-de446615b2c6%2F308a993e-65e1-4840-a60b-d9c83ceaa0c2%2FUntitled.png

Причем здесь вообще экстерналы и оптимизация? Чтобы процессор не нагружался и правильно ограничивать FPS, вы используете Sleep или std::this_thread::sleep_for - не имеет значения. Так вот, когда ваш поток засыпает на n ms, он может проснуться ровно по таймеру, а может и позже, ведь планировщик вызывается интервалами. Если ваш сон дольше, чем один интервал, то он будет перенесен на другой, то есть:
C++:
Expand Collapse Copy
if( currentSleep <= 0.f)
       Resume();

// else ignore. Even with 100 nanoseconds left.
// so it will actually take currentSleep + currentTImer

С этим можно бороться следующими способами:
  • Установить минимальный интервал с помощью timeBeginPeriod, но в большинстве случаев ваш сон не будет соответствовать желаемому.
  • Использовать прерывания, для этого есть метод _mm_pause. Проверять, прошло ли нужное время, можно с помощью QueryPerformanceCounter, или посчитать руками заранее. При этом подходе вы будете ужасным человеком, вы будете мешать планировщику Windows.
  • Вызывать NtDelayExecution с -1, чтобы спать на минимальное количество времени, но для этого нужно просчитывать нужное количество циклов для сна, ну или костыль с QueryPerformanceCounter =)
Case №3: Мой оверлей лагает. Что же не так?
Буду честен, над этой проблемой мы в проекте провели не одну неделю, перепробовали всё: начиная со сменой движка отрисовки, заканчивая переписыванием полностью кодовой базы. В один момент, спустя месяцы, я снова решил попробовать свои силы в этой проблеме. При диалоге и рассуждении с моим хорошо знакомым seniusz, ко мне пришло озарение, что это Windows мне что-то портит. Спустя пару минут гугления обновлений Windows, я нашёл то самое! Чтобы исправить маленький FPS в оверлее, вам нужно сделать две вещи:
  • Отключить Game Mode, он доступен с Windows 10 1809
  • Отключить планирование графического процессора с аппаратным ускорением

К сожалению, проблема до сих пор остается частично. Что-то в Windows обрезает FPS ровно в два раза, выделяя больше ресурсов на игру. Если вы знаете, как это решить - отпишите мне, буду благодарен!

Case №4: Защищайтесь сударь
В этом кейсе нет конкретики. В большинстве внешних читов, которые мне довелось протестировать, я замечал много проблем с безопасностью от анти-чита (например, X1, Pellix, PUSSYCAT, AIMSTAR и т.д.).

Основная проблема: мало кому нужен чит, который не способен обеспечить защиту от анти-чита.
https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff2be0e4d-16b7-4c34-93c6-de446615b2c6%2F84ba9203-fde9-422a-a08c-ba3a7d2d4cb1%2Fpasted-everything-here-is-pasted-and-detected.gif


Вывод
В разработке экстернал читов есть множество проблем, но все они решаемы. Главное думать головой, и пытаться понять что делаешь.
До скорой встречи, Make cheats, not war!

Мой блог ( зачем он здесь?? ) -
Пожалуйста, авторизуйтесь для просмотра ссылки.


Источники:
Пожалуйста, авторизуйтесь для просмотра ссылки.

Пожалуйста, авторизуйтесь для просмотра ссылки.

Пожалуйста, авторизуйтесь для просмотра ссылки.
( фраза Make cheats, not war! )
Что касается уиаксеса с ним есть один забавный прикол: если делать его так как ты показал в посте, у тебя в процессе висит флаг который можно получить даже при QUERY_LIMITED_INFORMATION :)

Что касается пелликса, мы буквально сделали минимум защиты не особо заморачиваясь, если ты про ксго версию то там вообще беда была, в кс2 лучше но мы всё ещё не занимаемся вещами по типу скрытия процесса от итерации. Чит делается под банку пива вечерами, и мы больше занимаемся добавлением прикольного функционала (по типу экстернал аволла) чем защитой. Хочу отметить что при всём при этом за 2 года у чита ни разу не было банвейва (хотя и по причине того что валве пофигу)

А так пост хороший, сталкивался буквально со всем из вышеперечисленного.
P.S. Что касается точного времени для слипа можно заюзать NtSetTimerResolution после чего вызывать NtDelayExecution в стиле

Sleep:
Expand Collapse Copy
LARGE_INTEGER interval;
interval.QuadPart = -1ll * (int)(flMilliseconds * 10000.0f);
NtDelayExecution(true, &interval);
 
Последнее редактирование:
P.S. Что касается точного времени для слипа можно заюзать NtSetTimerResolution после чего вызывать NtDelayExecution в стиле

Sleep:
Expand Collapse Copy
LARGE_INTEGER interval;
interval.QuadPart = -1ll * (int)(flMilliseconds * 10000.0f);
NtDelayExecution(true, &interval);
Он не точный, по факту NtDelayExecution это просто более низкий уровень для Sleep, проблема с пропуском на следующий интервал будет присутствовать
 
Он не точный, по факту NtDelayExecution это просто более низкий уровень для Sleep, проблема с пропуском на следующий интервал будет присутствовать
Он будет по 0.5мс клоку при этом не сжирая цпу на цикл с _mm_pause.
_mm_pause подходит в случае если ты делаешь условный спинлок но для слипов он как по мне слишком много цпу жрёт.

Например вот я сделал бесконечный цикл с _mm_pause() на своём ноуте с Ryzen 7 6800h
1715841628227.png

Да, там будет идеальная точность но как правило это не нужно. Теперь пример с "точным" NtDelayExection на 0.5 мс клоке:

1715841708930.png

Даже при том что он может пропустить пол миллисекунды, мы выигрываем в нагрузке на цпу в (?) раз. Не могу представить ситуацию где прийдётся делать более 1500 циклов с слипом впринципе. К слову я замерял по приколу и получилось что если сравнивать мёртвый цикл с _mm_pause и без каких бы то слипов вообще, нагрузка на цпу отличается аж на целых 3%(!), так что если тебе действительно нужно сделать эти 360к циклов в секунду (что странным образом соответствует частоте процессора) то _mm_pause погоды не делает (с ним происходит в среднем 349к циклов в секунду при соответственно 3% выигрыше в проценте загруженности ядра)
 
Последнее редактирование:
читать лень, но надосуге я это прочту, респект за целый конспект
 
Он будет по 0.5мс клоку при этом не сжирая цпу на цикл с _mm_pause.
_mm_pause подходит в случае если ты делаешь условный спинлок но для слипов он как по мне слишком много цпу жрёт.

Например вот я сделал бесконечный цикл с _mm_pause() на своём ноуте с Ryzen 7 6800h
Посмотреть вложение 276999
Да, там будет идеальная точность но как правило это не нужно. Теперь пример с "точным" NtDelayExection на 0.5 мс клоке:

Посмотреть вложение 277000
Даже при том что он может пропустить пол миллисекунды, мы выигрываем в нагрузке на цпу в (?) раз. Не могу представить ситуацию где прийдётся делать более 1500 циклов с слипом впринципе. К слову я замерял по приколу и получилось что если сравнивать мёртвый цикл с _mm_pause и без каких бы то слипов вообще, нагрузка на цпу отличается аж на целых 3%(!), так что если тебе действительно нужно сделать эти 360к циклов в секунду (что странным образом соответствует частоте процессора) то _mm_pause погоды не делает (с ним происходит в среднем 349к циклов в секунду при соответственно 3% выигрыше в проценте загруженности ядра)
Да, ты прав, да и в статье в целом я так и сказал, что этот метод будет нарушать идею планировщика WIndows. Но этот вариант показан как путь к стабильному решению, самым правильным в целом будут прерывания с -1 через системный вызов NtDelayExecution, и расчётом количества нужных циклов ( если конечно же нужна точность более 1ms )
 
на сколько я помню простым смертным запрещено вызывать данную функцию.
Это не задукоментированная функция, её нет в sdk, ты её сможешь её можешь получить через getprocaddress и использовать, но твой процесс должен иметь ui контекст, иначе не запашет
 
на сколько я помню простым смертным запрещено вызывать данную функцию.
Да, спасибо за примечание, хотел, но забыл упомянуть.
Для этого способа нужно иметь права TokenUIAccess в токене пользователе. Для этого можно просто скопировать права токена с winlogon, и после этого свободно можно будет создать новый процесс с правами использования CreateWindowInBand.
Примерный PoC:
Пожалуйста, авторизуйтесь для просмотра ссылки.
 
Да, ты прав, да и в статье в целом я так и сказал, что этот метод будет нарушать идею планировщика WIndows. Но этот вариант показан как путь к стабильному решению, самым правильным в целом будут прерывания с -1 через системный вызов NtDelayExecution, и расчётом количества нужных циклов ( если конечно же нужна точность более 1ms )
Тогда сорян, зря быканул.
Это не задукоментированная функция, её нет в sdk, ты её сможешь её можешь получить через getprocaddress и использовать, но твой процесс должен иметь ui контекст, иначе не запашет
В качестве альтернативы можно установить этот флаг в кернеле, тогда он не будет палиться в флагах процесса. Он прям в EPROCESS лежит.
 
Назад
Сверху Снизу