Помощь - Поиск - Пользователи - Календарь
Полная версия: Uoext. Расширяя Возможности Клиента
UoKit.com Форумы > Ultima Online : Dev > Работа с клиентом UO > Вспомогательные программы > UOExt
Страницы: 1, 2, 3, 4, 5, 6, 7, 8
Warstone
UOExt - Ultima Online protocol Extender

Текущая версия: 0.1.0-RC1

Данная программа позволяет вам добавить еще один уровень абстракции в связке клиент - сервер для более эффективного управления как ресурсами так и самим клиентом.

Данная программа выполнена в виде dll, которая подключается к клиенту во время запуска (клиента). Она запускает в адресном пространстве клиента еще один "прокси-сервер" и перенаправляет весь протокол через себя. В отличие от других программ того-же класса, которые перехватывают recv/send, прокси сервер работает в отдельном потоке, что положительно сказывается на плавности картинки клиента, однако налагает дополнительные требования к программисту. В частности: Если прокси-сервер, по приходу какого-то пакета должен сделать серьезную обработку этого пакета, то клиент все-еще может сделать несколько шагов, до того, как переполнится локальный буфер действий клиента и он встанет (эффект потери соединения с сервером). Для игрока - это не большое время, но для программы - это миллиарды тактов.
Побочный эффект данного подхода состоит в том, что вам больше не надо следить за тем, является-ли ваш клиент шифрованным, так как программа автоматически расшифрует протокол, если сервер не принимает зашифрованный протокол.

Так как данная программа выполняется в адресном пространстве клиента, ей так-же доступны любые данные клиента. Более того, перехват API распространяется и на клиент. Поэтому вы имеете все данные клиента и можете производить относительно долгие вычисления без "фризов" клиента.

Сам исходный код данной программы доступен по адресу: http://code.google.com/p/uo-ext/ и имеет лицензию GPL. Однако плагины, написанные вами, являются самостоятельным продуктом (так-же dll) и, насколько я понимаю, могут не попадать под лицензию GPL. Если это не так, и тут есть кто-нибудь, кто разбирается в лицензиях - свяжитесь со мной, пожалуйста, для консультаций по лицензиям.

Исходный код программы написан на Object Pascal, однако плагины могут быть написаны на любом языке (соглашение о вызовах stdcall или, в терминах Си это должно быть, WINAPI соглашение).

История версий (с r53)
r60
- UOExt.GUI: Убрано мерцание при частом обновлении картинки.
- UOExt.GUI: Добавлен проект-тест для UOExt.gui.dll
r57
- Добавлен проект UOExt.GUI. Это шкурка "по умолчанию". Нет поддержки UOExt. Сама картинка сделана командой сервера "Квинтэссенция". Все скопировано правильно!

r56
- UOExt выгружается на старте клиента, если она не поддерживается сервером.

r55
- Убран проект UOLoader из репозитория. Фактически, он не использовался в работе с тех пор, как заработало заражение ехе
- Добавлена проверка на поддержку сервером UOExt в купе с передачей настроек. Аналог Razor'овского Negotiate features with server.
- Поправлен баг с падением клиента при разрыве соединения во время игры.
- В репозиторий добавился код для RunUO для поддержки UOExt

r53
Первый релиз, относительно которого будет вестись история.


Мини FAQ по работе с UOExt

Начальная установка
UOExt поставляется в 2-х основных форматах: debug и release. Отличие их в том, что debug "выкидывает" консоль и пишет туда отладочные сообщения. release, же работает без дополнительного окна.
На данный момент предпочтительный метод работы с UOExt состоит в заражении выполняемого файла клиента игры UO вызовом UOExt при запуске.
Процесс заражения происходит так: Скопировать UOExt.dll в папку с клиентом, открыть командную строку (Пуск - Выполнить cmd.exe), перейти в папку с клиентом и выполнить следующую команду:
Код
%windir%\system32\rundll32.exe UOExt.dll,Infect32 client.exe

Где client.exe - название выполняемого файла клиента УО. Так-же рекомендуется сохранить резервную копию, так как UOExt пропишет себя в текущем exe и будет запускаться каждый раз при старте модифицированного клиента.
После этой операции вы можете работать с клиентом, как раньше. Просто он будет загружать UOExt.

Поддерживаемые программы
На данный момент UOExt умеет работать с клиентом с которого снято или не снято шифрование (авто определение факта снятия шифрования).
Так-же UOExt запускается с Razor.
Тесты совместимости с другими сопутствующими программами не проводились.

Механизм проверки сервера на работу с UOExt
UOExt проверяет сервер на поддержку UOExt путем отсылки серверу пакета 0xEF с пустыми значениями. Если в ответ в течении 5 секунд не прилетит пакет 0x00, то считается что сервер не поддерживает UOExt. Содержание пакета можно почитать в комментариях в коде.

Механизм расширения функционала путем написания плагинов
Будет позже.


Roadmap

