cpuid inc.
-
Автор темы
- #1
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Привет.
Эта тема скорее всего похожа на codereview, но это не совсем так.
Просто хочу высказать мои предположения на основе наблюдений - "Почему вт лагает?".
Итог: Почти все проблемы исходят из реализации "Защиты", и её применения везде где только можно. (Исключительно моё мнение которое имеет обоснования)
p.s Офк msvc коверкает исходники до неузнаваемости для оптимизации, но принципы работы остаются все те же.
Эта тема скорее всего похожа на codereview, но это не совсем так.
Просто хочу высказать мои предположения на основе наблюдений - "Почему вт лагает?".
Xored string
-----
Вт юзает xorstr как и многие читы.
В основном он юзается для того "усложить" реверс.
Можно привести много аргументов о том что xorstr должен быть максимально быстрый, но при этом чем быстрее и легче его декодить, тем реверсить это все дело будет проще.
В случае лламы это самый блять юзелесс ксор который я когда либо видел, буквально.
Давайте для примера снимем его ксор при помощи cpp online.
Для того же примера возьмём рандомную заксореную строку из ватермарки:
![1595947486525.png 1595947486525.png](https://yougame.biz/data/attachments/89/89848-2f8e11f1a7b4fde58870c8c257f7fee6.jpg)
И сразу обращаем внимание на xor операцию а.к.а возвести в значение 0x30.
0x30 как вы могли уже догадаться и есть xorkey.
Теперь заходим сюда на любой cpp online сайт и вставляем три строки кода (
![1595947715000.png 1595947715000.png](https://yougame.biz/data/attachments/89/89850-119d039cde7e4336742d6ee3bc76c2ac.jpg)
В структуре Xored строка и ключ. Компилируем и запускаем.
![1595947836135.png 1595947836135.png](https://yougame.biz/data/attachments/89/89851-56d454f73486475ada5f41ab5c13753b.jpg)
В итоге наш xored value превращается в legacy mode за 0,5 секунды.
Офк кто-то может поспорить и сказать что "Ну так ты все равно потратил время, находил это, дексорил, етк". Да, согласен, но тут же есть и обратная сторона, таких ксоров в вантапе тысяча если не больше, и дексорить каждый занимает время. В реверсе офк это время не так важно как в игре, но оптимизации от этого не лучше.
Лучшее решение - частично ксорить, т.е ксорить только самые важные участки кода, ибо даже на казалось бы юзелесс функциях все равно есть ксор.
Fowler-Noll-Vo. (FNV1A в нашем случае)
_____
Тут уже немного посложнее.
Не так много читов (из популярных и не очень) юзают fnv1a, причиной тому является затратность вызова и сложность реализации которая отпугивает пастеров.
Обычно вт юзает FNV1A чтобы достать переменную из Source SDK класса.
Пример: Если нетвар m_lifeState равен 0x0 то мы его фиксим через FNV1A.
SS:
К этому +- нет вопросов т.к после того как нетвар найден ot фиксит сразу же и глобальную переменную к которой обращался, но лично я считаю что это глупо в данном случае т.к нетвары найти не проблема.
Совсем другая сторона извращенности лламы: Поиск модуля через FNV1A. (При поиске сигнатуры)
Это просто пиздец, и мало того что ест фпс до пизды, так это еще и может циклично если что-то устарело, плюс это еще и юзелесс т.к можно просто брутнуть название модуля. (Поиск сигнатур всегда приходится на основные модули: client, engine, etc)
Лучшее решение: Да хотя-бы ксорить, да мы получим убыток в фпс, но не будем вызывать кучу оверрайда, или же на крайний случай использовать t1ha hash (sec + fast) /xxhash (fast + ~sec), или же вариант который идеально подходит для замены fnv1a при работе с маленьким объемом данных - Murmur2A.
-----
Вт юзает xorstr как и многие читы.
В основном он юзается для того "усложить" реверс.
Можно привести много аргументов о том что xorstr должен быть максимально быстрый, но при этом чем быстрее и легче его декодить, тем реверсить это все дело будет проще.
В случае лламы это самый блять юзелесс ксор который я когда либо видел, буквально.
Давайте для примера снимем его ксор при помощи cpp online.
Для того же примера возьмём рандомную заксореную строку из ватермарки:
![1595947486525.png 1595947486525.png](https://yougame.biz/data/attachments/89/89848-2f8e11f1a7b4fde58870c8c257f7fee6.jpg)
И сразу обращаем внимание на xor операцию а.к.а возвести в значение 0x30.
0x30 как вы могли уже догадаться и есть xorkey.
Теперь заходим сюда на любой cpp online сайт и вставляем три строки кода (
Пожалуйста, авторизуйтесь для просмотра ссылки.
):![1595947715000.png 1595947715000.png](https://yougame.biz/data/attachments/89/89850-119d039cde7e4336742d6ee3bc76c2ac.jpg)
В структуре Xored строка и ключ. Компилируем и запускаем.
![1595947836135.png 1595947836135.png](https://yougame.biz/data/attachments/89/89851-56d454f73486475ada5f41ab5c13753b.jpg)
В итоге наш xored value превращается в legacy mode за 0,5 секунды.
Офк кто-то может поспорить и сказать что "Ну так ты все равно потратил время, находил это, дексорил, етк". Да, согласен, но тут же есть и обратная сторона, таких ксоров в вантапе тысяча если не больше, и дексорить каждый занимает время. В реверсе офк это время не так важно как в игре, но оптимизации от этого не лучше.
Лучшее решение - частично ксорить, т.е ксорить только самые важные участки кода, ибо даже на казалось бы юзелесс функциях все равно есть ксор.
Fowler-Noll-Vo. (FNV1A в нашем случае)
_____
Тут уже немного посложнее.
Не так много читов (из популярных и не очень) юзают fnv1a, причиной тому является затратность вызова и сложность реализации которая отпугивает пастеров.
Обычно вт юзает FNV1A чтобы достать переменную из Source SDK класса.
Пример: Если нетвар m_lifeState равен 0x0 то мы его фиксим через FNV1A.
SS:
![](/proxy.php?image=https%3A%2F%2Fsun6-14.userapi.com%2F6N8An6am9A_81on_RyLMrjEM91BtdHkhYzPUlA%2FJWdUlfgbKpg.jpg&hash=435f00db94baaaa9079fef101209b707)
К этому +- нет вопросов т.к после того как нетвар найден ot фиксит сразу же и глобальную переменную к которой обращался, но лично я считаю что это глупо в данном случае т.к нетвары найти не проблема.
Совсем другая сторона извращенности лламы: Поиск модуля через FNV1A. (При поиске сигнатуры)
Это просто пиздец, и мало того что ест фпс до пизды, так это еще и может циклично если что-то устарело, плюс это еще и юзелесс т.к можно просто брутнуть название модуля. (Поиск сигнатур всегда приходится на основные модули: client, engine, etc)
Лучшее решение: Да хотя-бы ксорить, да мы получим убыток в фпс, но не будем вызывать кучу оверрайда, или же на крайний случай использовать t1ha hash (sec + fast) /xxhash (fast + ~sec), или же вариант который идеально подходит для замены fnv1a при работе с маленьким объемом данных - Murmur2A.
Тут скорее всего дело в том что мы пытаемся из Unsafe сделать Safe2Use, но опять же некоторые моменты просто юзелесс.
Для примера возьмём GetActiveWeapon:
Почти вся эта строка юзелесс, и так ненужных проверок в вт куча и больше. Конечно если вырезать их то большого прироста вы не получите, но маленький прирост фпс будет обеспечен.
Для примера возьмём GetActiveWeapon:
![](/proxy.php?image=https%3A%2F%2Fsun6-16.userapi.com%2F9CI90N33D_goqtejF_uohOEDJx6DRGotzOCC0g%2FL1HmxYoKJRE.jpg&hash=4fce1536aa1f8333133a3d84f242a483)
Почти вся эта строка юзелесс, и так ненужных проверок в вт куча и больше. Конечно если вырезать их то большого прироста вы не получите, но маленький прирост фпс будет обеспечен.
Как бы это ни было странно, но да, тут тоже есть косяки.
Для примера возьмём startup функцию, которая вызывается каждый фрейм т.к внутри находится функция которая отвечает за рендер & обновление ватермаки, и прочего стаффа который требует обновления каждый +- фрейм.
SS:
Данная функция хукается еще на уровне первичных проверок на дебагер и прочее. Опять же в функциях которые вызываются внутри просто тонны ксора.
Несомненно делать такой хук под функцию из d3x9 это умно, но реализация это пиздец, без преувеличений.
В этой же функции вызывается поиск оффсетов & установка хуков, и в этой же функции вызывается первый рендер меню.
Я конечно понимаю что еще многого не знаю о кс разработке, но разве такое по логике исполнения является приемлимым? Да еще и при этом каждый фрейм ненужные проверки, я уже не говорю о том какую нагрузку испытывает процессор если фреймы стакнулись.
Для примера возьмём startup функцию, которая вызывается каждый фрейм т.к внутри находится функция которая отвечает за рендер & обновление ватермаки, и прочего стаффа который требует обновления каждый +- фрейм.
SS:
![](/proxy.php?image=https%3A%2F%2Fsun6-19.userapi.com%2F7anWfWSxXCPCLvigRVkx5PDHIZWl72eaJD8nIg%2FYmU-O1V0YyY.jpg&hash=00090f53608be3dcdb60d35d5276f327)
Данная функция хукается еще на уровне первичных проверок на дебагер и прочее. Опять же в функциях которые вызываются внутри просто тонны ксора.
Несомненно делать такой хук под функцию из d3x9 это умно, но реализация это пиздец, без преувеличений.
В этой же функции вызывается поиск оффсетов & установка хуков, и в этой же функции вызывается первый рендер меню.
Я конечно понимаю что еще многого не знаю о кс разработке, но разве такое по логике исполнения является приемлимым? Да еще и при этом каждый фрейм ненужные проверки, я уже не говорю о том какую нагрузку испытывает процессор если фреймы стакнулись.
В3 тоже не обошелся без добавления мутаций, но так же и v3 много чего было переработано для оптимизации.
По поводу "защиты" - к примеру ллама выучил арифметическое разделение указателей.
Т.е IEngineInterface0 ^ IEngineInterface1 = EngineInterfacePointer;
Тут опять же много можно спорить было это решение юзелесс или нет, но на мой взгляд - реверсер всегда найдет то, за что отвечают эти два значения.
По поводу "защиты" - к примеру ллама выучил арифметическое разделение указателей.
Т.е IEngineInterface0 ^ IEngineInterface1 = EngineInterfacePointer;
Тут опять же много можно спорить было это решение юзелесс или нет, но на мой взгляд - реверсер всегда найдет то, за что отвечают эти два значения.
Итог: Почти все проблемы исходят из реализации "Защиты", и её применения везде где только можно. (Исключительно моё мнение которое имеет обоснования)
p.s Офк msvc коверкает исходники до неузнаваемости для оптимизации, но принципы работы остаются все те же.
Последнее редактирование: