Подкатегории

  • 16 Темы
    16 Сообщения
    PromisingP
    Синтаксис и команды скриптов в Cheat Engine.

    Скриптовой язык в Cheat Engine в основном позволяет создавать и внедрять в игру ассемблерный код на ходу, и выгружать его из игры восстанавливая оригинальный код.

    Окно скриптинга может быть открыто через окно отладчика, или сочетанием клавиш Ctrl+A в этом окне:

    aa3d2169-17ba-46a0-8283-610eeac9bb0d-изображение.png

    После открытия вы увидите следующее окно:

    dc90933e-a171-435d-8681-fc97e5aa4bde-изображение.png

    В нём можно написать скрипт и нажать кнопку Execute что позволит выполнить скрипт. Что бы добавить скрипт в таблицу и сохранить его, вам сначала нужно добавить в него определённые команды, а именно две команды обозначающие разделы, которые будут выполняться при включении и выключении скрипта [ENABLE] [DISABLE]:

    18a14491-4909-4895-b017-9a3a8e5b33e0-изображение.png

    Эти команды обозначают правила для включения и выключения скрипта. После их добавления можно добавить скрипт в таблицу с помощью контекстного меню:

    e2ab9f5a-ac29-458f-9db2-7d45305ec53b-изображение.png

    Если всё сделано верно, скрипт появится в таблице и окно редактора можно закрыть:

    3549713b-31a9-4a37-a1e6-9651812135a0-изображение.png

    Теперь вы можете снова открыть редактор, но уже для конкретно этого скрипта в таблице. Для этого дважды кликните по нему в графе Value, или откройте редактор через контекстное меню:

    8dfbfc3d-4265-41c7-b5c8-6f3a7e013269-изображение.png

    Откроется редактор для конкретно этого скрипта, вы можете сохранить изменённый скрипт нажав кнопочку OK:

    7ab76f83-bde0-4213-b5b1-28cbcca1d222-изображение.png

    Основные команды которые могут пригодиться:

    Запись данных по адресу, необходимо указывать размерность:

    //db - byte //dw - word //dd - dword //dq - qword (Адрес): db/dw/dd/dq(размерность) (число) //Пример, записать по адресу 0087745A подряд 12 байт, сначала 0, дальше 5, потом 7. 0087745A: dd 0 5 7 //Пример, записать по адресу метки label подряд 4 байта 1, 7, 10, 2 label: db 1 7 A 2

    Каждая метка обозначает после себя регион памяти все метки в котором будут относиться к ней, если они уже не определены в другом месте, или не являются настоящим адресом.

    //По адресу 0087745A располагается метка label, метка label нигде не определена, //значит она определяется и обозначается как место в скрипте после добавления. //Таким образом в данном примере label идёт в зоне 0087745A, сразу после него и указывает на тоже самое место, //то есть далее использовать label будет тоже самое что указать 0087745A: 0087745A: label: dd 0 //В следующем примере, указано что после 0087745A выделено 4 байта со значением 0, //зарезервировано командой dd 0, получается, метка будет указывать на следующие 4 байта после первых идущих в 0087745A: 0087745A: dd 0 label: dd 0

    Метка может быть зарегистрирована в текущем скрипте, или даже объявлена глобально для использования из других скриптов.
    label(lack) зарегистрировать метку lack для текущего скрипта.
    registersymbol(lack) зарегистрировать метку lack глобально.
    unregistersymbol(lack) снять регистрацию с метки lack, обычно используется в секции [DISABLE].

    Пример скрипта, который записывает при включении по адресу 0087745A число float 4 байта 5, а при выключении int32 0:

    6a28906b-91b1-4705-8723-eb71d17e7f3a-изображение.png

    С помощью скрипта вы можете легко выделить память и записать в неё значения. Выделяется память с помощью команды alloc(newmem, 1000), эта команда выделяет новую память как минимум размером 1000 и создаёт для неё метку newmem, которая аналогична адресу выделенной памяти.

    Пример скрипта в котором выделяется новая память и в неё записывается значение, после выключения скрипта память освобождается командой dealloc(newmem):

    0587b40e-a7b4-48ce-82f9-d96514d6d49c-изображение.png

    Мы можем зарегистрировать newmem что бы получить возможность добавить эту метку как адрес в таблицу и увидеть значение:

    b11f6e64-bb52-40f6-a153-d2eed90574af-изображение.png

    Добавьте адрес newmem в таблицу, нажав на кнопку Add Address Manually:

    8f3006e6-3215-494d-b885-53061d0a6d72-изображение.png

    b027a2c5-e3cf-489f-b746-2308e7aca1c3-изображение.png

    Включите скрипт нажав на квадратик слева от него, если всё сделано верно вы увидите значение записанное в память, не забудьте что Cheat Engine должен быть подключён к какому то процессу:

    a191fe28-9104-466d-9804-ff62d53e3ea8-изображение.png

    Значение float, измените его тип дважды кликнув на 4 Bytes в столбике Type что бы оно отображалось корректно:

    c9687ac4-c521-46f7-89d8-caf560d90eae-изображение.png

    Более продвинутые команды и примеры скриптов рассмотрены в следующих статьях.

  • Zombie Driver

    7
    0 Голоса
    7 Сообщения
    139 Просмотры
    Partizan1078P

    Совсем забыл что обещал поковыряться.
    Какая версия была уже не помню. Но вроде последняя.
    Из интерсного наверно только NoClip.

    ZombieDriverHD.7z

  • Как при отключении скрипта вернуть или (записать) в адрес значение ?

    18
    0 Голоса
    18 Сообщения
    67 Просмотры
    A

    @garik66, оо, попытаюсь сделать,спасибо большое.

  • [Dune Spice Wars] Поиск неизвестного значения

    9
    0 Голоса
    9 Сообщения
    409 Просмотры
    K

    Я чуть покопал её. Получается вот такой вот класс у неё по части ресурсов

    class Player { public: double N0000004F; //0x0000 double MoneyCome; //0x0008 double PlaskritCome; //0x0010 double PowerCome; //0x0018 double Fuel; //0x0020 double Water; //0x0028 double AuthorityCome; //0x0030 double GegemonyCome; //0x0038 double LansraadCome; //0x0040 double Research; //0x0048 double InfluenceCome; //0x0050 double N0000005A; //0x0058 double Votes; //0x0060 double CommandPoints; //0x0068 double UnitsAtOnce; //0x0070 double N0000005E; //0x0078 double N000000EF; //0x0080 double N000000F0; //0x0088 double N000000F1; //0x0090 double N000000F2; //0x0098 double N000000F3; //0x00A0 double N000000F4; //0x00A8 double N000000F5; //0x00B0 double N000000F6; //0x00B8 double N000000F7; //0x00C0 double N000000F8; //0x00C8 double N000000F9; //0x00D0 double N000000FA; //0x00D8 double N000000FB; //0x00E0 double N000000FC; //0x00E8 double N000000FD; //0x00F0 double N000000FE; //0x00F8 double N000000FF; //0x0100 double N00000100; //0x0108 double N00000101; //0x0110 double N00000102; //0x0118 double N00000103; //0x0120 double N00000104; //0x0128 double N00000105; //0x0130 double N00000106; //0x0138 double N00000107; //0x0140 double N00000108; //0x0148 double N00000109; //0x0150 double N0000010A; //0x0158 double N0000010B; //0x0160 double N0000010C; //0x0168 double N0000010D; //0x0170 double N0000010E; //0x0178 double N0000010F; //0x0180 double N00000110; //0x0188 double N00000111; //0x0190 double N00000112; //0x0198 double N00000113; //0x01A0 double N00000114; //0x01A8 double N00000115; //0x01B0 double N00000116; //0x01B8 double N00000117; //0x01C0 double N00000118; //0x01C8 double N00000119; //0x01D0 double N0000011A; //0x01D8 double N0000011B; //0x01E0 double N0000011C; //0x01E8 double N0000011D; //0x01F0 double N0000011E; //0x01F8 double N0000011F; //0x0200 double N00000120; //0x0208 double N00000121; //0x0210 double N00000122; //0x0218 }; //Size: 0x0220

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

    Но одну вещь как сломать я нашёл, нужно найти "Коэффициент откладывания в запасы" специи, как я её назвал. ищется так же в double от 0 до 1, если поставить по середине будет 0.5, соотственно продавать всё будет 0, оставлять всё будет 1. если выкрутить эти значения больше единицы или сделать отрицательными, денег будет приходить много. рядом с этим коэффициентом еще что-то крутится, но я так и не понял что это.

  • C++ Internal DLL Hack // Pattern Scanner

    3
    0 Голоса
    3 Сообщения
    216 Просмотры
    R

    @BiNooos

    C++ Code to Find an Address by Signature
    This code includes:

    A function to compare bytes against a signature and mask.
    A function to iterate over the memory of the module and find the pattern.
    cpp
    Copy code
    #include <Windows.h>
    #include <Psapi.h>
    #include <iostream>

    // Function to compare memory bytes with the pattern and mask
    bool CompareBytes(const BYTE* data, const BYTE* pattern, const char* mask) {
    for (; *mask; ++mask, ++data, ++pattern) {
    if (*mask == 'x' && *data != *pattern) {
    return false; // Byte mismatch
    }
    }
    return (*mask == 0); // Pattern fully matched
    }

    // Function to find the pattern in the memory of the module
    DWORD64 FindSignature(HMODULE hModule, const BYTE* pattern, const char* mask) {
    MODULEINFO moduleInfo = { 0 };
    GetModuleInformation(GetCurrentProcess(), hModule, &moduleInfo, sizeof(MODULEINFO));

    DWORD64 baseAddress = (DWORD64)moduleInfo.lpBaseOfDll; // Base address of the module DWORD64 moduleSize = (DWORD64)moduleInfo.SizeOfImage; // Size of the module BYTE* moduleBytes = (BYTE*)baseAddress; for (DWORD64 i = 0; i < moduleSize; i++) { if (CompareBytes(moduleBytes + i, pattern, mask)) { return (DWORD64)(moduleBytes + i); // Return address if pattern found } } return 0; // Pattern not found

    }

    // Example usage of the pattern scanner
    int main() {
    // Example signature (byte pattern) and mask
    const BYTE pattern[] = { 0x89, 0x45, 0xFC, 0x48, 0x89 };
    const char* mask = "xxxxx"; // 'x' indicates exact match; '?' indicates any byte

    // Replace with the target module handle (e.g., "example.exe" or a DLL) HMODULE hModule = GetModuleHandleA("example.dll"); if (hModule == NULL) { std::cerr << "Module not found!" << std::endl; return -1; } // Find the address of the pattern in the module DWORD64 foundAddress = FindSignature(hModule, pattern, mask); if (foundAddress != 0) { std::cout << "Pattern found at address: 0x" << std::hex << foundAddress << std::endl; } else { std::cout << "Pattern not found!" << std::endl; } return 0;

    }
    Explanation:
    CompareBytes():

    This function checks whether the bytes in memory match the pattern provided. The mask string is used to define how strictly each byte should match. An 'x' in the mask indicates that the corresponding byte should match exactly, while a '?' allows for any byte to be considered valid in that position.
    FindSignature():

    This function scans through the memory of the module (hModule), comparing each section of memory against the provided pattern and mask. If it finds a match, it returns the address where the pattern starts.
    Usage:

    In the main() function, we search for a simple example byte pattern ({ 0x89, 0x45, 0xFC, 0x48, 0x89 }) in a module (example.dll). The mask xxxxx indicates that all bytes in the pattern must match exactly.
    Replace "example.dll" with the actual module you want to scan (e.g., the target process or DLL you're interested in).
    Notes:
    GetModuleHandleA() is used to obtain the handle of the module (DLL or EXE). If you're scanning an external process, you will need to obtain the module handle from the target process using methods like EnumProcessModules() or CreateToolhelp32Snapshot().
    You may want to adjust memory protections or handle reading memory from other processes using functions like ReadProcessMemory() if you are working with a process other than your own.

  • Pocket Rogues 1 убийство = +1 лвл

    Решенные
    13
    0 Голоса
    13 Сообщения
    127 Просмотры
    G

    @CoinsDMG Замечательно.👍

  • Textorcist взлом для импорта сохранений

    7
    0 Голоса
    7 Сообщения
    110 Просмотры
    StoneWeaverS

    Пользователь @magrega написал в Textorcist взлом для импорта сохранений:

    Запилил гайд в стиме, тебя упомянул @StoneWeaver, если вдруг интересно
    Гайд

    Прикольный гайд и спасибо, что упомянул )) Но я бы копнул дальше, и пореверсил бы игру, чтобы понять, как кодируется и декодируется этот айдишник. Возможно, на досуге так и сделаю ))

  • Hollow Knight скорость персонажа

    10
    0 Голоса
    10 Сообщения
    125 Просмотры
    Partizan1078P

    @quane Ищите fall speed

  • Code Filter крашит игру

    Закрыта
    6
    0 Голоса
    6 Сообщения
    80 Просмотры
    StoneWeaverS

    @Haarfus Да было бы за что )) Тему закрываю, раз вопрос исчерпан.

  • Шифровка

    7
    0 Голоса
    7 Сообщения
    177 Просмотры
    G

    @Templar если не изменяет мне память, горячая клавиша не нужна.
    а ну вот, вторая галочка сверху в настройках 11.jpg

  • [ПОМОЩЬ] Обнаружение ИИ

    3
    2 Голоса
    3 Сообщения
    144 Просмотры
    N

    @StoneWeaver Не волнуйся, чувак, я все понял! Спасибо большое, ваш совет мне очень помог. Я проследил, почему было показано сообщение, и добрался до функции... Я не менял никаких значений и не "nop"... Это было простое преобразование "jne" в "jmp".

    А еще лучше то, что я нашел функции, которые могут задавать статус животного... Например, сделать так, чтобы оно утомилось, чтобы оно заснуло, сделать его голодным и начать есть, а также разозлить его, что учитывается при прохождении. миссии...

    Вот скриншот того, как это работает, а животные обо мне не заботятся

    Streamable видео

    ОписаниеОписание

    Спасибо за ваше время! Надеюсь, я вернусь, когда на ум придет еще одно сомнение

  • Как правильно сделать call в своём скрипте?

    Решенные
    8
    0 Голоса
    8 Сообщения
    169 Просмотры
    P

    В качестве некого заключения данной темы хочу предложить кусочек своего скрипта, который демонстрирует как передачу параметров в функцию, так и получение от неё результата в случаях, если оные передаются через регистр.

    // начало скрипта (flgRain выведен в таблицу и назначена горячая клавиша на установку значения в 1) cmp byte ptr [flgRain],0 // проверяем не было ли команды на смену дождя je endRain // если нет - завершаем скрипт mov byte ptr [flgRain],0 // если была, то сначала сбрасываем флаг обратно (нам не нужно беспрерывно менять дождь туда-сюда, нужно выполнить код лишь единожды) pushad // сохраняем все регистры в стек call Terraria.Main::get_IsItRaining // проверяем идёт ли сейчас дождь (результат вернётся в регистр EAX) test eax,eax // 0 - не идёт, 1 - идёт je @f // прыжок к секции начала дождя (пропустить остановку дождя) если EAX==0 call Terraria.Main::StopRain // останавливаем дождь popad // восстанавливаем регистры из стека jmp endRain // выход из скрипта (не нужно запускать дождь) @@: call Terraria.Main::StartRain // запустить дождь popad // восстановить регистры из стека endRain:

    За идею использования инструкций pushad/popad хочу поблагодарить пользователя "youneuoy" с Discord канала GamehackLab[RU].

  • как узнать смещение?

    2
    0 Голоса
    2 Сообщения
    83 Просмотры
    Partizan1078P

    Выложи весь лог. Посмотри что находится в rdi и в r12. Наверняка в одном из двух будет структура. А дальше. Либо сканер. Либо смотри что пишет в эти регистры выше по коду.

  • Debug меню в Cheat Engine неактивно.

    6
    0 Голоса
    6 Сообщения
    122 Просмотры
    P

    Неактивные элементы меню говорят о том, что нет сработавшего брейка.
    Если после установки breakpoint'а (F5) и возвращения в игру - игра играется и он не срабатывает, то видно поставили брейк на участок кода, который пока никак не участвовал в игре.

  • поиск структуры

    2
    0 Голоса
    2 Сообщения
    128 Просмотры
    P

    Могу подсказать только если .NET игрушка (хотя для Mono в инетах пишут тоже работает) - в CE в этом плане есть инструмент:
    91efe7dc-0bb8-4891-a545-80d6170b339a-image.png
    Далее уже всё должно быть понятно интуитивно
    94c7bee7-e0d2-4339-866f-0d3c5ce0b55b-image.png
    В частности по кнопке можно получить адреса всех структур выбранного класса
    2bf6503a-78e6-4ce3-9138-ef9e1ebec252-image.png

    Если в вашей игрушке такой менюшки не показывается, то давайте разбираться. Для начала откуда знание названия структуры?

  • Взлом Unturned (Unity, Mono)

    Не решенные
    2
    0 Голоса
    2 Сообщения
    140 Просмотры
    P

    Если главная цель найти указатель на структуру и способ не имеет значения, то я бы рекомендовал сменить подход к задаче.
    К примеру у меня была цель найти указатель на класс игрока в Terraria (.NET) - я нашёл здоровье, потом нашёл инструкцию, которая в него пишет, в инструкции адрес куда писать регистр+смещение, предположил, что в регистре искомый адрес и проверил эту гипотезу через dissect data/structure всё в том же CE, делаю инъекцию, которая вытаскивает его в символ который выводится в CE и который можно использовать в других скриптах, что я и делал.
    Думаю dissect будет одинаково работать и в вашем случае.
    22406b65-4727-463b-9cd5-c608a5766fe7-image.png
    1 - игра сама вычисляет адрес структуры
    2 - и потом прибавляя смещения находит то ей сейчас из этой структуры нужно

    Коротко: ваша игра как-то догадывается как искать стамину и прочее, нужно просто за ней проследить и перехватить на моменте, когда она найдёт то что и вам тоже нужно.

  • не могу понять почему не выводиться базовый адрес игры в трейнере

    Не решенные
    2
    0 Голоса
    2 Сообщения
    82 Просмотры
    __fastcall_

    @android Возможно некая функция в игре постоянно туда пишет своё значение.

  • таймер в игре веселая ферма 4

    Закрыта
    10
    0 Голоса
    10 Сообщения
    173 Просмотры
  • ultimap 2 на amd

    2
    0 Голоса
    2 Сообщения
    50 Просмотры
    LIRWL

    Пользователь @123qwer написал в ultimap 2 на amd:

    Подскажите что нужно сделать.

    Ответ вот тут Чпок

  • Как получить всё оружие в начале игры?

    7
    0 Голоса
    7 Сообщения
    140 Просмотры
    __fastcall_

    @Hakor Ида про или чит энжин - выбор за тобой и он зависит в основе от знаний, если по асм коду умеешь понимать, то через СЕ/x64dbg и подобные, если нет, то лучше ида, мне не принципиально через что смотреть, но это надо тебе.

  • Вызов игровой функции, принимающей в качестве аргумента массив или указатель на него

    1
    0 Голоса
    1 Сообщения
    92 Просмотры
    Нет ответов