Дослідження чужого чита для FarCry 4

Не так давно придбав гру FarCry 4 і вона мені відразу дуже сподобалася. З часом захотілося трохи поколупатися у внутрішностях цієї гри і написати для неї чит.


Трохи поковирявшись у грі за допомогою налагоджувача, мені вдалося без особливих зусиль дізнатися, як зробити такі функції: нескінченні патрони, стрільба без перезарядки, телепортація гравця, скорострільність, прибрати віддачу. Так само дізнався, як збільшити висоту стрибка гравця. Але ось коли я почав шукати, як зробити гравця безсмертним (мені здавалося, що в цьому нічого складного не буде), виникли труднощі.

Для початку за допомогою Cheat Engine знайшов адресу здоров'я персонажа і поставивши брекпоінт на запис. Знайшов інструкцію, яка змінює здоров'я. Природно, як і в більшості ігор, ця інструкція відповідає за зміну здоров'я всіх персонажів у грі, будь то вороги, або свої, або навіть транспорт (автомобілі, літаки). Такі завдання мені вирішувати не вперше і я знаю, що потрібно знайти, чим гравець відрізняється, припустимо, від автомобіля або від ворога, провести ін'єкцію коду і перед змінювальною інструкцією додати перевірку. В результаті чого ця інструкція буде виконуватися для всіх об'єктів - крім гравця.

Але в пошуках цієї відмінності я просидів кілька днів - і все марно. Мені не вдалося знайти жодної зачіпки на те, як відрізнити що-небудь у грі від гравця. Втім, не став впадати у відчай і вирішив піти не зовсім чесним шляхом - просто «подивитися», як це роблять інші чити, в яких є функція безсмертя.

Я приступив до пошуків читів для FarCry 4 в інтернеті і знайшов чит для останньої версії гри 1.9. Скачав, антивірус забив тривогу. Наступний чит, який скачав, не працював, але антивірус він не розлютив. 3-й скачаний чит начебто опинився без вірусів і робітник.

Насамперед я вирішив перевірити виконуваний файл чита за допомогою PEiD.

Як можна здогадатися, нічого хорошого напис «Not a valid PE file» не віщує. Це означає, що над ним знущалися пакувальники, протектори та інша нечисть. Але не все так погано, адже ми ж не хочемо модифікувати цей файл, він і так повністю безкоштовний і поширюється вільно. Все, що нам потрібно це дізнатися - звідки даний чит, що читає і куди записує.

Для запису даних у чужий процес є WinApi функцій WriteProcessMemory, а для читання ReadProcessMemory. Тепер перевіримо, чи встоїть великий і могутній захист цього чита перед API монітором. Перед OllyDBG вона встояла; після того, як я спробував відкрити його в цьому зневаднику, він написав, що не хоче працювати з невалидними файлами.

Запускаємо гру і під контролем API монітора запускаємо чит. API монітор до цього файлу, як виявилося, ніяких претензій не має. Тепер перевіримо, чи перехопить він виклики двох потрібних нам функцій. Для цього активуємо в читі безсмертя і дивимося на результат.

Спочатку чит прочитав один байт з пам'яті гри, а потім ще 3 рази зробив запис. При першому виклику він записав 5 байт, при другому - 21 байт, і при третьому виклику знову 5 байт. Якщо трохи подумати, то можна здогадатися, що до чого. Спочатку проводиться заміна оригінальної інструкції на безумовний перехід, потім за адресою, куди буде здійснюватися стрибок, записується код розміром 21 байт і наостанок в кінець цього коду додається безумовний перехід на наступну інструкцію, яка знаходиться за оригінальною (яка змінює здоров'я).

Однак насправді я вгадав тільки з другим і третім викликом, при першому виклику за адресою FC64.FCE_Engine_GetCloudTypeCount+21F923 записується наступна інструкція:

comiss xmm9,[rbx+0C]

.

Нижче знаходиться зображення основного коду, який записується при другому виклику функції WriteProcessMemor.

Детально я не став розбиратися, як цей чит робить гравця безсмертним. Вирішив просто скопіювати цей алгоритм і додати в свій чит.

Також хочу додати особисто мою думку з приводу читів типу «Трейнер». Я вважаю, що захистити такі чити від злому практично неможливо, оскільки відомо їх слабке місце, яке полягає в тому, що вони в будь-якому випадку повинні викликати WinApi функції WriteProcessMemory і ReadProcessMemory і як би там не шифрувалися дані, в ці функції вони надходять в чистому вигляді. Також я хочу сказати, що якщо ви зібралися писати серйозні чити з унікальним функціоналом, то краще це реалізувати у вигляді DLL, яку при запуску гри інжектувати в процес - там вже не так просто буде адресочки дізнатися.

Якщо трейнер скомпільований під .NET, то API монітор відмовиться з ним працювати. У цьому випадку можна в зневаднику встановити брекпоінт на функції WriteProcessMemory і ReadProcessMemory, а коли він спрацює - подивитися вміст стека і витягти звідти адресу, за якою будуть записані дані.

Те, що я написав вище - це моя особиста думка, і хтось може з цим погодиться, а хтось ні. Сподіваюся, ця стаття вам сподобалася.

Не раджу вам «копіпастити» функціонал чужих читів, оскільки ви при цьому не набираєтеся досвіду. Також створення читів таким способом не приноситиме задоволення.