r53 (29.04.2012) - UOExt: Решение косяков с шифрованием.
- UOExt: Очередь загрузки плагинов
- UOExt: Взаимодействие между плагинами
r53 (29.04.2012) - UOExt: PE_PROXYEND - добавить в параметры наличие коннекта до клиента и сервера, а так-же причину завершение прокси.
- UOExt (фича): Поддержка старого шифрования (Которое основано на Pi... Это 2-е клиенты что-ли)
Устарело - UOExt (фича): Если UOExt словило какой-то неизвестный пакет, то его надо записать в отдельный файл на диске.
- UOExt (фича): Автоматическое чтение протокола зи запущенного ехе (только для 2д версий).
- UOExt (фича): Если пришел неизвестный пакет с сервера (с клиента он придти не может ибо выше), то просто не пропускать его дальше. Заодно и сдампить.
- UOExt (фича): В дебаг режиме пользуясь VEH уметь ловить ошибки и откатываться до вызова плагина. (с возможным продолжением работы, хотя этого скорее всего не будет)
r54 (01.05.2012) - UOExt (фича): Ловить первый пакет с сервера и проверять его на "каноничность". Если он "каноничен", то UOExt не поддерживается этим сервером, если он специальный, то из него прочитать настройки для UOExt.
r56 (01.05.2012) - UOExt (фича): Если сервер не поддерживает UOExt, то она выгружается из АП клиента, позволяя ему продолжать работать в штатном режиме.
r57 (15.05.2012) - UOExt (фича): Добавить специальную dll'ку, которая будет заниматься визуализацией процесса клиенту.
- UOExt (правка): Сделать проверку что на этапе инициализации IP/порт те-же что и на этапе коннекта самого клиента.
- UOExt (правка): При заражении ставить метку о заражении. Это нужно для того, чтобы убрать возможность повторного заражения и/или перезаражать, если механизм заражения изменился.
Ozzy Osbourne
Надо надо smile.gif
Сейчас анимации на весь экран приходится сенд пакетами делать(( а так будет способ поинтереснее smile.gif
StaticZ
Конечно надо, только вот поддержка Razor всеже нужна
Ozzy Osbourne
ну разоры шмазоры это можно и потом прикрутить. пока с этим ненадо заморачиваться что бы не распылятся.
Warstone
Итак... Пройден этап первичного тестирования и вылова глюков. dll удачно рапортует о том, что создан прокси на свободном порту и клиент схавал подложный login.cfg. То есть клиент не отторгает эту длл... Во время тестов удалось удачно и напрочь подвешивать Windows7, чему я, честно говоря, удивился.

Следующий шаг - тестирование клиент-сервера.

А интересующихся Сферойдов так и нет.
Wap
Потенциально штука для сферы неплоха в плане хотя бы фильтрования информации, потому что полноценное фильтрование исходящих пакетов в сфере невозможно.
Реально без поддержки инжекта и разора вряд ли стал бы такое использовать, да и вообще дофига более простых и полезных задач есть.
Потестить никаких проблем нет.
Warstone
На вопрос общаственности... Как делать систему плагинов?

Сейчас в планах 2 типа плагинов: Клиентские и серверные. Клиентские - пользователь может сам ставить/писать (получается этакое макро средство для упертых), тут могут быть всякие свисто-перделки...

Серверные - вот тут вопрос... Их ставит Администратор сервера путем прописывания еще одного пакета в протокол... Вообще, планирую сделать инкапсуляцию своего протокола в протокол УО (По принципу 0xBF пакета). Серверные плагины скачиваются непосредственно с сервера (с Game сервера) и тут-же инициализируются. Клиент не может управлять этими плагинами, если это запрещено сервером.

Плагины пока-что планируются как dll файлы, у которых есть Initialize функция, которой и передается управление. В параметрах будет, скорей всего, описание функций, по принципу OpenGL'ного выбора разрешения экрана (кажется, давно дело было... Если коротко: На каждую функцию будет 8 байт: ID функции и ссыль на участок памяти. Таким образом, при изменении хоста, плагины не всегда переписывать надо).

Пока список функций довольно простой:
RegisterPacketHandler(Header:Byte; Handler: TPacketHandler);
UnRegisterPacketHandler(Header: Byte; Handler: TPacketHandler);
RegisterPacketType(Header:Byte; Size:Word);
SendPacket(ToServer:Boolean; Data: Pointer; Size: Word);

TPacketHandler = function (Data: Pointer; var Size:Word; var Send: Boolean):Boolean;
Для последнего - Если вы поменяли пакет, то возвращаете True, если нет, то False. Пакет можно менять (вплоть до смены типа пакета), но нельзя вылезать за рамки Size. Надо послать больше? SendPacket и Send := False;. Да, если ставите Send := False; то следующие плагины этот пакет не обработают... То есть пакет как будто и не приходил вовсе.

При SendPacket он так-же будет проходить стек обработчиков.

Да, все функции stdcall(WinAPI соглашение).

Как-то так...

С# планируется, но на далекое будущее.

Предложения, пожелания?
StaticZ
Цитата(Warstone @ 13.11.2010, 14:33) *

Серверные плагины скачиваются непосредственно с сервера (с Game сервера) и тут-же инициализируются. Клиент не может управлять этими плагинами, если это запрещено сервером.

Нужна система защиты иначе могут просто подменить плагин на одноименную пустышку.

Цитата(Warstone @ 13.11.2010, 14:33) *

Плагины пока-что планируются как dll файлы, у которых есть Initialize функция, которой и передается управление. В параметрах будет, скорей всего, описание функций, по принципу OpenGL'ного выбора разрешения экрана (кажется, давно дело было... Если коротко: На каждую функцию будет 8 байт: ID функции и ссыль на участок памяти. Таким образом, при изменении хоста, плагины не всегда переписывать надо).

Чето вообще не уловил логики.. Причем тут изменение хоста? и для чего вообще переписывать плагины при изменении хоста?

ЗЫ: насколько я понимаю каждый плагин работает в своем потоке?
Может лучше сделать чето типа плагинс.сфг где прописать названия функций что вызывать?
Soteric
Цитата(Warstone @ 1.11.2010, 12:09) *
Оно вообще-то надо?

Нам надо хоть один завершенный продукт программиста Warstone, чтобы начать воспринимать его идеи серьезно smile.gif
Warstone
Цитата(StaticZ @ 13.11.2010, 15:58) *

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

ЗЫ: насколько я понимаю каждый плагин работает в своем потоке?
Может лучше сделать чето типа плагинс.сфг где прописать названия функций что вызывать?

Насчет хоста - я имел в виду саму программу. Пока оставим... Мне тут самому еще продумать место надо.

Нет, все плагины "работают" в одном потоке... потоке Прокси. Вернее так: Сначала Прокся проходится по всем плагинам (тут куча оговорок, потом распишу) и вызывает инициализацию. Так как это обыкновенные длл(то тут вы можете спавнить сколько хотите потоков, но их смысл пока ускользает), в коде инициализации вам передают ссылки на API, вы регистрируете расширения протокола и обработчики пакетов. Дальше, как только все плагины инициализированы, начинается сам процесс "перехвата"... Как только приходит пакет с клиента или сервера, он расшифровывается (разархивируется Хаффман, возможно потом и снятие шифрования будет) и вызываются обработчики, которые зарегистрированы для этого пакета. Во время работы обработчика можно регистрировать новые обработчики, разрегестрировать старые, в том числе и текущий, посылать дополнительные пакеты в обе стороны. Если пакет прошел все обработчики и с него не снят статус отправления, то он опять упаковывается, если это надо и посылается дальше клиенту или серверу.

Как-то так...

Сотерик... Я сарказм понял и он вполне имеет место быть. Вообще - ты прав. В частности... Посмотрим.
Vizit0r
Цитата(Warstone @ 1.11.2010, 11:09) *

UOExt или Ultima Online ® © ™ Protocol Extender
Суть идеи: На клиенте повесить обработчик протокола между клиентом и сервером. То есть технология такая: Клиент читает Login.cfg... Как только он делает CreateFileA, перехватчик создает, в отдельном потоке, слушающий тред и скармливает клиенту Что-то типа LoginServer=127.0.0.1,XXX, где XXX - динамически порт. Клиент коннектится к этому "серверу", тот, в свою очередь, коннектится к настоящему серверу и начинает пропускать протокол через себя.
Естественно что через такую прокси систему так-же можно получать пакеты, которые неизвестны клиенту и обрабатывать их, посылать пакеты клиенту, не получая их с сервера.
Что это дает:
Возможность часть логики переложить на клиента. Я приведу пару примеров, которые просто очень хорошо ложатся в эту идеологию:
1) Есть "хотелка":
Раскрашивать проперти вещи различными цветами. То есть красным если требование не выполнено и зеленым, если оно - выполнено. Это можно сделать на сервере, но зачем? Это будет занимать лишнее время сервера, которое всегда дорого.
Можно это-же сделать на клиенте. Тогда раскрашивать будет сам клиент, а серверу, простите, пофигу.
2) Есть "хотелка":
Хочу ощще ппц спец. эффекты при касте магии. То есть кидается спелл... Дальше начинаются спец. эффекты по всему экрану. Они ни на что не влияют, но они есть...
Такую штуку, опять-таки, хорошо делать на клиенте, а сервер будет просто посылать id анимации, время, прошедшее с запуска анимации.

