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

keng

Ветераны
  • Постов

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

  • Посещение

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

    55

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

  1. Путей достаточно большая куча - смотря что ты подразумеваешь под этим читом. По сути, интеллект ботов сводится к здоровому циклу, который заставляет их бегать туда-сюда и реагировать на обстановку (например, если они заметят тебя). Выйти на этот цикл можно: 1. Через функцию стрельбы. 2. Через функцию нанесения урона. 3. Через функцию изменения координат при перемещении. 4. Найдя адрес здоровья врага и функцию, его читающую. И так далее. Что потом делать? Или просто писать фильтры (стрелять можешь только ты, бегать можешь только ты и так далее), или реверсить весь цикл и смотреть, что происходит. Например, можно найти такой кусок кода: if(isPlayerDetected) { StartAlarm(self); FireAtWill(Player); } А при этом когда бот умирает, то происходит вот это: if(self.Health <= 0) { self.isDead = 1; DropCurrentWeapon(self); AnimateDeath(self); } Соединяем это и: if(isPlayerDetected) //Если заметили игрока { self.isDead = 1; //Ставим себе флаг, обозначающий что мы мертвы DropCurrentWeapon(self); //Выкидываем оружие AnimateDeath(self); //Анимируемся //StartAlarm(self); //Тревогу не вызываем //FireAtWill(Player); //Стрелять не начинаем } Такое называется "medusa hack" - в честь одной из сестёр горгон греческой мифологии. Что делает? Всё просто - когда враг тебя замечает и пытается отреагировать (начать стрелять в тебя, поднять тревогу) - он просто умирает. Ещё можно просто попробовать найти нужные значения в структуре игрока - заметил он тебя или нет, поднял тревогу или нет, есть ли у него оружие или нет и так далее.
  2. Привет! Всё верно, но это не совсем бессмертие. По факту, происходит такое: 1. Есть инструкция, которая постоянно (несколько раз в секунду) читает адрес здоровья (только твой или ещё чей-то - неизвестно). 2. Ты пишешь скрипт, который помимо чтения записывает именно в твой адрес здоровья (при помощи указателя) какое-то большое число. Да, с виду это будет выглядеть, как бессмертие, но бессмертие - это невозможность нанести тебе урон, а функцию нанесения урона ты не отключал, так что если ты записываешь часто-часто 100 в адрес здоровья, а игра тебя ранит на 101 - ты умрёшь. Поэтому самый верный вариант - ставить брейкпоинт на запись (тем самым ты попадёшь как раз на инструкцию, которая ранит игрока) и отключить её.
  3. У тебя есть адрес начала сканирования (address base модуля), адрес конца сканирования (address base + size модуля) и адрес текущего байта для сравнения. Вот собственно этого и достаточно, чтобы прогресс бар показывал верные значения. Правда, сканирование происходит достаточно быстро (при использовании хорошего алгоритма), так что смысла в этом не много. Для начала укажи язык, на котором пишешь.
  4. В любом случае, у меня эта проблема решилась запуском программы от имени администратора (т.е. с его правами).
  5. А вот [это] не катит?
  6. Ящитаю, что ты её занопил в инстансе дллки для конкретно процесса игры, а остальные программы будут подгружать себе новую.
  7. Дык а как мы тебе это проверим-то? Если у тебя работает - значит всё ок.
  8. Говоришь, что если окно делает MouseLeave(), или если Rectangle окна игры не содержит координат мыши (ага), то меняешь курсор принудительно. Т.е. если винда хочет нарисовать курсор за пределами игрового окна - что-то типа SetCursor(), файл курсора можно взять прямо из ресурсов игры. Или найди событие, отвечающее за смену курсора - отладь его при переходе указателя из окна игры в рабочий стол, ну и отключи нафиг смену указателя на текущий виндовый. Правда, нафига такие костыли? Короче, хук на GetMessage, там проверка на [вот это], если она проходит - то [вот это]. Не то, чтобы офигеть, как оптимально, но просто в реализации и работать будет.
  9. Имхо (не в обиду), сидеть и как обезьянка переписывать код из видеоуроков "чтобы было так же" - фиговый подход. Разберись, как работает трейнер с точки зрения логики (алгоритмически), а затем уже выясни, как реализуется та или иная часть алгоритма на выбранном тобой языке. Мы можем тебе подсказать, "как надо написать код", но вот почему именно так - мало кто станет заморачиваться.
  10. Бряк на WriteProcessMemory = "очень хорош" в олли? О_о Протекторы никто не отменял, если что. Автор, зачем тебе настолько необходима защита твоих трейнеров и на каком она должна быть уровне?
  11. Ну да, мы об одном и том же говорим, просто с разных сторон. Я стараюсь не пользоваться указателями вообще, т.к. есть вероятность, что даже если игра будет одинаковой версии - на разных компьютерах указатель может не работать. Не знаю, может просто вбилось в голову - я не выяснял.
  12. Аобскан актуален для поиска функции, при чём тут id или указатели? Указатель не всегда надёжен тем, что в некоторых ситуациях он не работает, а вот id работает хотя бы в рамках текущего патча игры.
  13. Тогда да, твой вариант лучше. Но мой тоже работать будет.
  14. Воспользуйся любой тулзой аля "code cave finder" (она есть и встроенная в самом СЕ), пиши туда. Приобщись к 0ldsk00l!
  15. Запиши в память, побайтно, а потом адрес первого байта и запихивай в стек.
  16. Надо строку записать в память и затем push адрес строки. Ты посмотри просто, как это в дизассемблере выглядит.
  17. Суть сигнатуры в том, что она должна указывать на первый байт нужной команды. Переходишь в оле в окно кода, жмёшь ctrl+g, вбиваешь адрес инструкции и копируешь байты нужной инструкции и ниже (потому что определённая последовательность команд уникальна, в отличие от одной команды, которая может встречаться в коде много раз). PS: "Я делаю сигнатуры при помощи оли" - не совсем корректно, потому что сигнатуры делает не сама оля, а плагин для неё.
  18. Есть отличная от нуля вероятность в будущем наткнуться на эту же тему и перечитывать, перечитывать, перечитывать!!!!11111
  19. Так в том вся и прелесть! В игре есть функция DealDamage() - НанестиУрон(), аргументом которой служит структура "Player" - "Игрок". Вот как оно выглядит: struct Player //Структура "Игрок" { int Team; //Поле, хранящее команду игрока. 0 для союзников, 1 для врагов, к примеру float Health; //Поле, хранящее текущее здоровье игрока string Name; //Поле, хранящее имя игрока } void DealDamage(Player p) { //Функция нанесения урона. В аргументах принимает структуру Player if(p.Health > 0) { //Если здоровье игрока больше нуля p.Health = p.Health - 10; //Вычитаем из здоровья десяточку } } Теперь представь, что есть игровое поле и две команды - наша и не наша, по два игрока в каждой: Команда 0: Игрок А, Игрок Б Команда 1: Игрок В, Игрок Г А вот, какие у этих игроков будут структуры: Player { Team = 0; Health = 100; Name = "Vasya" } Player { Team = 0; Health = 100; Name = "Petya" } Player { Team = 1; Health = 100; Name = "Grisha" } Player { Team = 1; Health = 100; Name = "Dima" } Теперь представим, что Дима стреляет в Васю. Вызывается функция: DealDamage(p); Здесь p - адрес структуры Васи, потому что в него стреляют и ему наносится урон. По логике, наши от врагов отличаются только одним полем - полем Team. Вот мы берём и пишем скрипт: HackedDealDamage(Player p) { if(p.Health > 0) { //Если здоровье больше нуля if(p.Team != 0) { //И ранят игрока НЕ нашей команды (наша - 0) p.Health = p.Health - 10; //Наносим урон! } } } Вот, типа того. Функции на самом деле до лампочки, кто в кого стреляет, а мы просто берём и слегка её меняем, заставляя ранить только тех, кто не в нашей команде. Сравнивать же можно что угодно - такое вот поле Team, или какой-нибудь уникальный идентификатор игрока (ID), или же вообще адрес его здоровья (через указатель). Т.е. игра ВСЕГДА отличает игрока, его союзников и врагов - то есть ВСЕГДА будет какой-то уникальный признак, который и надо искать в структуре. Надеюсь, начинает проясняться. Ramil, главное, не надо сидеть и тыкать пальцем в небо, надеясь что оно вдруг возьмёт и заработает - лучше приводи конкретные примеры того, что именно тебе не ясно. Вопрос вида "Как мне написать скрипт?" слишком широк и абстрактен, чтобы так вот взять и ответить - не бывает универсальных решений, надо рассматривать конкретику.
  20. Попробую оттолкнуться от твоих же скриншотов. Итак: 1. Ты нашёл адрес здоровья своего игрока - 0x3590632С. 2. Поставил бряк, получил инструкцию: MOV [EDI+10],EAX Что инструкция делает? Она просто кладёт в адрес здоровья ([EDI+10]) новое его значение, хранящееся в EAX. Но фишка вся в том, что при этом в EDI может быть много разных значений, т.е. это структура: struct Player { string Name; //Имя, например, "keng" float Health; //Здоровье, например, 100 } Вот и получается, считай, [Player+10], а 0x10 - смещение до поля Health в структуре. Если взять найденный тобой адрес, то получается: Health = 0x3590632С; Player = 0x3590632С - 0x10 = 0x3590631С; Вот, собственно, и выходит, что когда у тебя в регистре EDI лежит 0x3590631С, это значит что пытаются ранить твоего игрока. Пишешь скрипт: CMP EDI,0x3590631С JNE back MOV [EDI+10],EAX JMP back Что он делает, построчно: CMP EDI,0x3590631C Зная, что в EDI у нас лежит адрес начала структуры (как нашего игрока, так и врагов), а здоровье находится по смещению 0x10 от этого начала ([EDI+10]), то мы сравниваем (CMP = compare = англ. сравнить) содержимое регистра EDI и адрес начала структуры нашего игрока. После операции сравнения в процессоре устанавливается определённый флаг, сигнализирующий о том, равны ли (или нет) значения. JNE back JNE = jump if not equal = англ. прыжок, если не равно - одна из команд условного перехода. Прыжок выполняется тогда, когда последняя операция сравнения дала результат "не равно". В противном случае, процессор пропускает выполнение этой команды и послушно топает выполнять следующую. MOV [EDI+10],EAX MOV = move = англ. переместить - команда копирования из A в Б ("mov Б,А", "mov куда,что"). Банально и просто копирует значение здоровья, которое хранится в EAX, в поле структуры игрока, начало которой хранится в EDI. Получается примерно так: Player.Health = EAX; Где Player - структура (EDI), Health - поле этой структуры, хранящее здоровье ([EDI+10]). Что у нас остаётся? JMP back JMP = jump = англ. прыжок - команда безусловного перехода. Натыкаемся - управление переходит на адрес, указанный после команды. Кстати, back - это адрес команды игрового кода, следующей сразу после MOV [EDI+10],EAX. Т.е. это инъекция получается. Дык вот, к чему я это всё. Как тебе правильно подсказал ARM4ND0 в [17-м] посте, тебе надо найти разницу между твоей структурой и вражеской. Что-то типа: struct Player { int TeamID; //Идентификатор принадлежности к той или иной команде игроков string Name; float Health; } Найти такой идентификатор можно всегда, т.к. сама игра всегда знает, кто в кого стреляет и кто какой команде принадлежит. Раз это знает игра - это можно выяснить. Только вот в скрипте придётся сравнивать не EDI с адресом структуры игрока (это вообще не совсем правильно, т.к. игра может использовать DMA и адрес будет каждый раз новый), а этот самый id. Допустим, что id в структуре находится по смещению 0x14 и наш игрок имеет id = 5, а враги - id = 7, тогда вместо: CMP [EDI+10],0x3590632С Надо будет сделать: CMP [EDI+14],5 Т.е. на Си это выглядело бы примерно так: if (SomePlayer.ID == 5) { //Если id в структуре = 5 (т.е. это наш игрок) return; //Просто выходим } else { //Иначе DealDamage(SomePlayer); //Наносим урон } return; //И только после этого выходим PS: Можно писать как: CMP [EDI+10],0x3590632С Так и: CMP EDI,0x3590631С Почему именно - это будет вопросом на самостоятельное изучение.
  21. Если можешь идентификатор найти - делай через него, если нет - через указатель. Это дело вкуса и умений исключительно.
  22. Дополню предыдущий пост, если не найти разницу в структурах между игроком и врагом, то можно сравнивать регистр, хранящий в момент выполнения инструкции адрес здоровья того, кому наносится урон, с указателем. Это менее надёжный вариант, но более простой в реализации.
  23. Ида - это примерно как фотошоп. И дизасм, и отладчик, и очень крутая система скриптов, и куча всяких плюшек. Почитай к ней документацию - офигеешь. PS: Очень рекомендую писать крякми на чистом С или асме, чтобы полностью понимать, что происходит.
×
×
  • Создать...

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

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