1. Гость, мы просим Вас ознакомиться с Правилами Форума и Отказом от ответственности!

Результаты поиска

  1. int 3
    rcmp — библиотека для хуков и работы с памятью Создана с целью упростить жизнь C++ разработчика, который пишет читы/библиотеки/моды/плагины. Для её использования нужно: Знать современный C++ и уметь на нём писать (хеллоу-ворлды и код на "C с классами" не считаются) Иметь опыт написания библиотек, которые внедряются в чужой процесс (через инжект, LD_PRELOAD или какую-либо другую технику) Причины создания библиотеки при наличии множества альтернатив подробно описаны в README. Если кратко — перемешивание ассемблера и C++ чревато багами, ухудшает качество кодовой базы и распыляет внимание разработчика, в то время как библиотека избавляет от низкоуровневой каши. Благодаря rcmp, за последние несколько лет я не написал ни строчки на ассемблере, что не может не радовать. На этом вступление окончено, перейдём к практике. Подключение к проекту Предполагая, что CMake проект вашей библиотеки my-cool-library уже создан и rcmp лежит в external/rcmp: add_subdirectory(external/rcmp) target_link_libraries(my-cool-library PRIVATE rcmp) Примеры использования Так как единственная полуживая игра на этом форуме - это PW, то и примеры будут по ней. В примерах используется ядро версии 1.5.5. С тем же успехом можно работать с любым другим сервисом или клиентской частью. Сами примеры немного надуманы, потому что серьезные вещи не реализуются в несколько строк кода, но суть уловить можно. Баг "d 174" заключается в том, что игрок отправляет на сервер пакет 174 с пустым телом, из-за чего ядро благополучно падает. Фикс элементарный: находим в ядре функцию DispatchCommand класса gplayer_imp. Её адрес - 0x0809472A Сигнатура - int(gplayer_imp*, int, const void*, size_t). Эта функция отвечает за приём клиентских пакетов. Пишем код для её перехвата: struct player_imp; // forward declaration // Для хука необходимо указать адрес оригинальной функции, её сигнатуру и передать сам "хук" // Хук — это лямбда, которая имеет на один аргумент больше, чем оригинальная функция // Первый аргумент лямбды — `auto original` — указатель на оригинальную функцию rcmp::hook_function<0x0809472A, int(gplayer_imp*, int, const void*, size_t)>([](auto original, gplayer_imp* self, int cmd_type, const void* buf, size_t size) { // детектируем кривой пакет if (cmd_type == 174 && size < 6) { // можно просто залоггировать или даже забанить игрока за такую наглость // псевдокод логгирования: // logger().trace("Hacker alert! Player ID = {}", self->_parent->ID.id); // оригинальную функцию не вызываем, просто выходим return 0; } // можно также логгировать вообще все пакеты от игрока, почему бы и нет? (псевдокод) // logger().trace("id={}, packet={}, len={}", self->_parent->ID.id, cmd_type, size); // пакет валидный, вызываем оригинальную функцию return original(self, cmd_type, buf, size); }); Возьмём произвольный скилл и поменяем его время перезарядки. Сделаем его случайным. // Выбор пал на скилл с ID = 111 // Функция: GNET::Skill111Stub::GetCoolingtime // Адрес: 0x0897F4E6 // Сигнатура: int __cdecl GNET::Skill111Stub::GetCoolingtime(const GNET::Skill111Stub *const this, GNET::Skill *skill) // в сигнатурах можно заменить все указатели на указатели на void, если лень объявлять типы rcmp::hook_function<0x0897F4E6, int(const void*, void*)>([](auto...) { return rand() % 5000; // от нуля до пяти секунд }); // Функция: item::Use // Адрес: 0x080F6DA4 // Сигнатура: int __cdecl item::Use(item *const this, item::LOCATION l, int index, gactive_imp *obj, size_t count) // Пример продвинутый, но неполный, т.к. предполагается наличие объявленных ранее классов rcmp::hook_function<0x080F6DA4, int(item*, item::LOCATION, int, gactive_imp*, size_t)>([](auto original, item* self, item::LOCATION loc, int index, gactive_imp* obj, size_t count) { item_body* body = self->body; // предмета нет в ячейке, нечего использовать if (body == nullptr) return 0; // прописываем логику для "своих" предметов // предмет с id = 1000 будет телепортировать игрока в рандомную точку на высоте 50 if (body->_tid == 1000) { static_cast<gplayer_imp*>(obj)->LongJump(A3DVECTOR(rand() % 1000 - 500, 50, rand() % 1000 - 500)); return 1; // возвращаемое значение - сколько предметов было потрачено } // предмет с id = 2000 будет писать в 10-й канал чата от имени игрока, где он находится else if (body->_tid == 2000) { const A3DVECTOR& pos = obj->_parent->pos; char message[100]; std::sprintf(message, "I'm at: %f, %f, %f", pos.x, pos.y, pos.z); static_cast<gplayer_imp*>(obj)->Say(message, 10); return 0; // предмет не тратится при использовании, почему бы и нет? } // на этом моя фантазия кончилась, поэтому для остальных предметов никаких кастомных эффектов не будет return original(self, loc, index, obj, count); }); Из примеров видно, что можно перехватывать вообще любые функции, прописывать произвольную свою логику вместо оригинальной или в дополнение к ней. Всё ограничивается лишь фантазией разработчика. Напишите в комментариях, каких примеров не хватает — допишу. Ссылка на библиотеку: [IMG] Требования: C++17, Windows/Linux, x86/x86-64. P.S. "Боевой" пример использования библиотеки — Replay Mod для ныне популярной игры Among Us
    Автор темы: int 3, 13 ноя 2020, ответов - 7, в разделе: C/C++
  2. int 3
    [IMG] AutoAngel — кроссплатформенная open-source библиотека, написанная на языке C++ (имеются биндинги для Python и lua), которая даёт возможность автоматически работать с файлами различных форматов движка Angelica3D. Многим в нашей сфере не раз приходила в голову идея об автоматизации тех или иных действий при работе с файлами. Да, нынче существуют крайне мощные редакторы практически для всех известных форматов. Разработчики трудятся над ними, чтобы предоставить пользователю красивый и удобный интерфейс, ускорив и упростив работу над выпуском обновлений. Но ни один редактор не даёт возможности полноценно обрабатывать файлы на уровне скриптов. Когда я в очередной раз понял, что мне придётся совершить множество одних и тех же действий (добавить 42 питомца, 42 яйца, 42 рецепта со сложной иерархией, 42 описания, 42 скилла и т.д.), тогда и пришла мысль о создании библиотеки AutoAngel. AutoAngel позволяет писать короткие, удобные и понятные утилиты и скрипты на языках Python и lua без ущерба производительности (ядро библиотеки на C++). Библиотека является достаточно молодой, но уже даёт достаточно широкие возможности по автоматизации рутинных действий. Поддерживаемые форматы: elements.data — чтение, модификация, запись. Поддержка любых версий, всех листов (основана на конфигах sELedit). pck архивы — чтение. Стандартные ключи, без поддержки pkx. Примеры использования: Утилита сравнения elements.data (python, lua) - показывает, чем отличаются два elements.data (удаления/добавления/изменения элементов). Утилита сравнения pck архивов (python, lua) - показывает, чем отличаются два архива (удаления/добавления/изменения элементов). Симулятор лута (python, lua) - показывает средний и суммарный лут с моба за N попыток его убийства. Генератор описания шахт (python, lua) - выводит описание содержимого шахт/сундуков с иконками предметов из ЛК для форума. Исходный код и инструкции по сборке: [IMG] Поддерживаемые платформы: Windows, Linux Поддерживаемые языки: C++, Python, lua Планы на будущее: Подробная документация pck+pkx, сохранение архивов, шифрование. Больше форматов Больше примеров
    Автор темы: int 3, 24 июл 2019, ответов - 1, в разделе: PW Разработки
  3. int 3
  4. int 3
  5. int 3
    <Клиент> В папке /element создаём файл dbserver.conf c содержимым: [GameClient] type = tcp isec = 2 iseckey = baxixD0awqydOtrxjxr8uhzaslmnqh osec = 2 oseckey = baxiykbpn3fxLqpsdpiodI4iazqjdl И перезапускаем клиент. <Сервер> В файле glinkd/gamesys.conf в каждой секции GLinkServer* дописываем следующее: isec = 2 iseckey = baxiykbpn3fxLqpsdpiodI4iazqjdl osec = 2 oseckey = baxixD0awqydOtrxjxr8uhzaslmnqh И перезапускаем GLink. *sec + *seckey = тип шифрования + ключ шифрования, где * - это i (input) или o (output) То, что на сервере i, в клиенте - o и наоборот. Ключ можно подкорректировать под себя, я скопипастил откуда-то. Что означает каждая цифра в алгоритмах шифрования - не скажу. Вот когда всех OOG ботов перепишут под этот фикс, тогда и узнаете. Выражаю благодарности: Китайцам (隨機漢字), которые скомпилировали клиент с поддержкой шифрования. Гоше (deadraky), за предположение о наличии шифрования. Себе (int 3), за умение пользоваться IDA. Всем лучи добра! P.S. Использование "в лоб" спасает лишь от шарового софта, не поддерживающего шифрование. Для надежности советую изменить ключи шифрования и упаковать файл с ними получше. И помните - не бывает идеальной защиты.
    Автор темы: int 3, 9 июн 2018, ответов - 19, в разделе: PW Документация
  6. int 3
    Всем привет! Представляю античит собственной разработки - Tiny Defender. Представляет собой сервис, полностью заменяющий и обобщающий стандартный китайский gacd (game anti-cheat daemon). [IMG] Фичи и возможности: Защита от программ, работающих через инжект пакетов (фарм-боты/SkillSender/автосвап/...) Защита от статической модификации клиента (подмена/пропатчивание elementclient.exe) Защита от эмуляции клиента (OOG) - детектирование в течение минуты. Прекрасно защищает от продвинутых читов, работающих без клиента: крафтеры, фарм-боты, флудеры. Защита от кликеров: прожатие скиллов, автоматизация действий Защита от прочих способов "быстрых прожатий" Запрет игры больше, чем в N окон Защита от динамической модификации клиента (после запуска процесса) - по данному принципу работают многие читы Ограничения доступа по железу и/или IP Наказание за любое запрещенное действие: Просто логгирование Кик персонажа Информирование о нарушении в ПМ определенному кругу лиц (GMам, например) Бан персонажа Бан аккаунта Особый режим бана (top secret) Вывод капчи с возможностью искупить вину и получить плюшку (как на китайском официальном сервере) "Белый" список пользователей, которым разрешено всё Возможность оповещения о любых событиях в GM-чат Продвинутая защита от обхода/отключения (привет, gacdOFF) Режим "тестирования", при котором отключены все блокировки - для тестирования возможностей API для взаимодействия с различным софтом (в будущем) Бонусы: Клиент/сервер произвольной версии Не требует перезапуска сервера Не требует модификации клиента Логгирует абсолютно все свои действия в консоль/файл. А в консоль еще цветными буковками ^_^. Также, логи частично русифицированы. Все вышеописанные фичи отключаются/настраиваются, что позволяет подстроить его под правила конкретного сервера Написан на чистом C++ последних стандартов, в связи с чем работает крайне шустро Для чего НЕ предназначен данный античит: Для защиты от атак на сервер. Античит разрабатывался для других целей. Таргетированные атаки могут проводиться с использованием редких багов или OOG-спама, которые действуют мгновенно или за очень короткий промежуток времени. Распознать атаку, заменив лишь один игровой сервис, невозможно. На данный момент идёт закрытое тестирование продукта (читай: купить пока что нельзя). Планировался набор тестеров, однако, они нашлись ещё до создания темы. Также, в связи с этим, некоторые фичи еще разрабатываются/дорабатываются. Реализовано не всё, однако никто не отменял обновления. Дата релиза неизвестна. Skype: smertig_zhyk Цена: Будет решена после окончательного релиза
    Автор темы: int 3, 7 фев 2017, ответов - 19, в разделе: Продам
  7. int 3
  8. int 3
  9. int 3
    Мне потребовалось: IDA + Hex Rays, хекс редактор, Cheat Engine и немного знаний асма. Ахтунг! Все числа в статье - в 16-ричной системе счисления. Где-то есть 0x, где-то нет. Статья будет состоять из трёх частей: Итак, нужно запретить доступ к дебаг командам всем, кроме ГМов. Как? У меня не было опыта редактирования ядра, но я предположил, что нужно глянуть функции, которые отвечают за управление Debug командами (лвл ап - d 2000 и подобные) и GM командами (телепорт гма - d 19 1 1 1 и подобные). Открываем ядро IDA'ой, ждём полного анализа. Слева список функций: [IMG] Жмём Alt-T, вбиваем в поиск Debug. С помощью Ctrl-T можно переключать на следующий результат поиска. Через минуту я нашёл интересные функции (они были рядом): [IMG] Название говорит за себя. Выбираем GMCommandHandler, F5 (генерация псевдокода). Видим (у меня переименованы некоторые переменные): [IMG] Строчка if ( (param1 <= 200 || param1 > 222) && param1 != 19 ) палит всю функцию. Я вспомнил, что для гма доступны как раз команды d 19, d 201, d 202, .., d 222. Видно, что идёт запись в лог, если параметр неверный. Значит мы на верном пути. Смотрим дальше. Должна быть проверка на то, ГМ ли это вызывает. Тут одно из двух: либо проверка идёт перед вызовом функции (где-то в дебрях кода), либо внутри функции. Я безуспешно проверил все функции CheckGMPrivilege, HasGMPrivilege, которых оказалось полно в ядре, но ни одна не вызывалась при использовании этих команд. (Десктопная убунту + IDA, приаттаченная к процессу. Спасибо Максимиану за подсказку). Всё оказалось проще. Сразу после записи в лог идёт строчка if ( *(a1 + 0x48) ) Очевидно, что a1 - указатель на структуру перса, который юзает команду d num, а +0x48 - это смещение до GM флага или структуры с информацией о GM правах. В любом случае, если это значение 0, то идёт выход из функции. В асм коде эта проверка выглядит так: [IMG] Если 0, то прыжок не идёт (jnz - jump if not zero). Записали, назовём это IsCharGM() (просто для себя) Переходим к функции DebugCommandHandler, F5. Начало у неё такое: [IMG] Опять же, переменные переименованы, так как я вводил свои структуры. Красным выделена строчка, которая вызывает функцию GLog::log(), которая записывает куда-то что-то. Вроде и полезная.. Но нам ведь надо всунуть нашу найденную проверку IsCharGM(), а для неё еще место нужно. Поэтому я принял решение стереть эту функцию нафиг (ВОТ ЭТО ДЫРА!!1) Смотрим асм код: [IMG] Зеленое - махинации с указателями на локальный/глобальный стек, трогать нельзя ни в коем случае. Красным - функция GLog::log(). Смотрим адрес начала этой функции: 0x812527E и конец: 0x812529C минус один == 812529B. Аргументы функции DebugCommandHandler: [IMG] По счастливой случайности, первый параметр оказался как раз тем самым указателем на структуру перса, вызывающего команду (поверьте на слово, проверил бряками в иде). Это очень сильно упрощает задачу. Почему? Об этом во второй части. Что мы знаем? а) У нас есть 0x1E (30 штук) байт для проверки гм прав у перса (0x1E - вместо затёртой, в будущем, функции) б) В функцию DebugCommandHandler передаётся указатель на структуру перса Как должен примерно выглядеть код проверки? На си: if (*(a1+0x48)) return 0; На асме: mov eax, [ebp+8h] ; в регистр eax суём наш указатель на структуру. Он находится в [ebp+8], потому что http://i.imgur.com/h6Exx0z.png cmp [eax+48h], 00 ; сравниваем значение по адресу eax+48 с нулём jz %адрес выхода с функции% (jz %адрес% можно заменить на mov eax, %адрес% / jz eax, но мой "генератор" опкода отказался работать с "jz %регистр%") Теперь поэтапно: а) Адрес выхода с функции? Листаем функцию в самый низ, видим там: [IMG] Зеленое - адрес выхода с функции. 0x812B8D1 б) Теперь нужно этот асм-код преобразовать в опкод. Я делал это с помощью Cheat Engine. На первый взгляд нет проблем, просто преобразовать 3 команды в байт-код. Ан нет! Команда jz %ptr% на самом деле опознаётся компьютером, как jz +N, где N - разность между адресом назначения и адресом команды, следующей сразу за прыжком. Вот такая хитрая относительная адресная арифметика. Поэтому: I) Переводим первые две команды в опкод: [IMG] 8B 45 08 83 78 48 00 - 7 байт в сумме II) Возвращаемся к записанным ранее адресам: 0x812527E (адрес начала функции, которая будет стёрта). Прибавляем 7 байт. 0x812527E+7 == 0x8125285. Значит по адресу 0x8125285 будет лежать команда jz +N. Она занимает 6 байт (опкод самого jz + 4 байта на N). Значит 0x8125285 + 6 == 0x812528B. III) Теперь вычитаем из конечного адрес (выхода с функции 0x812B8D1) полученный адрес (0x812528B) == 0x6646. Вот и всё. Теперь спокойно переводим команду jz +6646 в байты: 0F 84 46 66 00 00 Весь код: 8B 45 08 83 78 48 00 0F 84 46 66 00 00 Открываем ядро в хекс редакторе (мой любимый - 010 Editor). В файле все адреса смещены на 0x8048000 относительно того, что в памяти, поэтому берём адрес функции для затирания: 812527E и вычитаем 8048000, получаем DD27E. Переходим по этому адресу (Ctrl-G), видим [IMG] Затираем 0x1E (30 в десятичной) байт. Не нулями, а байтами по 90 (nop - no operation). Вообще, код лучше не затирать нулями никогда. [IMG] Затёрли, теперь вбиваем наш код: [IMG] Сохраняем. Поздравляю, вы великолепны. 1. Скорее всего (это никак не меняет сути гайда), там не указатель на структуру персонажа, а указатель на объект. И функции - это просто методы класса, которые выполняют действия над этим объектом. С другой стороны, обычно указатель на объект передаётся в ecx, поэтому могу и ошибаться. 2. Дыр быть не может. Если вы прочитали гайд полностью, это должно быть очевидно. Если игрок не может использовать ГМ команды, то он не может использовать дебаг команды. 3. Минус - не будет функции, которая что-то там логгирует. 4. Возможно, я индус, и можно было сделать всё проще, но я привык редактировать код, а не копаться в каких-нибудь xml и искать нужные параметры. 5. Я не описал (и не буду) моменты, как я добывал значения переменных с помощью бряков в ИДЕ, иначе это не влезет в одно сообщение. Да и в гугле полно информации на эту тему. Материал можно копировать и использовать на своё усмотрение, но указание автора (int 3) приветствуется. Если есть вопросы - задавайте, с радостью отвечу.
    Автор темы: int 3, 18 авг 2014, ответов - 11, в разделе: PW Документация
  10. int 3