Вообще, тут возможности безграничны.

Что есть на данный момент:
преАльфа версия. Перехват протокола реализован. Инъекция производится с помощью "Запускатора".

Что будет дальше:
преАльфа, после вылова глюков и, возможно, рефакторинга кода, перейдет в Альфу, с которой удастся поработать некоторым шардам (пока один на RunUO. Возможно нужен будет еще один на Sphere/POL, но все зависит от активности Сферойдов и POLотеров =))

я обожаю изобретателей велосипедов. они натыкаются на проблемы, сто раз решенные до них, при этом не читают эти ваши интернеты, и героически их преодолевают.

Даю намек - исходники инжекта уже лет 10 как лежат на сурс форже. Там как раз и расшифрование+расжатие трафика, подмены пакетов, и отсыл своих пакетов клиенту\серверу, и прочее, прочее.

Вариантов два - или автор как раз их и использовал (но скромно молчит об этом), либо автору надо вручить медаль героического изобретателя велосипедов.




После прочтения постов про возможность встраивания ЛЮБЫХ плагинов-аддонов - стало понятно, что надо будет детектить еще и эту dll'ку в кач-ве вредной.


P.S. Вообще замечательная тема, не мог пройти мимо. даже потратил минуту на регистрацию smile.gif

P.P.S. А название топика- то какое классное "We do what EA can't.". Я бы сказал, что EA это нафиг не надо просто. впрочем автор видимо себя считает более крутым, чем программисты из EA )))
Warstone
Цитата(Vizit0r @ 15.11.2010, 9:40) *

я обожаю изобретателей велосипедов. они натыкаются на проблемы, сто раз решенные до них, при этом не читают эти ваши интернеты, и героически их преодолевают.

Даю намек - исходники инжекта уже лет 10 как лежат на сурс форже. Там как раз и расшифрование+расжатие трафика, подмены пакетов, и отсыл своих пакетов клиенту\серверу, и прочее, прочее.

Вариантов два - или автор как раз их и использовал (но скромно молчит об этом), либо автору надо вручить медаль героического изобретателя велосипедов.
После прочтения постов про возможность встраивания ЛЮБЫХ плагинов-аддонов - стало понятно, что надо будет детектить еще и эту dll'ку в кач-ве вредной.
P.S. Вообще замечательная тема, не мог пройти мимо. даже потратил минуту на регистрацию smile.gif

P.P.S. А название топика- то какое классное "We do what EA can't.". Я бы сказал, что EA это нафиг не надо просто. впрочем автор видимо себя считает более крутым, чем программисты из EA )))

Ну а теперь мы еще немного подумаем... Желательно - головой...

Реалии жизни таковы: Или мы играем на Инжекте или на Razor'е... Что неудобно.

Медаль можешь вручать. Я не протестую... Только Платиновую или, как минимум, - золотую.

Насчет плагинов и детектинга dll в кач. вредной... Как-бы тебе сказать... Вариантов куча, так как пока рано говорить о возможностях, поэтому ваш сарказм - смешон. Да и как ты будешь детектить dll там, где ее нет?(Это если надо будет начинать войну).

Ну а насчет PPS... В качестве примера вот такой вариант:
Кеширование статики и динамически обновляемая статика во время игры - здесь это можно, у ЕА я как-то этого не нашел. Даже с EditServer в uo.cfg.
Vizit0r
про P.P.S. - а EA оно просто не надо. вот и все.

Цитата
Ну а теперь мы еще немного подумаем... Желательно - головой...

емкий ответ, на все. главное - аргументированный.


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

а насчет dll там, где ее нет - это вообще пять.

засим удаляюсь, как-то попозже зайду, гляну.

P.S. Если пользовательских плагинов не будет - то удачи в разработке, если будут - то грандиозного фейла проекту smile.gif
Warstone
Цитата(Vizit0r @ 15.11.2010, 10:43) *

про P.P.S. - а EA оно просто не надо. вот и все.
емкий ответ, на все. главное - аргументированный.
действительно, рано еще. через пару месяцев зайду, проведаю обстановку, может будет что-то более готовое, что уже можно будет рубить smile.gif

