Перейти к содержанию

roma912

Пользователи+
  • Постов

    223
  • Зарегистрирован

  • Посещение

  • Победитель дней

    7

Весь контент roma912

  1. Ну мне пришел в голову такой вариант - написать свой парсер и на его основе уже использовать функции рисования. Если хочешь сделать разметку для текста вроде HTML, то придется написать тебе обработчик данной строки. Допустим, ты передаешь в свою функцию следующее (Ну соотв. класс для всего этого) CustomGDIDraw->DrawTextbyHTML("<fontColor:#ff0000> January 30, 2011\n </fontColor><fontColor:#ff0010> Feb 1, 1999\n </fontColor><fontColor:#ff0050> Feb 2, 1970\n </fontColor>") Первый твой этап - сделать парсинг, который ты уже будешь обрабатывать по своей логике. Сначала определять текст, потом цвет, потом символы переноса и т.д. Самый простой вариант - регулярка (кликабельно) Совпадения по группам, это будет то, что тебе нужно в данном случае. Группа 1 - выдаст тебе hex цвета. Далее уже сам преобразуешь Группа 2 - выдаст тебе текст, который нужен для отображения. Далее уже сам обработаешь перенос строки. Ну и по итогу получишь то, что хотел. Минус только в том, что тебе придется на совершенно любой текст ставить данные кастомные теги. В целом теги можно сделать и попроще, чтобы и сама регулярка была проще. Ну тут уже как хочешь, тебе решать. По поводу переноса текста - берешь начальные координаты отрисовки, и высчитываешь от этой координаты вниз некоторое количество пикселей (Допустим шрифт 14 + отступ текста 8 = 22). Примерно такая логика для переноса текста. Ну а далее стандартная отрисовка по координатам. Идею для реализации я тебе описал, дальше все за тобой.
  2. Еще есть другой вариант. 1. Ставишь хук на нужную точку или функцию 2. При срабатывании хука запоминаешь нужные тебе регистры 3. Выписываешь все в файл 4. Возвращаешь управление игровой функции
  3. roma912

    CE в Wargame EE/AB/RD

    Поэтому тебя и направили изучать основы ассемблера. Изучишь основы, тогда поймешь что нопнуть
  4. Это конечно все хорошо, но лучше для записи смещений использовать reclass. Штука очень удобная и сгенерирует автоматически класс для дальнейшей работы
  5. Насколько я понял никакого виртуального метода у данного объекта нет, т.к. тут _thiscall и передается указатель на EC_LoginUIMan Если существуют какие-то варианты вызова метода без поиска данного указателя EC_LoginUIMan или установки хука, то готов прочитать пару статей об этом.
  6. Вот для конкретности. Есть базовый класс AUIManager, в котором virtual PAUIDIALOG GetDialog(const char *pszName); - Метод для получения окна по имени, он точно реализован. Ставлю точку на вызов метода с нужным именем окна, нахожу указатель на класс из Ecx и Reclass уже подсказывает что это CECLoginUIMan, где базовый класс AUIManager Логично предположить, что этот метод будет и в CECLoginUIMan, однако указатель на нее найти не получается Если предположение не точное, то возможно ли выйти на базовый класс (AUIManager) через (CECLoginUIMan) и взять его указатель? А потом еще глубже в нем найти указатель через VTable на метод GetDialog?
  7. В том и проблема, что виртуальный метод в исходном коде есть, а в самом VTable AUIManager его не имеется... Ну и если взять указатель на этот класс, то внутри него также не имеется указателя на данный метод
  8. У меня вопрос насчёт устройства методов, которые существуют внутри объекта (в памяти) Допустим с виртуальными все понятно, и вызываются они через vtable. А возможно ли найти обычную функцию внутри объекта? (в памяти) Т.е лежат ли там указатели на все методы класса? Или для _thiscall конвенции это так не работает?
  9. Ну это уже слишком... Хотя тоже имеет право на жизнь Мне проще написать dll на с++ которая вызовет просто эту функцию по адресу и все. Тем более все аргументы ты уже знаешь через декомпилятор .net
  10. Не обязательно находить матрицу из этой функции. Можно просто использовать саму функцию, вызывать ее для перевода.
  11. Ну... Я с видовыми матрицами работал совсем немного Но перевернутых никаких мне не встречалось. Да и если посмотреть как формируется н-мерный массив, то он останется таким же и в памяти. Т.е. как он был записан в коде, так должен и выглядеть в памяти. Разве что в CE выбрать неправильное отображение (Оно и может наверное запутать)
  12. Ну если игра не на юнити, то тогда и нужно искать видовую матрицу Для юнити довольно просто все писать. Берешь саму dll, которая Assembly-csharp из папки manage. Это считай твоя "основная библиотека классов" для модификаций чего угодно. После написания инжектируешь как mono библиотеку
  13. Ну наверняка структура до каменя примерно такая pPlayer->CInventory[N]->CItem-> (И вот тут уже вариации) В любом случае нужно искать указатель на инвентарь, а далее искать указатель на каждую вещь в инвентаре Иначе врятли ты найдешь сразу камешек который тебе нужен Ну а для возвращения его в слот, нужно найти функцию которая ставит / вынимает его, если это невозможно записью указателя в память
  14. Ну вот такие хуки как раз довольно сложно отлаживать. Переписал бы ты хук на detours 1.5, или же 3 версию. Там хотя бы точно не накосячишь со стеком и прочим.
  15. Ну тут я не стал его прикреплять т.к. там довольно много не совсем нужного. Допустим 4 массива по 80 элементов а потом перебор каждого и отрисовка просто в Canvas wpf. Все это выкладывать смысла особо нет. Это довольно простая вещь, которую не так и тяжело написать вместе с последующим сохранением в файл Тоже так думал, но когда рядом с одной стрелочкой игрока будет еще десяток, легко же запутаться
  16. Вот и настало время когда я вернулся снова к этой игре Только теперь уже для нее есть исходный код, который позволит находить всякие функции в разы быстрее и проще На этот раз будем делать карту ресурсов, рисовать ее и загружать прямо в игру Этапы которые этому способствуют 1. Распаковать саму карту из surfaces.pck 2. Достать саму карту, посмотреть каким образом она примерно отображается 3. Узнать координаты респа ресурсов Vec3 на карте 4. Перевести Vec3 игровые в Vec2 картовые 5. Нанести по Vec2 соответствующие иконки 6. Привести все в читаемый формат для игры 7. Запаковать все обратно 1. Распаковка pck этой игры уже не представляется сложностью, и есть довольно много софтов делающее это (Собственно как и упаковка обратно) А значит пункты 1 и 7 не сложны совсем 2. Карта в игре отображается довольно специфическим образом (Незнаю как до этого додумались разработчики, или же это движок сам режет так интересно) В целом картина такая Мировая карта состоит из 88 частей - т.е. 8 столбцов и 11 строк (В свою очередь каждый квадрат тут 1024*1024 пикселя) Из всех этих кусков собирается единая карта, которую можно будет увидеть в игре Формат файла dds, т.е. в итоге мы должны получить карту в 88 dds файлов как в оригинале 3. Координаты респа найти довольно легко, опять же распаковав configs.pck Внутри будет coords_data.txt в котором некоторым списком указаны Vec3 координаты нахождения ресурса / моба и т.п. Структура примерно такая Парсим нужные координаты по ID (Пишем вспомогательный парсер который выдаст c++ массив с Vec3) 3091 - ID, world - фильтрация только для основной карты Ну и достаем Vec3 - x y z координаты 4. Когда есть массив всех этих ресурсов, нужно перевести Vec3 (Т.е. внутриигровое положение в мире, на карту, которая 2D) Тут поможет исходник клиента PW, и метод который рисует стрелочку игрока на карте Вот та самая функция в исходном коде, далее надо ее найти и заменить координаты (т.е. оригинально передаются Vec3 игрока, и вычисляется Х-У для рисования на карте) Ничто не помешает нам подменить эти координаты на те, где находятся ресурсы Vec3 Далее дело техники, и создания хука (Учитывания calling conventions, определения аргументов и т.д.) Имея исходный код не так сложно найти функцию (Правда версия игры немного старее чем этот исходный код) Собственно вот и хук. В цикле перебираем массив который сделали на шарпе путем парсинга файла Выдаем результаты в виде массива (Далее пригодится) Таким образом я получил координаты для 4х видов ресурсов (Больше мне и не нужно. Vec2 координаты) ~320 штук 5. Далее необходимо нанести все это дело на карту. Дабы не скреплять все 88 кусков в каком-нибудь редакторе мне удалось найти (Не без помощи) карту 8*1024 х 11*1024 пикселей. Т.е. точно такую как и нужна Для добавления иконок на общую картину была написана еще одна вспомогательная программа на шарпе, которая грузит общую карту, а потом по координатам ставит маленькую иконку 16х16 по координатам из массива (Скрин выше) Ну соответственно наносим сами иконки на общую карту и сохраняем в jpg. Получаем на выходе карту в 113мб с нанесенными иконками Остается всего 2 пункта, один из которых пустяковый 6. Режем эту общую карту в фотошопе (Качаем фотошоп, да да у меня его не было на этой машине) с помощью инструмента "раскройка" И как раз получаем 88 изображений; 8 столбцов и 11 строк, где каждая картинка по 1024*1024 пикселя. Идеально Остается нерешенным только вопрос конвертации из jpg в dds. Но тут придется только ручками все делать. А также ручками приводить потом названия этих кусочков в вид который на скриншоте №1. (Не смертельно, но долго) Заменяем 88 dds файлов на новые в папке maps 7. Запаковываем все обратно в единый pck файл программой из п1. и проверяем в игре. Все работает. Отлично.. Сама по себе идея не новая, но вот реализации именно внутри игры пока что не видел нигде
  17. Можешь словить запрос на авторизацию, потом просто слушать этот сокет, самый классный вариант как по мне Но не факт что рабочий, т.к. наверняка что-то может помешать Проблема по сути в том, что во флеш игру ты не сделаешь никакого хука
  18. Ну смотри. На скриншоте есть даже пост запрос Я бы начал с него. Посмотреть вообще насколько часто игра ими общается А посмотреть очень просто любым сниффером
  19. Такое только перехватом можно отследить Хук Send и recv ф-ий в сокете Ну и конечно же нужно найти функции шифрования трафика
  20. А еще можно найти указатель на хп и выставить банку на клавишу Потом читать хп и если оно меньше твоего установленного %, отправлять игре Sendmassage c нажатием клавиши на которой установлена банка Это самый просто вариант, максимально простой
  21. Может просто скрыл шторку где показываются asm команды? Хмм?
  22. Начиная от версии игры заканчиваю сущей магией вне Хогвардса
  23. Так, давно что-то ничего не писал в блог Собственно время пришло Данная статья является примером метода о котором рассказано в данном видео Рассмотрим вызов игровой функции на примере перовой части игры Dishonored В данном примере будем восполнять себе количество маны, которая в игре не может регенерироваться полностью после использования череды способностей Для начала нам необходимо найти само значение маны, благо оно храниться 4мя байтами в памяти и тут нет ничего сложного Теперь когда у нас есть адрес маны или же указатель на данный адрес, нам необходимо найти метод который как раз и перезаписывает значение Делается это очень просто (F6) Нас интересует инструкция которая перезаписывает значение 1 раз Выходим на эту инструкцию в дизассемблере и ставим брейк Вот мы и нашли инструкцию, далее просто выходим из него (Кнопка Execute till return) Для того чтобы вызвать метод, необходимо узнать и проанализировать его параметры. Этим и займемся В метод передается 2 параметра, один из которых находится в ecx (Указатель на базовый класс) А второй передается в регистре ecx, до инструкции которая перезапишет значение Данный кусок: push ecx mov ecx,esi Регистр edx содержит все время один и тот же не изменяющийся адрес, т.е он статичен Распишу параметры чтобы было более нагляднее push ecx (Значение 50 в данный момент) mov ecx, esi (В ecx записывается значение из esi (0x0AD0A000)) Теперь если немного проанализировать, то можно понять что 50 - это значение маны, которое будет присвоено игроку после применения способности А 0x0AD0A000 это указатель на начало структуры игрока, т.е PlayerController* player; Таким образом метод выглядит так: ManaMethod(PlayerController* player, int ManaOut); Теперь можно приступать к написанию самого кода на c++, чтобы вызывать этот внутреигровой метод (При этом заранее найдем работающий указатель на класс игрока PlayerController) Для вызова метода нам необходимо определить его соглашение о вызове, т.е в каком порядке туда передаются аргументы Посмотреть все соглашения можно тут https://ru.wikipedia.org/wiki/Соглашение_о_вызове Немного почитав можно увидеть что это соглашение __thiscall thiscall — соглашение о вызовах, используемое компиляторами для языка C++ при вызове методов классов в объектно-ориентированном программировании. Аргументы функции передаются через стек, справа налево. Очистку стека производит вызываемая функция. Соглашение thiscall отличается от cdecl соглашения только тем, что указатель на объект, для которого вызывается метод (указатель this), записывается в регистр ecx. В самом коде объявляем этот метод для его вызова далее //Метод принимает PlayerController* и ManaOut //0x00AB17C0 - адрес которых хранился в edx и он статичен typedef void*(__thiscall * _ManaType)(PlayerController* Player, int Mana); _ManaType ManaFunc = (_ManaType)(0x00AB17C0); Остается только написать вызов этого метода и на этом дело будет сделано /*PlayerConroller.h */ struct PlayerController { public: char pad_0000[2656]; //0x0000 int Mana; //0x0A60 }; /*Метод который вызывается при создании потока из dll*/ void onAttach() { while (true) { if (GetAsyncKeyState(VK_END)) { PlayerController* Player = reinterpret_cast<PlayerController*>(*(DWORD*)(Base + 0x01052DE8)); //Получаем указатель на игрока PlayerController* ManaFunc(Player, 100); } Sleep(150); } } Собственно на этом моменте статья закончена При нажатии на кнопку END внутри игры, мана восполняется до 100 единиц
  24. Думаю ты можешь выйти на инструкции которые перебирают в цикле указатели на персонажей А потом уже просто читать их прямо оттуда Те которые уже не будут использоваться сразу отпадают, т.к иначе игра бы просто пыталась читать пустой / неправильный указатель
  25. Можешь при каждой отработке функции просто обновлять указатель на объект а потом пользоваться функциями Примерно также как у меня и сделано
×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.