а насчет dll там, где ее нет - это вообще пять.

засим удаляюсь, как-то попозже зайду, гляну.

P.S. Если пользовательских плагинов не будет - то удачи в разработке, если будут - то грандиозного фейла проекту smile.gif

Всегда рад конструктивной критики.
А dll можно грузить руками так, чтоб она неотсвечивала в списках загруженных dll. Тогда ее только по сигнатуре искать. Нет, это можно, но тогда какая большая будет база сигнатур... Сопоставимая с самим клиентом.
Буду ждать.
На PS: Всегда есть галочка "Сервер прав" и пакет с сервера "запретить клиентские плагины", вы не находите?
StaticZ
Цитата(Vizit0r @ 15.11.2010, 9:40) *

P.P.S. А название топика- то какое классное "We do what EA can't.". Я бы сказал, что EA это нафиг не надо просто. впрочем автор видимо себя считает более крутым, чем программисты из EA )))


EA много чего не надо, однако это не значит что пользователям это не надо. Например изменение расширения игрового окна в UO EA досихпор не может сделать хотябы 1024х768, что совсем не много при современной диагонали монитора минимум 17-19 дюймов, я уже молчу про то что и 24-26 дюймовые мониторы давно уже продаются по приемлемой цене. То что современные компьютеры без проблем потянут UO на любом разрешении тоже очевидно.. EA выпускает аддоны но исправить это даже не хотят, хотя уверен там работы на день максимум на неделю, а при помощи Razor'а можно ставить любое разрешение и все этим пользуются и всем это надо... Также не стоит забывать что EA делает клиент только для офф сервера а не для фришардов, а у многих фришардов UO мягко сказать сильно переделанна, при этом так сказать возникают проблемы связанные с ограничением клиента, т.е. клиент мешает реализовать многие задумки такчто слоган "We do what EA can't." имеет полное право на жизнь. Конечно есть Инжект (у которого кстати проблемы совместимости с новыми клиентами), но он ориентирован на игроков, а данная тулса предназначена для использования нестандартных фишек фришардов и плагины тут в основном делают не игроки а администрация под конкретно свой сервер. Без подержки плагинов сервером толку от них будет не много. Кстати один из вариантов - "теневая авторизация" и запрет разора и инжекта и прочего макросного софта, о чем кстати мечтают много фришардов. Такчто сам проект востребован, но конечно не для игроков оси-стайл серверов, ну а дальше все зависит от реализации идеи... :-)
d`ArcZeal
Цитата(Ozzy Osbourne @ 1.11.2010, 12:31) *

Надо надо smile.gif
Сейчас анимации на весь экран приходится сенд пакетами делать(( а так будет способ поинтереснее smile.gif

А чем сенд пакеты плохи, не подходят, отлично работают.
Ozzy Osbourne
Работают отлично, с этим проблем нет. Но когда в мире стоит к примеру квестовый предмет который посылает в радиусе экрана сендпакеты каждые там 2 сек - то это может вызвать некие тормоза если рядом с ним будет к примеру 20-30 плееров. Ну я не тестил, но предполагаю
Warstone
Цитата
А чем сенд пакеты плохи, не подходят, отлично работают.
А все просто... Так ты напрягаешь сервер рассчитывать что и где показать, а так по этому поводу напрягается клиент. Серверу и так есть чем заняться. Пусть он урон просчитывает.
GblPower
Полезная штука. Особенно для ПОЛа.
И вопрос, как от кодерного ламера - если я правильно понимаю схему, то эта прога не поможет отключить "олвейс лайт" от инжи, разора и т.д. Или все же есть возможность?
StaticZ
Цитата(GblPower @ 17.11.2010, 11:55) *

Полезная штука. Особенно для ПОЛа.
И вопрос, как от кодерного ламера - если я правильно понимаю схему, то эта прога не поможет отключить "олвейс лайт" от инжи, разора и т.д. Или все же есть возможность?

и да и нет... "олвейс лайт" можно отключить со стороны сервера и для етого предусмотренаа опция Negotiate razor features with server, при этом сервер должен поддерживать расширение протокола разора ну и для того чтобы убедится что никто не обошед это ограничение приедется дисконектить клиентов что не ответили на запрос отключения фич... т.е. дисконектить всех кто играет без разора или другой тулсой или с разором но с выключенной опцией Negotiate razor features with server. Для инжекта может чтото и есть похоже но не думаю...
Warstone
На самом деле - надо проверять... Надо знать как руководит протоколом Разор и Инжа. Узнать это можно, поэтому, в теории, эти фишки можно обходить. А можно просто запрещать использовать Разор или Инжу.
Destruction
Цитата(Warstone @ 17.11.2010, 13:04) *

На самом деле - надо проверять... Надо знать как руководит протоколом Разор и Инжа. Узнать это можно, поэтому, в теории, эти фишки можно обходить. А можно просто запрещать использовать Разор или Инжу.

Что касается инжекта..

Если с ним будет получаться такая цепочка:
server <-> injection <-> твоя тулза <-> клиент

То инжект в этой цепочке очень легко выцепить. Ты можешь любым способом поменять пакеты которые отсылает клиент/сервер (и соответственно научить работать с изменениями клиент/сервер) и в результате, либо тихонько следить за инжекторами (например 1 неправильный пакет - инжа детектед), либо просто блокировать (хотя бы доп. шифрование накрутить и инжа уже ничего не поймет) возможность использования инжы.

В любом случае будут умельцы которые будут использовать софт, но делится они врятли станут (не выгодно, т.к. повлечет обновление защиты, которое ко всей прочей радости может оказаться прозрачным для клиента).
Warstone
Как сделать - я и так понимаю. Вопрос куда я попадаю в цепочке "сервер - инжект - клиент".

У меня есть подозрения, что все-таки между сервером и инжектом, так как я специально перехватывал протокол так, что-бы клиент не трогать. Там фактически в тихую поднимается прокси сервер, который через себя транслирует пакеты. То есть механизм такой: Клиент начинает читать Logn.cfg (перехват CreateFileA), процедура перехвата запускает прокси сервер в адресном пространстве клиента отдельным потоком (чтоб в плагинах опять-таки можно было перехватывать АПИ). И через перехват ReadFile скармливает содержимое Login.cfg но уже вида LoginServer=127.0.0.1,<ProxyPort>. Порт выбирается произвольно самой проксей.
Warstone
Итак... первая встраиваемая версия готова. Запускается через запускатор. В дебаг сборке работает почти как UOSpy, в релиз сборке ее не видно, но она есть =).

Силы брошены на систему плагинов. Она так-же уже есть, но кривоватая как я не знаю что... Но работает =)
Warstone
Некоторые люди сильно ругали меня за то, что не видно - что делается. Такое ощущение, что я ввожу народ в заблуждение. Возможно. Что-бы развеять подозрения - собранная "демонстрационная" версия:
http://ifolder.ru/20756056

Для работы этой... "демки" необходим клиент версии 6.0.Х (просто потому что основная часть протокола писалась с него), освобожденный от шифрования (через UO_Rice, например), а так-же сервер настроенный на 127.0.0.1:2593 (Значения пока зашиты внутри).
Файл ProtocolShower.plg необходимо положить в папку Plugins вашего клиента (папку надо будет создать).

Инструкции к запуску: Запускаете UOLoader.exe, который есть в архиве, в появившейся простейшей форме, указываете путь декриптованного ехе от установленного клиента и жмете кнопку запустить.

Что должно произойти: Должен появиться запускающийся клиент, но помимо его - еще одно консольное окно, где в последствии будет идти лог переданных пакетов между клиентом и сервером.

Да, демка простейшая, так как на данный момент и показывать-то нечего.
Warstone
Итак... Хотелось-бы немного рассказать об API и послушать ваши замечания. Все, что я сейчас расскажу не является истиной в последней инстанции и может быть изменено. Итак - погнали.

На данный момент система предоставляет возможность использовать плагины для перехвата, анализа и подмены протокола UO версии 6-х клиентов. Плагины - это обыкновенные dll библиотеки с дополнительными правилами "игры". Вот код простейшего плагина на Delphi:
Код
library HelloWorld;

uses
  PluginsShared in '..\ProtocolExtender\PluginsShared.pas',
  uMain in 'HelloWorld\uMain.pas';

{$E plg}
exports InitializationProc;
begin
end.
Как видно из кода, плагин должен экспортировать процедуру InitializationProc, через которую и идет начальное "общение" с "хостом".
Текущее представление юнита PluginsShared:
Код
unit PluginsShared;

interface

const
  PF_REGISTERPACKETHANDLER: Cardinal = 1;
  PF_UNREGISTERPACKETHANDLER: Cardinal = 2;
  PF_REGISTERPACKETTYPE: Cardinal = 3; // Not supported right now. Reserved for futher use.
  PF_SENDPACKET: Cardinal = 4;

type
  TPacketHandler = function (Data: Pointer; var Size:Cardinal; var Send: Boolean; IsFromServerToClient: Boolean):Boolean stdcall;
  (**
    Send - Send this package to reciver.
    Result - If true - this event breaks bubbling.
    If Send = false then Result forced to true.
  **)

  RAPIFunc = record
    FuncType: Cardinal;
    Func: Pointer;
  End;
  PAPIFunc=^RAPIFunc;

  TInitializationProc = procedure (anAPIFunc: PAPIFunc) stdcall;

  TRegisterPacketHandler = procedure(Header:Byte; Handler: TPacketHandler) stdcall;
  TUnRegisterPacketHandler = procedure(Header: Byte; Handler: TPacketHandler) stdcall;
  TRegisterPacketType = procedure(Header:Byte; Size:Word) stdcall;
  TSendPacket = function(Packet: Pointer; Length: Cardinal; ToServer, Direct: Boolean; var Valid: Boolean):Boolean; stdcall;

implementation

end.
Как видно из этого модуля, InitializationProc имеет только один параметр - ссылку на передаваемую функцию API.
Механизм инициализации плагина следующий:
- Плагин загружается через LoadLibrary.
- Вызывается InitializationProc(nil). На этом этапе плагин может сделать какую-нибудь подготовительную работу перед приемом API.
- Передается весь набор API через последовательный вызов InitializationProc.
- Вызывается InitializationProc(nil). На этом этапе плагин может и должен установить обработчики пакетов (Путем вызов RegisterPacketHandler). Больше InitializationProc вызываться не будет.

Инициализация плагинов происходит во время обращения клиента к login.cfg. Это гарантирует что клиент еще ни разу не подключался к серверу.

Ну и на последок еще 3 файла:

Утилитарный класс-помошник:
Код
unit PluginAPI;

interface

uses PluginsShared;

type
  TPluginInitialization = procedure;

  TPluginApi = class
  private
    FRegisterPacketHandler: TRegisterPacketHandler;
    FUnRegisterPacketHandler: TUnRegisterPacketHandler;
    FSendPacket: TSendPacket;
  protected
    procedure RegisterAPIFunc(anAPIDescriptor: PAPIFunc);
  public
    procedure RegisterPacketHandler(Header:Byte; Handler: TPacketHandler);
    procedure UnRegisterPacketHandler(Header:Byte; Handler: TPacketHandler);
    function SendPacket(Packet: Pointer; Length: Cardinal; ToServer, Direct: Boolean; var Valid: Boolean):Boolean;
  end;

  procedure InitializationProc (anAPIFunc: PAPIFunc) stdcall;

var
  API : TPluginApi;
  PluginInitialization : TPluginInitialization;
  Initialized : Boolean;
  Initialazing : Boolean;

implementation

uses SysUtils;

// Procedures

procedure InitializationProc (anAPIFunc: PAPIFunc) stdcall;
begin
  API.RegisterAPIFunc(anAPIFunc);
  If anAPIFunc = nil Then Begin
    If not Initialazing Then Initialazing := True
    else Begin
      Initialazing := False;
      If Assigned(PluginInitialization) Then PluginInitialization();
      Initialized := True;
    End;
  End;
end;

// TPluginApi

procedure TPluginApi.RegisterAPIFunc(anAPIDescriptor: PAPIFunc);
begin
  If anAPIDescriptor = nil Then Exit;
  If anAPIDescriptor^.FuncType = PF_REGISTERPACKETHANDLER Then
    FRegisterPacketHandler := anAPIDescriptor^.Func
  Else If anAPIDescriptor^.FuncType = PF_UNREGISTERPACKETHANDLER Then
    FUnRegisterPacketHandler := anAPIDescriptor^.Func
  Else If anAPIDescriptor^.FuncType = PF_SENDPACKET Then
    FSendPacket := anAPIDescriptor^.Func
end;

procedure TPluginApi.RegisterPacketHandler(Header:Byte; Handler: TPacketHandler);
begin
  If @FRegisterPacketHandler = nil Then Raise Exception.Create('RegisterPacketHandler not supplied by host');
  FRegisterPacketHandler(Header, Handler);
end;

procedure TPluginApi.UnRegisterPacketHandler(Header:Byte; Handler: TPacketHandler);
begin
  If @FUnRegisterPacketHandler = nil Then Raise Exception.Create('UnRegisterPacketHandler not supplied by host');
  FUnRegisterPacketHandler(Header, Handler);
end;

function TPluginApi.SendPacket(Packet: Pointer; Length: Cardinal; ToServer, Direct: Boolean; var Valid: Boolean):Boolean;
begin
  If @FSendPacket = nil Then Raise Exception.Create('SendPacket not supplied by host');
  Result := FSendPacket(Packet, Length, ToServer, Direct, Valid);
end;

initialization
  API := TPluginApi.Create;
  PluginInitialization := nil;
finalization
  API.Free;
end.
Полный пример HelloWorld.plg(основной фаил):
Код
library HelloWorld;

uses
  PluginsShared in '..\ProtocolExtender\PluginsShared.pas',
  PluginAPI in 'Common\PluginAPI.pas',
  uMain in 'HelloWorld\uMain.pas';

{$E plg}
exports InitializationProc;
begin
end.
Ну и uMain.pas:
Код
unit uMain;

interface

implementation

uses Windows, WinSock, PluginAPI;

var
  HelloWorldPacket: Array [0..56] of Byte;

function HelloHandler(Data: Pointer; var Size:Cardinal; var Send: Boolean; IsFromServerToClient: Boolean):Boolean stdcall;
var
  isValid: Boolean;
begin
  API.UnRegisterPacketHandler($3A, @HelloHandler);
  API.SendPacket(@HelloWorldPacket, 57, False, True, isValid);
  Result := False;
end;

procedure Init;
var
  sDummy: String;
Begin
  API.RegisterPacketHandler($3A, @HelloHandler);

// Filling Hello world packet
  ZeroMemory(@HelloWorldPacket, 57);
  PByte(@HelloWorldPacket)^ :=  $1C; //Header (1Byte)
  PWord(Cardinal(@HelloWorldPacket) + 1)^ :=  htons(57); // SizeOfpacket (2Bytes)
  PCardinal(Cardinal(@HelloWorldPacket) + 3)^ :=  $FFFFFFFF; //Serial (4Bytes)
  PWord(Cardinal(@HelloWorldPacket) + 7)^ :=  $FFFF; // Graphic (2Bytes)
  PByte(Cardinal(@HelloWorldPacket) + 9)^ :=  $00; // MessageType (1Byte)
  PWord(Cardinal(@HelloWorldPacket) + 10)^ :=  htons($03B2); // Hue (2Bytes)
  PWord(Cardinal(@HelloWorldPacket) + 12)^ :=  htons($0003); // Font (2Bytes)
  sDummy := 'System';
  CopyMemory(PChar(Cardinal(@HelloWorldPacket) + 14), @sDummy[1], 6); // Name (30Bytes)
  sDummy := 'Hello World!' + #0;
  CopyMemory(PChar(Cardinal(@HelloWorldPacket) + 44), @sDummy[1], 12); // Message (Various)
End;

initialization
  PluginInitialization := @Init;
end.


Пожелания, предложения, помидоры?

ЗЫ: Текущую версию ProtocolExtender'а выложу чуть позже.
Warstone
Да, ну и дальнейшие планы:

1) Переделать инициализацию на вызов не по "одной процедуре", а все сразу скопом.
2) Дать возможность указывать протокол в плагине (поддержка любого протокола любой версии, если вы напишите "протокольный плагин")
Можно указывать протокол, который не следует стандарту "Если длинна пакета не известна, то она пишется во 2-м и 3-м байте пакета"
3) Криптование со стороны клиента и сервера (Шифрованный клиент к нешифрованному серверу и наоборот).
4) Распаковка/Запаковка zlib'ом пакета с Гампами (и других пакетов, если такие будут)
5) Доработка утилитарных классов. В частности для чтения/записи пакетов.
6) Механизм отслеживания "оригинальных" и "измененных" Серийников для того, чтобы можно было удобно и безопасно спавнить айтемы и мобайлы в мире через прокси, а не через сервер
Частично сделан. Всего будет 3 механизма:
1) Статический (Администратор сервера выделяет большой пул серийников, пул задается в конфиге перехватчика)
2) Серверный (Сервер, по запросу, предоставляет маленькие пулы серийников, пулы получаются через расширение протокола)
3) Проксируемый (Перехватчик выдает незанятые серийники, если сервер их занимает, начинается трансляция серийников из серверный в клиентские и обратно)
Пока сделан механизм 1.

7) Получение плагинов с сервера и инкапсуляция своего протокола внутрь УО'шного для управления системой с сервера. (Собственно это была основная цель данного проекта. Дать возможность держателям серверов "дописывать" поведение клиента в зависимости от своих пожеланий)
8) Механизм временных событий (стандартные средства тут не работают).
9) Механизм синхронизации с другими потоками клиента (необходимо для реализации перехвата API в плагинах)
Синхронизация сделана через 2-х ступенчатую систему изменения Interlocked переменных.

999) Оптимизация протокола УО для большей эффективности передачи данных и снижению нагрузки на канал.
Wap
Потестил "демонстрационную" версию.
Запускает клиент нормально, коннектится нормально, играть вроде можно, лог пакетов идет. Короче говоря, никаких проблем не обнаружено. (Клиент: 6.0.13.0; Эмулятор: SphereServer 0.56b, одна из последних сборок).
По коду сказать нечего, я не программист. smile.gif

P.s. А нет, рано порадовался, что проблем совсем нет. При закрытии клиента крестиком гарантировано вылетает вот такое:
Нажмите для просмотра прикрепленного файла
Ozzy Osbourne
А что поддержки более ранних версий клиента можно не ждать?
Warstone
Цитата(wap @ 22.12.2010, 17:39) *

Потестил "демонстрационную" версию.
Запускает клиент нормально, коннектится нормально, играть вроде можно, лог пакетов идет. Короче говоря, никаких проблем не обнаружено. (Клиент: 6.0.13.0; Эмулятор: SphereServer 0.56b, одна из последних сборок).
По коду сказать нечего, я не программист. smile.gif

P.s. А нет, рано порадовался, что проблем совсем нет. При закрытии клиента крестиком гарантировано вылетает вот такое:
Нажмите для просмотра прикрепленного файла

Угу. Правильно. Оно и должно. Это связано с тем, что по закрытию процесса я не убиваю там консоль. Короче, это баг, но он фича.

Цитата(Ozzy Osbourne @ 23.12.2010, 1:50) *

А что поддержки более ранних версий клиента можно не ждать?
Вообще - я сильно их не люблю. Правда это не значит что нельзя. В плагинах будет возможность (уже сейчас есть) переопределить протокол, как вам хочется. То есть берете маны по протоколу 2.0.3 клиента и перебиваете длинны пакетов.

А вообще, в PluginsShared сейчас уже 13 или 14 номер под API забит
Warstone
Только что получилось в ран-тайме объяснить что в staidx0.mul все записи типа:
0xFFFFFFFFh;
0;
0;

Объяснил... Статика из мира пропала. Радуюсь. Возможно таким-же макаром можно будет объяснять что статика поменялась.
Warstone
Текущий код залит в транк. Код доступен тут: http://code.google.com/p/uo-ext/source

Желающие могут присоединиться.

Не факт что код вообще рабочий =)
StaticZ
наконец-то!!, уже солидный проект с сайтом smile.gif будем надеятся что не забьеш и доведеш проект до конца.

ЗЫ Еслиб был шарп или С++ присоединился, но от дельфи как-то уже отвык и нос немног воротит... Хотя плагины мона ведь на си писать.. так что могу подсобить с чем-то, правда сильно на меня не рассчитывай - сам знаешь я и так весь перегружен своим проектом
Warstone
Ну плагины действительно на чем угодно можно писать (уже сейчас).
StaticZ
Цитата(Warstone @ 7.1.2011, 16:55) *

Ну плагины действительно на чем угодно можно писать (уже сейчас).

Недельки через две попробую ченить замутить, щас дел много mad.gif а кстати могу еще помочь с расширением для ранки и енкриптом протокола (если еще не сделал).
Warstone
Цитата
а кстати могу еще помочь с расширением для ранки
Тут не понял.
Цитата
енкриптом протокола
Пока не надо, но если очень интересно - могу дать коммитера - сделаешь себе бранч и... Ну ты понял =))
Warstone
Почистил код. 5-я ревизия должна автоматом собираться и работать. Нужны волонтеры для тестирования и помощи.
Warstone
Волонтеров нету (внезапно).

Вопрос сообществу: Некоторые аспекты автоматического декрипта вынуждают поддерживать клиенты только версий старше 6.0.6.0 примерно... (Фактически - с тех пор, как появился 0xEF пакет. То есть новый механизм Сида и версии)

Сейчас склоняюсь к тому, что-бы внести директиву компиляции. Что-то типа CLIENC - если она будет, то программа попытается определить шифрование и работать с шифрованным протоколом со стороны клиента. Если нету - то считается что шифрование снято.

Так-же будет директива SRVENC которая отвечает за шифрование со стороны сервера (Вообще - за возможность шифрования, так как те настройки, которые есть в ShardSertup в последствии будут автоматом получаться с сервера на логин стадии, а есть-ли шифрование со стороны сервера - будет выполнено в виде настройки именно в этом модуле).
StaticZ
Цитата(Warstone @ 15.1.2011, 4:29) *

Волонтеров нету (внезапно).

Вопрос сообществу: Некоторые аспекты автоматического декрипта вынуждают поддерживать клиенты только версий старше 6.0.6.0 примерно... (Фактически - с тех пор, как появился 0xEF пакет. То есть новый механизм Сида и версии)

Сейчас склоняюсь к тому, что-бы внести директиву компиляции. Что-то типа CLIENC - если она будет, то программа попытается определить шифрование и работать с шифрованным протоколом со стороны клиента. Если нету - то считается что шифрование снято.

Так-же будет директива SRVENC которая отвечает за шифрование со стороны сервера (Вообще - за возможность шифрования, так как те настройки, которые есть в ShardSertup в последствии будут автоматом получаться с сервера на логин стадии, а есть-ли шифрование со стороны сервера - будет выполнено в виде настройки именно в этом модуле).


ну я предлагал свою помощь, а ты говориш нет smile.gif

директивы компиляции - бред... конечно для разработки может и прикольно, но для пользователей нет.. лучше уш передать два параметра в качестве аргументов или взять из инишника (1е предпочтительнее т.к. например позволит запускать один и тотже ехе с разными параметрами для разных серверов и не плодить сто пятсот одинаковых ехе шников + пара ярлыков или батников для ламеров для запуска).. А вообще наличие шифрования или его отсутсвия можно автоматически определить )
Warstone
Цитата
ну я предлагал свою помощь, а ты говориш нет
Когда я это говорил?
Цитата
А вообще наличие шифрования или его отсутсвия можно автоматически определить
Да, но если у тебя версия до 6.0.5.0, то снять автоматом шифрование - ты не сможешь. Ключи нужны. Или версию читать из ехе (где она там зашита - хз). Как результат - шифрование есть, но оно не снимается... Все идут лесом.
Цитата
1е предпочтительнее т.к. например позволит запускать один и тотже ехе с разными параметрами для разных серверов и не плодить сто пятсот одинаковых ехе шнико

Ты, видно, вообще не смотрел как работает эта система... Она не меняет ехе. Она подключает в АП ехе свою длл. Поэтому не 100500 ехе, а 100500 длл, это раз. Второе - в планах конфиг сервера получать с сервера. То есть конфигурацией приложения будет заниматься исключительно сервер, а не ини. Никаких ини - это не "еще одна макро система".

Хотя я, наверно, понял о чем ты... По идеи можно и без дириктив компиляции... Хотя все-таки Вариант с дириктивами я, наверно, оставлю. Для тех, кто захочет оттюнинговать само ядро, что-бы оно быстрее работало/меньше занимало и т.д.
StaticZ
Цитата(Warstone @ 15.1.2011, 15:23) *

Когда я это говорил?
"Волонтеров нету (внезапно)."

Цитата(Warstone @ 15.1.2011, 15:23) *

Или версию читать из ехе (где она там зашита - хз)
Именно ее и читать, она нигде не зашита а спокойно сидит в таблице ресурсов... прочитать не проблема. винапи ето умеет )

Цитата(Warstone @ 15.1.2011, 15:23) *

Она подключает в АП ехе свою длл.
ммм хитро..... я то думал это просто ммм сервер
Warstone
Цитата
"Волонтеров нету (внезапно)."
А до этого фразу 5 дней назад про необходимость волонтеров - не видел?
Цитата
Именно ее и читать, она нигде не зашита а спокойно сидит в таблице ресурсов... прочитать не проблема. винапи ето умеет
Уже рассказали... Значит, возможно, я рано бью тревогу.
Цитата
ммм хитро..... я то думал это просто ммм сервер
Ну в АП ехе создается в отдельном потоке прокси-сервер. Клиент насильственно подключается к этому прокси (да, а клиент и сервер сидят в одном процессе. Вот такая-вот загогулина).
Надо это для того, чтобы можно было перехватывать обращение клиента к WinAPI. Там будут единственные проблемы с синхронизацией, но они решаемы. Зато не надо будет городить межпроцессное взаимодействие.
Wap
Что касается меня, я вроде уже отписывался(касается почти всех подобных задумок):
- могу потестить что-либо.
- могу оценить совместимость чего-либо с эмулятором SphereServer 0.56b.
В случае, если это не требует особых знаний или больших затрат времени.
Не программист, поэтому помочь в написании програмного кода чего-либо не могу, да и времени лишнего нет.
Warstone
Да.... насколько я понял тут 3 калеки (включая меня) )). Ладно, проехали. Сейчас силы сосредоточенны на поддержку шифрования со стороны клиента (эмуляция галочки Patch OSI encryption в Razor или UORise, если коротко). Со стороны сервера - хз надо-ли вообще.
Warstone
Собственно новости:
В готовящейся версии:
- Фикс багов (в частности, самый тупой, который видел - Вызов zLib крашился, если самой zLib не было).
- Шифрование. Сейчас работает прозрачное шифрование Login сессии. Со стороны клиента - автоопределение, в сторону сервера - задается в настройках шарда. Коммит будет, когда будет работать шифрование Игрового сервера.

Да, похоже что Шифрование это началось с 3-х клиентов. То есть 2-е клиенты могу (надо тестировать вообще-то) пойти лесом (ну пока-что).
Warstone
Следующая ревизия. Детект шифрования клиента. Полностью работает нешифрованный клиент (с проксей, умеющей определять шифрование), Логи и часть Геим шифрования в шифрованном клиенте. Тут не успел вчера просто.

И код опять немного отрефакторился.
Wap
Цитата(Warstone @ 30.1.2011, 4:36) *

Да, похоже что Шифрование это началось с 3-х клиентов. То есть 2-е клиенты могу (надо тестировать вообще-то) пойти лесом (ну пока-что).
По моим данным, начиная с версии 2.0.4 до настоящего времени используется 1 и тот же тип шифрования. В более ранних клиентах есть какие-то нюансы. Вот, кусок из списка криптов сферы:
Цитата
[DEFNAME ENC_TYPE]
ENC_NONE 0 // No encryption
ENC_BFISH 1 // Blowfish
ENC_BTFISH 2 // Blowfish + Twofish
ENC_TFISH 3 // Twofish

0700110 02DFB574D 0A3ED9E7F ENC_TFISH // 7.00.110
...
0200040 02DF385BD 0A3ED127F ENC_TFISH // 2.00.40
0200030 02DBBB7CD 0A3C95E7F ENC_BTFISH // 2.00.30
0200020 02D63ADDD 0A3A5227F ENC_BTFISH // 2.00.20
0200010 02D2BA7ED 0A3817E7F ENC_BTFISH // 2.00.10
0200000 02D13A5FD 0A39D527F ENC_BTFISH // = 2.00.00X
0200000 02D13A5FD 0A39D527F ENC_BFISH // 2.00.00
Что такое Blowfish и Twofish я лично не в курсе, можешь сам узнать, если хочешь.
Warstone
http://code.google.com/p/uo-ext/source/bro...der/Twofish.pas

Ой...

Но все-равно - спасибо.

На самом деле надо будет распотрошить исходники инжекта.

Кстати, именно по этому я и говорил что 2.0.3 и ниже - поддерживаться, скорее всего, не будут. Мне лениво делать старое шифрование. И если новое - нормально, так как будет спрос на "вот это, но без Разора", то до 2.0.3... Сами снимете.
StaticZ
Цитата(wap @ 1.2.2011, 20:56) *

Что такое Blowfish и Twofish я лично не в курсе, можешь сам узнать, если хочешь.

Алгоритмы шифрования:
http://ru.wikipedia.org/wiki/Blowfish
http://ru.wikipedia.org/wiki/Twofish
Warstone
Поддержка шифрованного клиента есть. Надо потестить на шифровнном сервере. То есть чтоб и клиент был шифрованный и сервер... Где-бы такой взять, кроме как на ОСИ?
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.
Русская версия Invision Power Board © 2001-2026 Invision Power Services, Inc.