Основы использования hLaPeX
|
|
ARMIA |
Дата: Пятница, 19.09.2008, 16:00 | Сообщение # 1 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
Содержание I. Login-сервер 1. Шифрование пакетов 2. Структура пакетов II. Game-сервер. 1. Протокол 2. xID и ObjectID 3. Примеры пакетов: a) скупка/продажа b) личка c) OID и IID d) говорим с NPC на примере разучивания скиллов III. Проблемы и как можно их использовать 1. отсутствие лимита на кол-во попыток авторизации 2. Удалённое определение версии lineage2 сервера 3. Удалённое "подвешивание" login-сервера 4. Клонирование 5. Создание "мутантов" и смешение скиллов 6. Бессмертие 7 'remote DoS' и что это даёт 8 SQL-injection 9 Заточка (или сказка о 100%-ом enchant'е) 10Геодата (хождение сквозь стены) 11 Прикол с SocialAction (0x1b) 12 Баг в Ride (0x6a) 13 Выкидываем из игры чаров 14 Баг с RequestRestartPoint (оживление и побег из тюрьмы) 15 Раздеть чужого персонажа не зная ни логина, ни пароля - разве это реально? 16 Итог VI. Пара слов о C4 hLaPeX - основы I. Login-сервер. Введение. Начнём с того, что разработчики lineage2 отделили логин сервер от игрового, дабы более менее разгрузить и без того забитый канал игрового сервера. Кроме того, логин сервер имеет свойство повисать (причём, это началось с с3 версии lineage и продолжается по сей день) и не пускать пользователей на сервер. Зато те, кто уже играют, не испытывают совершенно никакого дискомфорта =) А вследствие отсутсвия всё тех же багоискателей, которые могли бы найти и внятно объяснить девелоперам, где же всё-таки закрался баг, он остаётся до сих пор непофиксанным. Так вот, не смотря на всю прелесть идеи с разгрузкой игрового канала, наши отечественные админы упорно лепят логин сервер на одну машину вместе с игровым. 1. Шифрование пакетов. Для шифрования пакетов, которыми login-сервер обменивается с клиентом, lineage использует blowfish. Да, тот самый алгоритм, который был разработан Брюсом Шнейером в 1993 году. Про blowfish важно знать, что это симметричный блочный шифр. Симметричный - означает, что алгоритм использует 1 секретный ключ, которым и шифруются/дешифруются данные. А если говорить конкретно о blowfish, то на основе этого ключа генерируются 18 32-битных подключей и 4 матрицы размером 256 32-битовых слов каждая. Которыми, в свою очередь, шифруются/дешифруются данные. Блочный шифр - означает, что blowfish обрабатывает данные блоками (по 8 байт). А ещё это означает, что если целостность шифротекста была нарушена, то часть мы по-любому сможем восстановить. Применительно к lineage, нужно сказать, что ключ, на основе которого генерируются подключи, является константой и чётко прописан в исходниках l2j (вот на чём сыпались 99% исследователей lineage, которые предполагали, что ключ должен передаваться в одном из пакетов - см. ссылки в конце). Ещё важно отметить то, что первые 2 байта данных пакета _не_шифруются_. Чтож, с шифрованием, я думаю, мы разобрались. Идём дальше. 2. Структура пакетов. Первые два байта пакета (те, которые не шифруются) содержат длину данных пакета (как и в halflife). Следующий байт несёт в себе информацию о типе пакета. Логин-сервер обрабатывает пакеты: 0x00 - RequestAuthLogin (запрос на авторизацию - содержит логин и пароль) 0x02 - RequestServerLogin (запрос на заход на сервер) 0x05 - RequestServerList (запрос на список серверов) |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:00 | Сообщение # 2 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
На остальные он попросту не отвечает, оставляя лишь запись в логах. Клиентом же обрабатываются пакеты следующих типов: 0x01 - авторизация не прошла 0x03 - вы успешно авторизованы 0x04 - ответ на RequestServerLogin 0x06 - ответ на RequestServerList А также несколько дополнительные пакетов о бане аккаунта, проверки версии и тд - они представлены ниже. Следующий байт является дополнительным к вышеописанным запросам. Например, если сервер ответил нам на запрос авторизации пакетом типа 0x01, то следующий байт будет содержать причину, по которой авторизация не прошла (для нас важны: 0x03 - неверный логин или пароль, 0x07 - кто-то уже юзает аккаунт, 0x11 - установлен временный пароль). Но на самом деле этот байт уже не совсем служебный. Например, в RequestAuthLogin пакетах с этого байта начинается логин. Далее идёт Н-ное число байт, которые уже не являются управляющими, а несут информацию, определяемую типом пакета. Ну, например, для "RequestAuthLogin" это поле содержит логин и пароль. Важное предназначение имеют последние 8 байт пакета. Они содержат чексуму всего того, что идёт до них, за исключением опять же первых двух байт пакета. Каким же образом вычисляется эта самая чексумма? Из данных поочерёдно отделяются 32-битные слова. Первое XOR'ится со вторым. Результат этой операции XOR'ится со следующим словом и так далее. Пример вычисления чексуммы будет продемонстрирован ниже. |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:00 | Сообщение # 3 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
II. Game-сервер. 1. Протокол. Как и в пакетах login-сервера, первые два байта отводятся под длину. Далее байт означает тип пакета. Вот типы пакетов, которые должен обрабатывать С3 клиент lineage2 (некоторые буду комментировать): // отсылает login-сервер 0x01 loginfail2 0x02 accountKicked1 0x03 loginok 0x04 serverlist 0x05 serverfail 0x06 playfail 0x07 playok 0x08 accountKicked 0x09 blockedAccMsg // бан 0x20 protocol version different 0x00 VersionCheck // отсылает game-сервер 0x01 MoveToLocation 0x02 NpcSay 0x03 CharInfo // имеется в виду окружающие персы 0x04 UserInfo 0x06 Attack 0x07 Attack 0x08 Attacked 0x09 Attacked 0x0a AttackCanceld 0x0b Die 0x0c Revive 0x0d AttackOutOfRange 0x0e AttackInCoolTime 0x0f AttackDeadTarget 0x10 LeaveWorld 0x11 AuthLoginSuccess 0x12 AuthLoginFail 0x13 CharList // список чаров 0x15 SpawnItem // на некоторых С3 ответ на выбор чара 0x16 DropItem // на некоторых С3 передаёт инфо о мобе 0x17 GetItem 0x18 EquipItem 0x19 UnequipItem 0x1a StatusUpdate 0x1b NpcHtmlMessage // на некоторых С3 передаёт список шмота с ItemID и их ObjectID 0x1c SellList 0x1d BuyList 0x1e DeleteObject 0x1f CharSelectInfo 0x20 LoginFail 0x21 CharSelected 0x22 NpcInfo 0x23 NewCharacterSuccessPacket 0x24 NewCharacterFailPacket 0x25 CharCreateOk 0x26 CharCreateFail 0x27 ItemList 0x28 SunRise 0x29 SunSet 0x2a EquipItemSuccess // устарел 0x2b EquipItemFail // устарел 0x2c UnEquipItemSuccess // устарел 0x2d UnEquipItemFail // устарел 0x2e TradeStart 0x2f TradeStartOk // устарел 0x30 TradeOwnAdd 0x31 TradeOtherAdd 0x32 TradeDone 0x33 CharDeleteSuccess 0x34 CharDeleteFail 0x35 ActionFail 0x36 ServerClose 0x37 InventoryUpdate 0x38 TeleportToLocation 0x39 TargetSelected 0x3a TargetUnselected 0x3b AutoAttackStart 0x3c AutoAttackStop 0x3d SocialAction 0x3e ChangeMoveType 0x3f ChangeWaitType 0x40 NetworkFail // устарел 0x43 CreatePledge 0x44 AskJoinPledge 0x45 JoinPledge 0x46 WithdrawalPledge 0x47 OustPledgeMember 0x48 SetOutPledgeMember 0x49 DismissPledge 0x4a SetDismissPledge 0x4b AskJoinParty 0x4c JoinParty 0x4d WithdrawalParty 0x4e OustPartyMember 0x4f SetOustPartyMember 0x50 DismissParty 0x51 SetDismissParty 0x52 MagicAndSkillList 0x53 WarehouseDepositList 0x54 WarehouseWithdrawalList 0x55 WarehouseDone 0x56 ShortCutRegister 0x57 ShortCutInit 0x58 ShortCutDelete 0x59 StopMove 0x5a MagicSkillUser 0x5b MagicSkillCanceld |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:01 | Сообщение # 4 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
0x5d CreatureSay 0x5e EquipUpdate 0x5f StopMoveWithLocation 0x60 DoorInfo 0x61 DoorStatusUpdate 0x63 PartySmallWindowAll 0x64 PartySmallWindowAdd 0x65 PartySmallWindowDeleteAll 0x66 PartySmallWindowDelete 0x67 PartySmallWindowUpdate 0x68 PledgeShowMemberListAll 0x69 PledgeShowMemberListUpdate 0x6a PledgeShowMemberListAdd 0x6b PledgeShowMemberListDelete 0x6c MagicList // устарел 0x6d SkillList 0x6e VehicleInfo 0x6f VehicleDeparture 0x70 VehicleCheckLocation 0x71 GetOnVehicle 0x72 GetOffVehicle 0x73 TradeRequest 0x74 RestartResponse 0x75 MoveToPawn 0x76 SetTo 0x77 StartRotating 0x78 FinishRotating 0x79 MoveBackwardToLocation // имеется ввиду скилл или to_the_nearest_village после смерти 0x7a SystemMessage 0x7d StartPledgeWar 0x7e ReplyStartPledgeWar 0x7f StopPledgeWar 0x80 ReplyStopPledgeWar 0x81 SurrenderPledgeWar 0x82 ReplySurrenderPledgeWar 0x83 SetPledgeCrest // устарел 0x84 PledgeCrest 0x85 SetupGauge 0x86 ShowBoard 0x87 ChooseInventoryItem 0x89 MoveToLocationInVehicle 0x8a StopMoveInVehicle 0x8b ValidateLocationInVehicle 0x8c TradeOtherAdd2 0x8d TradePressOwnOK // устарел 0x8e MagicSkillLaunched 0x8f FriendAddRequestResult 0x90 FriendAdd // устарел 0x91 FriendRemove // устарел 0x92 FriendList // устарел 0x93 FriendStatus // устарел 0x94 TradePressOtherOk // устарел 0x95 FriendAddRequestResult2 0x96 LeaveWorld2 0x97 AbnormalStatusUpdate 0x98 QuestList 0x99 EnchantResult 0x9a AuthServerList // устарел 0x9b PledgeShowMemberListDeleteAll 0x9c PledgeInfo 0x9d PledgeExtendedInfo 0x9e SurrenderPersonally 0x9f Ride 0xa1 PledgeShowInfoUpdate 0xa2 ClientAction 0xa3 AquireSkillList 0xa4 AquireSkillInfo 0xa5 ServerObjectInfo 0xa6 HideGm 0xa7 AquireSkillDone 0xa8 GMViewCharacterInfo 0xa9 GMViewPledgeInfo 0xaa GMViewSkillInfo 0xab GMviewMagicInfo 0xac GMViewQuestInfo 0xad GMViewItemList 0xae GMViewWarehouseWithdrawList 0xaf PartyMatchList 0xb0 PartyMatchDetail 0xb1 PlaySound 0xb2 StaticObject 0xb3 PrivateSellList2 0xb4 PrivateBuyList2 0xb5 PrivateStoreMsg 0xb6 ShowMinimapPacket 0xb7 ReviveRequest // устарел 0xb8 AbnormalVisualEffect 0xb9 TutorialShowHtml 0xba TutorialShowQuestionMark 0xbb TutorialEnableClientEvent 0xbc TutorialClose 0xbd ShowRadar 0xbe DeleteRadar 0xbf MyTargetSelected 0xc0 PartyMemberPosition 0xc1 AskJoinAlliance 0xc2 JoinAlliance 0xc3 WithdrawAlliance 0xc4 OustAllianceMemberPledge 0xc5 DismissAlliance 0xc6 SetAllianceCrest // устарел 0xc7 ReceiveAllyCrest 0xc8 ServerCloseSocket // устарел 0xc9 PetStatusShow 0xca PetInfo 0xcb PetItemList 0xcc PetInventoryUpdate 0xcd AllianceInfo // устарел 0xce PetStatusUpdate 0xcf PetDelete 0xd0 PrivateSellList 0xd1 PrivateBuyList 0xd2 PrivateStoreMsg 0xd3 VehicleStart 0xd4 RequestTimeCheck 0xd5 StartAllianceWar 0xd6 ReplyStartAllianceWar // устарел 0xd7 StopAllianceWar 0xd8 ReplyStopAllianceWar // устарел 0xd9 SurrenderAllianceWar // устарел 0xda SkillCoolTimePacket 0xdb PackageToListPacket 0xdc PackageSendableListPacket 0xdd EarthQuake 0xde FlyToLocation 0xdf BlockList // устарел 0xe0 SpecialCamera 0xe1 NormalCamera 0xe2 CastleSiegeInfoPacket 0xe3 CastleSiegeAttackerList 0xe4 CastleSiegeDefenderList 0xe5 NickNameChanged 0xe6 PledgeStatusChanged 0xe7 RelationChanged 0xe8 OnEventTrigger 0xe9 MultiSellListPacket 0xea SetSummonRemainTime 0xeb OnSkillRemainSec 0xec NetPingPacket |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:01 | Сообщение # 5 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
От клиента серверу: 0x01 MoveBackwardToLocation 0x02 Say 0x03 EnterWorld 0x04 Action 0x08 RequestAuthLogin 0x09 Logout 0x0a Attack 0x0b CharacterCreate 0x0c CharacterDelete 0x0d CharacterSelect 0x0e NewCharacter 0x0f ItemList 0x10 RequestEquipItem 0x11 RequestUnEquipItem 0x12 RequestDropItem 0x12 RequestDropItemFromPet 0x14 UseItem 0x15 TradeRequest 0x16 AddTradeItem 0x17 TradeDone 0x1a RequestTeleport 0x1b SocialAction 0x1c ChangeMoveType // устарел. Теперь юзается 'RequestActionUse' 0x1d ChangeWaitType // устарел. Теперь юзается 'RequestActionUse' 0x1e RequestSellItem 0x1f RequestBuyItem 0x20 RequestLinkHtml 0x21 RequestBypassToServer 0x22 RequestBBSwrite 0x23 RequestCreatePledge 0x24 RequestJoinPledge 0x25 RequestAnswerJoinPledge 0x26 RequestWithDrawalPledge 0x27 RequestOustPledgeMember 0x28 RequestDismissPledge 0x29 RequestJoinParty 0x2a RequestAnswerJoinParty 0x2b RequestWithDrawalParty 0x2c RequestOustPartyMember 0x2d RequestDismissParty 0x2e RequestMagicSkillList 0x2f RequestMagicSkillUse 0x30 Appearing 0x31 SendWareHouseDepositList 0x32 SendWareHouseWithDrawList 0x33 RequestShortCutReg 0x34 RequestShortCutUse 0x35 RequestShortCutDel 0x37 RequestTargetCancel 0x38 Say2 // приват (на некоторых серверах - la2.ru - юзается 0x39) 0x3c RequestPledgeMemberList 0x3e RequestMagicList 0x3f RequestSkillList 0x41 MoveWithDelta 0x42 GetOnVehicle 0x43 GetOffVehicle 0x44 AnswerTradeRequest 0x45 RequestActionUse 0x46 RequestRestart 0x47 RequestSiegeInfo 0x48 ValidatePosition 0x49 RequestSEKCustom 0x4a StartRotating 0x4b FinishRotating 0x4d RequestStartPledgeWar 0x4e RequestReplyStartPledgeWar 0x4f RequestStopPledgeWar 0x50 RequestReplyStopPledgeWar 0x51 RequestSurrenderPledgeWar 0x52 RequestReplySurrenderPledgeWar 0x53 RequestSetPledgeCrest 0x55 RequestGiveNickName // вообще юзается для установки тайтла CL'ами. Может для чего ещё.. 0x57 RequestShowboard 0x58 RequestEnchantItem 0x59 RequestDestroyItem 0x5b SendBypassBuildCmd 0x5e RequestFriendInvite 0x5f RequestFriendAddReply 0x60 RequestFriendList 0x61 RequestFriendDel 0x62 CharacterRestore 0x63 RequestQuestList 0x64 RequestDestroyQuest 0x66 RequestPledgeInfo 0x67 RequestPledgeExtendedInfo 0x68 RequestPledgeCrest 0x69 RequestSurrenderPersonally 0x6a Ride 0x6b RequestAcquireSkillInfo 0x6c RequestAcquireSkill 0x6d RequestRestartPoint 0x6e RequestGMCommand 0x6f RequestPartyMatchConfig 0x70 RequestPartyMatchList 0x71 RequestPartyMatchDetail 0x72 RequestCrystallizeItem 0x73 RequestPrivateStoreManage 0x74 SetPrivateStoreList 0x75 RequestPrivateStoreManageCancel 0x76 RequestPrivateStoreQuit 0x77 SetPrivateStoreMsg 0x78 RequestPrivateStoreList 0x79 SendPrivateStoreBuyList 0x7a ReviveReply 0x7b RequestTutorialLinkHtml 0x7c RequestTutorialPassCmdToServer 0x7d RequestTutorialQuestionMark 0x7e RequestTutorialClientEvent 0x7f RequestPetition 0x80 RequestPetitionCancel 0x81 RequestGMList 0x82 RequestJoinAlly 0x83 RequestAnswerJoinAlly 0x84 RequestWithdrawAlly 0x85 RequestOustAlly 0x86 RequestDismissAlly 0x87 RequestSetAllyCrest 0x88 RequestAllyCrest 0x89 RequestChangePetName 0x8a RequestPetUseItem 0x8b RequestGiveItemToPet 0x8c RequestGetItemFromPet 0x8e RequestAllyInfo 0x8f RequestPetGetItem 0x90 RequestPrivateStoreBuyManage 0x91 SetPrivateBuyList 0x92 RequestPrivateStoreBuyManageCancel 0x93 RequestPrivateStoreBuyQuit 0x94 SetPrivateBuyMsg 0x95 RequestPrivateStoreBuyList 0x96 SendPrivateStoreBuyBuyList 0x97 SendTimeCheckPacket 0x98 RequestStartAllianceWar 0x99 ReplyStartAllianceWar 0x9a RequestStopAllianceWar 0x9b ReplyStopAllianceWar 0x9c RequestSurrenderAllianceWar 0x9d RequestSkillCoolTime 0x9e RequestPackageSendableItemList 0x9f RequestPackageSend 0xa0 RequestBlock 0xa1 RequestCastleSiegeInfo 0xa2 RequestCastleSiegeAttackerList 0xa3 RequestCastleSiegeInfo 0xa4 RequestJoinCastleSiege 0xa5 RequestConfirmCastleSiegeWaitingList 0xa6 RequestSetCastleSiegeTime 0xa7 RequestMultiSellChoose 0xa8 NetPing |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:01 | Сообщение # 6 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
Как видите, большинство клиентских пакетов начинается со слова Request, что переводится как "запрос". Да, действительно, весь процесс игры выглядит примерно так: сервер постоянно передаёт нам состояние мира, положение мобов/игроков/npc и тд. Мы же, когда что-то надо (пойти, атаковать и тд) передаём "запрос". Всё очень просто. |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:02 | Сообщение # 7 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
2. XID и ObjectID Каждая вещь (предмет, NPC) в игре имеет свой 16/32-битный идентификатор (профессии - 8-ми битный). Его смысл в том, что, согласитесь, удобнее передавать по сети 2/4-х байтное число, чем фразу Н-ной длины вроде: "Crystal Scroll: Enchant Weapon (Grade B)" или ник NPC вроде "Magister MacTePqpJlOMaCTeP". Как вы понимаете, он служит для идентификации того или иного объекта. Список этих идентификаторов и соответствующих им NPC/предметов храниться и на сервере и клиенте, и между собой они никак не синхронизируется. То есть, если сменить эту таблицу на сервере, то нужно патчить и клиент - это одна из причин, почему у каждого сервера свой патч. Помимо этого идентификатора есть ещё 32-ух битный Object ID. После захода в игровой мир, сервер присваивает каждому из предметов, которые есть у перса, свой уникальный OID. Причём OID каждого последующего предмета есть OID текущего -1. То есть OID генерируется отнюдь не рандомно, а по порядку. После присвоения, OID резервируется, так чтобы никто больше не умудрился получить аналогичный. Эта информация, кстати, не подтверждена исходниками, то есть является моим собственным умозаключением. Если же это не так, то по прошествию полного круга (от 0xFFFFFFFF до 0x00000000) может получится так, что уже занятый OID будет присвоен новой шмотке, что приведят к неизвестным последствиям (возможности клонирования или простому падению сервера). Но проблема в том, что диапазон OID довольно таки велик smile А если быть более точным, нужно присвоить OID ~4.3 млрду вещей, чтобы пройти полный круг, что даже на сервере с мега-онлайном займёт Н-ное число дней (а может и недель). Ещё раз повторюсь, это всего-лишь предположение. Но дело в том, что я, например, не видил ниодного la2 сервера (даже офф) с аптаймом более недели. Может проблема как раз в этом? А в целом, OID нужен для борьбы с клонированием. А точнее с выявлением оного. Что касается NPC, OID у них выдаётся по такому же закону, но при появлении NPC в мире. С OID персонажей то же самое. 3 Примеры пакетов. a) покупка предметов Для того, чтобы поставить на скупку предмет, нам нужно воспользоваться 3-мя пакетами. Первый 0x94 (SetPrivateBuyMsg). Как видно из названия он устанавливает то сообщение, которое будет выводится над головой у перса в момент торговли (то, которое на жёлтом фоне). Вот пример: // SetPrivateStoreBuyMsg пакет XX XX // Размер данных 94 // тип пакета 41 00 41 00 41 00 42 00 42 00 42 00 // текст. Символы должны быть разделены между собой null-байтом. 00 00 // конец пакета Далее используем пакет типа 0x91 (SetPrivateBuyList). В нём как раз передаём количество предметов,Item ID и цену. Например: // SetPrivateStoreList пакет XX XX // Размер данных 91 // тип пакета 01 00 00 00 // количество вещей // начало блока e1 02 00 00 // Item ID 00 00 01 00 00 00 // сколько предметов данного типа скупить e8 03 00 00 // цена // конец блока |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:02 | Сообщение # 8 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
Немного поясню этот пакет. Им мы поставили на скупку 1 вещь с IID 0x2e1 (Scroll of Resurrection) за 1000 аден. И последний пакет типа 0x1d. Он непосредственно запускает торговлю: XX XX // размер данных 1d // тип 01 00 00 00 // кол-во Что касается продажи, то там практически всё то же самое. Только вместо 'SetPrivateBuyMsg' юзаем 'SetPrivateStoreMsg', а вместо 'SetPrivateBuyList' - 'SetPrivateStoreList' соответственно. А, чуть не забыл, вместо Item ID юзаем Object ID, потому что мы продаём какой-то конкретный предмет. b) приватные сообщения Тут всё очень просто. XX XX // размер данных 38 // тип пакета (Say2) 42 00 42 00 42 00 42 // сообщение (BBBB) 00 00 00 02 00 00 00 // пробел =) 41 00 41 00 41 00 41 // ник (АААА) 00 00 00 // конец c) пример пакета в котором сервер передаёт нам список всех предметов, которые есть на чаре. Причём, именно этот пакет закрепляет за каждым Item ID уникальный Object ID. XX XX // длина пакета 1b // тип пакета (0x1b на antaras.ru) 00 00 05 00 // количество предметов 04 00 // тип шмотки 1e 26 14 40 // Object ID d4 15 00 00 // Item ID (0x15d4 - Tutorial Guide) 01 00 00 00 // Количество 05 00 00 00 00 00 00 00 00 00 00 00 00 00 // Заточка, квестовый итем, дропается или нет и ещё что-то 01 00 // тип шмотки 1d 26 14 40 // Object ID 7b 04 00 00 // Item ID (0x47b - Squire's pants) 01 00 00 00 // Количество 01 00 00 00 00 00 00 08 00 00 00 00 00 00 01 00 // тип шмотки 1c 26 14 40 // Object ID 7a 04 00 00 // Item ID (0x47a - Squire's Shirt) 01 00 00 00 // Количество 01 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 // тип шмотки 1b 26 14 40 // Object ID 0a 00 00 00 // Item ID (0x0a - dagger) 01 00 00 00 // Количество 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 // тип шмотки 1a 26 14 40 // Object ID 42 09 00 00 // Item ID (0x942 - Guild Member's Club) 01 00 00 00 // Количество 00 00 00 00 00 00 80 00 00 00 00 00 00 00 d) говорим с NPC на примере разучивания скиллов Для начала, нам нужно выделить NPC и завести с ним диалог: 04 // тип пакета (Action) 51 14 10 48 // OID NPC // далее идут координаты _нашего_ персонажа c6 51 01 00 // X 52 45 02 00 // Y b8 f2 ff ff // Z 00 // конец Причём однократная посылка этого пакета - выделение NPC. Чтобы завести с ним диалог, нужно послать этот пакет ещё раз. Далее, когда открывается окно с выбором диалогов и вы выбираете пункт "Learn skills", клиент серверу отсылает вот такой пакет: 21 // тип пакета (RequestBypassToServer) 6c 00 65 00 61 00 72 00 6e 00 5f 00 73 00 6b 00 69 00 6c 00 6c 00 00 // learn_skill 00 // конец После вызова диалога со скиллами, вы можете либо посмотреть информацию о любом скилле с помощью: 6b // тип пакета (RequestAcquireSkillInfo) 10 00 00 00 // номер скилла 09 00 00 00 // уровень Чтобы выучить этот скилл, посылается точно такой же пакет, но с типом 0x63 (RequestAcquireSkill) |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:07 | Сообщение # 9 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
III Проблемы и как можно их использовать 1. отсутствие лимита на кол-во попыток авторизации Это даёт возможность к бесконечному перебору паролей к тому или иному аккаунту. Я не буду описывать как и чего, брутфорсер он и в Африке брутфорсер. Расскажу лишь о своём личном опыте в этой области. Испытание проводилось на www.antaras.ru - старый, вымирающий отечественный lineage2 C1OFF сервер (с добавками из с3). Используя только ту информацию (ну и non-blocking sockets), что я предоставил выше, был написан брутфорсер (переборщик логинов и паролей) и программа, которая выдирает список ников, играющих в данный момент на сервере с 'http://antharas.ru/?id=2'. Составил от балды список паролей типа 123456789, 0987654321 (на antaras.ru минимальная длина пароля 8 символов - на всех серверах по-разному), список с никами,в данный момент играющих на сервере геймеров,составил ~1500 строк. Переборщик я запускал с постороннего сервера, дабы не палить свой ип. Итого, за ночь было вскрыто порядка 50 аккаунтов. Но, к сожалению, большая половина аккаунтов были либо пусты, либо с персонажами маленького уровня. Зато остальная малая часть... Скажу лишь, что суммарный урон, нанесённый геймерам, составил чуть больше 1ккк игровых денег (шмотом) или порядка 400$ ,если переводить в реальные - хотя как сторгуешься. Но, честно говоря, он не "составил", а "составил бы". Я, на самом деле, абсолютно ничего не взял с этих аккаунтов, а нашёл немного иное приминение всему этому wink Об этом ниже. |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:08 | Сообщение # 10 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
Есть 3 подводных камня во взломе аккаунтов этим методом. Во-первых, если мы логинимся на сервер под взломанным аккаунтом, а владелец его юзает в данный момент, то у него на экране появляется надпись, что кто-то ломится :/ Именно поэтому брутфорсер я зарядил на ночь, а вообще это лучше делать утром. Но, по моему небольшому опыту, могу сказать, что, то ли юзеры не обращают внимание на эту надпись, то ли не знают английского, то ли вообще не умеют менять пароль, но у меня проблем с такими аккаунтами (на которых кто-то играл) не возникло. Имею в виду, никто не сменил пароль из тех, кто меня пропалил. Во-вторых, ник != логин. Моя программа брала ники игроков, которые играли на сервере, но отнюдь не их логины. Но это тоже не особо серьёзная проблема в случае такого "массового" взлома, так как даже если у человека с ником NICKNAME логин LOGINNAME, то обязательно найдётся кто-то с логином NICKNAME и перебор паролей к нику NICKNAME не пройдёт напрасно, хоть мы взломаем и не этого конкретного персонажа. В-третьих, если вы раздели того или иного персонажа, он может обратиться к администрации и есть вероятность, что ему всё вернут. Как это предотвратить? Я с этим не сталкивался, но, помыслив логически, могу предположить, что: Они всё вернут, если чел докажет, что его раздели. Вы же можете сказать в своё оправдание, что купили у него всё за реал - это же нигде не фиксируется - а чел захотел вас кинуть. Для большей убедительности, в момент "раздевания" переведите со своего кошелька на любой другой кругленькую сумму и сделайте скриншот. Но админы, в свою очередь ,могут посмотреть в логах и увидеть там тысячи попыток залогиниться, соответственно дайте аккаунту недельки две отстоятся после взлома, пусть логи об атаке канут в лету. Также админы могут обратить внимание на ип, с которого обычно заходит жертва и его несоответствие с тем, с которого он был раздет. Тут уж.. Можете найти того, кто юзает этого же провайдера, либо воспользоваться его услугами самостоятельно, либо сломать один из его боксов, либо пытаться обьяснить админам, что он просто так ловко вас подставил. Программ, которые реализуют описанный способ взлома Lineage2 аккаунтов, в интернете я не видел... Именно поэтому решил написать и продавать свою - la2brute.5bb.ru. Нужно признать, что с началом повального её использования, аккаунты ломать стало всё сложнее и сложнее. Если я, после того как её написал (где-то в феврале 2006-го), на Российских популярных серверах мог сломать по 30-50 аккаунтов за ночь, то сейчас эта цифра в 4-5 раз меньше. И последнее, хочется отметить, что единственный сервер, который сделал-таки защиту от перебора, был la2.abyss.ru. Хотя на самом деле, ещё на antaras.ru ввели защиту - блокирование аккаунта на 5 минут после 40-ка ошибочных попыток залогиниться. Но при том массовом переборе, о котором я писал выше, эта защита практически бесполезна. 2. Удалённое определение версии lineage2 сервера Помните я говорил, что последние 8 байт в пакетах логин-сервера отводятся под чексумму? Точнее, из них предпоследние 4 :> А если вдруг оставить пакет без чексуммы, офф версия lineage сервера нас просто- напросто дисконнектит. В l2j функция, которая проверяет чексумму возвращает true или false, но почему-то возвращаемое значение не проверяется. То есть, фактически l2j не проверяет чексумму. Соответственно, если дисконнект, то офф, если нет, то l2j. 3. Удалённое "подвешивание" login-сервера Было замечено, что некоторые серверы на пакеты, не содержащие логина/пароля отвечают пакетом типа 0x03 (который означает, что вы успешно авторизованы). После чего начинают вести себя крайне нестабильно. Я проверил это на 10-ти крупных С3 серверах, половина никак не отвечала на такой пакет, другая отвечала пакетом 0x01 (авторизация не прошла), но только www.la2.ru посылал 0x03 и на время прекращал принимать входящие соединения (видимо, у них установлена система "авто-подъёма"). Для реализации программы, которая бы подвешивала la2.ru, вам нужно всего-лишь смешать выше-предоставленный генератор пакетов с простым tcp-клиентом. Бесконечный цикл посыла подобных пакетов приведёт к невозможности зайти на игровой сервер. |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:08 | Сообщение # 11 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
4. Клонирование Уязвимость о которой сейчас пойдёт речь имела место быть в С1 версии ЛА2, поэтому особо заострять внимание на ней не буду. Суть заключалась в том, что мы, авторизовавшись на login-сервере 1 раз под одним аккаунтом, могли заходить на game-сервер под этим же аккаунтом параллельно неограниченное число раз. Соответственно, можно было входить в игру под одним и тем же персонажем сколько угодно. Вторая возможность клонирования была описана в параграфе про IID и OID. Клонирование предметов через WH, питомцев и тд рассматривать не буду, мне не кажется эта тема интересной, т.к. на нормальных серверах это уже давно не работает. 5. Создание "мутантов" и смешение скиллов Очень интересная тема. Первым кто реализовал программно эти идеи (в рунете) был hint. Для начала, на сколько вам известно, в lineage существует несколько расс. За каждой из них закреплены свои классы (маг и войн). Но класс одной рассы естесственно отличается от аналогичного класса другой рассы (скиллами). А у рассы гномов нет класса магов вообще. Это было необходимое предисловие, чтобы понять смысл всего нижеописанного. А теперь рассмотрим запрос на создание персонажа: 0B // тип пакета 45 00 6D 00 30 00 30 00 00 00 // ник перса 04 00 00 00 // расса 00 00 00 00 // пол 35 00 00 00 // начальная профессия (класс) 14 00 00 00 // 6 постоянных значений, я затрудняюсь сказать, что они значат (INT, WIT, STR, DEX, CON, MEN © CyberBlade) 27 00 00 00 // 2D 00 00 00 // 1B 00 00 00 // 1D 00 00 00 // 0A 00 00 00 // 00 00 00 00 // тип волос 00 00 00 00 // цвет волос 00 00 00 00 // тип лица Этот пакет создаст Гнома война с ником "m00" мужского пола. Оказалось, что сервер (даже оффициальный) не проверяет соответствие рассы с выбраным классом. Это позволяет нам создавать чаров одной рассы с классом совершенно другой (я их называю мутантами =)). Звучит, конечно, интересно, но на самом деле мы имеем обычного чара со своими статами и скиллами, но с несвойственными ему текстурами. По идее баг кроме фана нам ничего дать не может (фана ввиде светлого эльфа спойлящего мобов :)), но оказалось, что из этого, на первый взгляд, неинтересного бага проистекают ещё два. Насколько вы знаете, у каждой рассы есть свои NPC у которых берутся квесты на профессию и учатся скиллы. Так вот, мутанты учат скиллы класса одной рассы у NPC другой рассы. К примеру, я, играя светлым эльфом, учил скилл гномов "Spoil" у NPC эльфов. И тут встал вопрос, а кто мне тогда будет давать профессию и какую? Дело в том, что скиллы даются в зависимости от профессии (в даном контексте "класса"), а вот квесты в зависимости от рассы. То есть, может получится такое, что по достижению 20-го уровня и будучи гномом-спойлером, вы сможете получить профессию "Elven Knight" (первая профессия светлых эльфов). Но эта информация не подтверждена на практике. Кстати говоря, считанное количество мутантов могут вообще учить скиллы. А вообще, если говорить о скиллах, то в ла2 есть ещё один баг. LA2 офф клиент не проверяет соответствие уровня чара и уровня доступного для изучения скилла. То есть, к примеру, будучи на 5-ом лвле human fighter'ом вы можете учить mortal blow максимального уровня (при условии, что хватит SP). Это легко реализуется на пакетном уровне. Ещё хочется добавить, что на l2j сервере какие-либо проверки вообще отсутствуют. То есть вы можете учить даже те скиллы, которые доступны только GM-ам. |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:10 | Сообщение # 12 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
6. Бессмертие. Вот мы и дошли до самой интересной темы, именуемой в простонародье - god mode. Согласитесь, на сервере, где онлайн больше 1000 человек, быть бессмертным - одно удовольствие =) Для начала, когда наступает бессмертие? На этот вопрос был дан банальный, но как оказалось точный ответ: когда чар уже мёртв. Казалось бы бред, но когда у персонажа 0 HP и он жив, его действительно невозможно убить (ну не савсем невозможно smile - об этом ниже). Но как сделать, чтобы у чара был абсолютный 0 HP, он был жив и при этом ещё HP не восстанавливались? Для начала рассмотрим вопрос с 0 HP. В la2 есть такой баг: если после смерти нажать на "return to the nearest village" и сразу же завершить процесс l2.exe, чар появится в городе с абсолютным 0 HP и даже с баффами (если они до этого были). Это свезано с тем, что после RequestRestartPoint-пакета клиент должен посылать пакет Apearing, после которого собственно сервер и восстанавливает чару HP и убирает баффы. А так как клиент мы закрываем, он этот пакет послать не успевает. Кстати, почему я всё время говорю "абсолютный" 0? Дело в том, что на сервере HP хранятся в переменной типа float (что самое интересное, клиенту пересылается оно в виде целого числа). То есть, если вы будете постепенно снижать HP до 0 с помощью bleed или poison, то вы не получите абсолютный 0, а если HP не ноль, значит вы живы. Поэтому единственный способ получить абсолютный 0 - это умереть. Вот, делать 0 HP мы научились, теперь поговорим о том, как заморозить их на нуле. 1) Первым шагом в этом направлении было создание гнома-мага (как было описано в предыдущем параграфе). Скорее всего, в следствие того, что у гномов нет такого класса как маг вообще, у него не регенерируются HP/MP. Соответственно, проделав с таким гномом выше-упомянутые действия, получим бессмертного персонажа. Этот баг пофиксили практически везде. 2) Второй способ был открыт несколько позднее гномов-магов. Оказалось, что при выборе несуществующей рассы, создаются бессмертные human'ы с любым классом. И самое интересное, что если таким способом создавать класс human mage, всё равно получится human fighter, но с магическими скиллами. У этих двух способов есть два очень весомых недостатка: a) созданные персонажи не могут учить скиллы и получать профессию. b) как вы понимаете, реген HP не работает вообще, соответственно вам придётся бегать бессмертным всё время. 3) А теперь, внимание, баг - который мне помог найти всё тот же hint. Насколько вы знаете, в линейке есть такая штука как перевес. Когда вы загружены на 65%+, у вас падает скорость бега, атаки и регенерации. Но мало кто знает, что если у вас 90%+, то помимо того, что вы не можете двигаться, у вас не регенерируется HP! Но что толку от того, что, появившись после смерти в городе, вы будете стоять на месте бессмертным? А тут нам поможет страйдер! Сев на него, вы сможете бегать с его скоростью при том, что HP всё равно не регенерируется! Но тут есть тоже маленький подводный камень - на некоторых серверах (reborn.ru - C4) нельзя атаковать будучи на страйдере. Тут уж ничего не поделаешь, могу посоветовать только пользоваться баффом blazing skin/freazing skin. 4) ну и последний баг с бессмертием - это demon's set. Это пожалуй самый старый баг на бессмертие и о нём в принципе все знают. Завязан он на том, что у вас получается отрицательные хп и вас соответственно опять же нельзя убить. |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:10 | Сообщение # 13 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
Все вышеописанные типы бессмертия объединяет один серьёзный недостаток. Персонаж перестаёт быть бессмертным как только у него каким-либо образом прибавится HP - в следствие lvlup'а или банального heal'а. Также он умирает от bleed, poison, некоторых вампиризмов. Ещё тут вспомнился баг с "fake death". На некоторых кривых явах после FD чары как бы так и остаются мёртвыми и их нельзя атаковать пока они не сделают рестарт. Ну это так, к слову. 7. 'remote DoS' и что это даёт Обычно уязвимости подобного рода особо не ценятся, так как более чем просто "поприкалываться" из них ничего получить нельзя. LA2 же постоянно сохраняет состояние мира (через каждые Н-секунд - этот вопрос ещё точно не изучен, да он и не так важен), чтобы после внезапного падения сделать откат. То есть, умея прогнозировать (или провоцировать) падение game-сервера, мы получаем "власть над откатами". Что это значит? А то, что, вас убили? Откат! Вас раздели? Откат!! У вас не получилось заточить шмотку? Откат!!! Кроме того, есть очень ценные монстры, которые имеют очень большое resp time (fairy queen timinel - респ 5 часов, например) и присутствуют в единичном экземпляре. Убили, повалили сервер, сервер поднялся, моб снова появился. В итоге время респа сокращается с 5 часов до 3-ёх минут. Как же перегружать сервер? Для l2j 100% рабочий способ - это кристализация. 72 // RequestCrystallizeItem 00 00 00 00 // OID предмета FF FF FF FF // количество Подставляем в этот пакет реальный OID предмета и отсылаем. На что сервер моментально падает. Для проджектов тут всё сложнее. При шифровании пакетов неправильным ключём, сервер иногда падает. ПОчему? Если ключи не совпадают, значит сервер при расшифровке получает совершенно рандомные значения (то есть ни то, что мы зашифровывали). И выследить как раз ту последовательность значений, при которой сервер падает, у меня пока что не получилось. |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:10 | Сообщение # 14 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
#include #include #include int main () { int O = 0, I = 0, Ot = 0, It = 0, total = 241, r = 0; srand(time(0)); for(int i = 0;i < total;i++) { r = rand()%2; printf("%i ",r); if® I++; else O++; if(!(i%60)) { printf("\n%i/%i\nВероятность успеха: %.2f\n",I,O,I/0.60); Ot+=O; It+=I; I = 0; O = 0; } } printf("Вероятность успеха в целом: %.2f\n",It/2.40); return 0; } Вот, что программа вывела на экран: ----------------------- 0 1 1 0 1 1 0 1 1 0 0 0 0 0 0 1 0 1 0 1 1 0 0 1 1 1 0 1 1 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 0 0 0 1 1 1 1 1 0 1 1 0 1 0 0 1 29/31 Вероятность успеха: 48.33 0 0 0 1 1 0 0 0 0 1 0 1 1 1 0 0 0 1 1 0 1 0 1 0 1 0 0 1 1 1 1 0 1 1 0 1 0 0 0 1 0 1 0 0 1 1 0 1 1 0 1 0 1 1 0 1 1 1 1 1 32/28 Вероятность успеха: 53.33 1 0 1 1 0 1 0 1 1 1 0 1 1 1 0 1 1 0 0 1 1 0 1 1 1 1 0 1 1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0 0 0 1 0 0 31/29 Вероятность успеха: 51.67 1 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0 1 0 1 1 0 1 0 1 0 0 0 1 0 1 1 0 0 1 0 0 1 0 1 1 1 27/33 Вероятность успеха: 45.00 Вероятность успеха в целом: 50.00 ----------------------- Как видите, тут прослеживаются те "типы рандома" о которых писал f4llen при том, что выпадение 0 и 1 равновероятно и никакой закономерности тут нет. Плюс ко всему при промежуточных измерениях вероятностей (для каждых 60-ти чисел), вероятность успеха несколько отклонялась от 50%, но общая всё равно была максимально близка к действительной вероятности выпадения 0 или 1. Таким образом, статистика f4llen'а ни что иное, как попытка систематизировать обычный рандом. Ну и последний камень в сторону тех, кто считает, что на вероятность заточки влияет даже погода за окном: В L2j нет своего генератора случайных чисел, в нём такой же библиотечный рандомайзер, что был использован выше. С той лишь разницей, что на вероятность заточки влияет одно единственное число, которое выставляется администрацией. Будте уверены, в lineage2 off то же самое. В итоге, хочу сказать, что не стоит пытаться обмануть rand(), скорее он обманет вас =) Стоит искать баги в самом процессе точки, но опять же, как было продемонстрировано выше, это слишком простой процесс, чтобы быть бажным. А вообще, "случайностей не бывает, а бывают только неизвестные нам закономерности" © Кто-то. 10. Геодата (хождение сквозь стены). Сегодня постучался человек в асю и начал спорить, что l2j ничем не отличается от оффа. В связи с этим я решил добавить в статью пару слов про геодату в l2j и off. Процесс передвижения по миру в la2 реализован довольно интересно. Оказывается, за тем, куда идти следит и сервер и клиент параллельно. Точнее, вы кликаете в ту точку, куда хотите попасть, клиент в соответствии с имеющейся у него геодатой смотрит можно ли туда пройти, если да, то посылает запрос на сервер. Тот уже в соответствии со своей геодатой разрешает или возвращает вас в исходное положение. Этим как раз и объясняется феномен под названием "нивидимые стены", который, кстати, присущь нашим фришардным проджектам с кривыми локациями. В l2j же нет геодаты, она прикручевается к нему дополнительно. Что это значит? А то, что за передвижением чара следит только клиент по имеющейся у него геодате. Поэтому, воспользовавшись ботом (в котором понятное дело также нет геодаты), вы можете ходить сквозь стены, потому что ни сервер, ни клиент (в лице бота) просто не знают про них. Эта проблема кстати не только l2j. На С1ОФФ как правило С3/C4 локации также без геодаты, то есть там точно также ответственность за передвижение возлагается только на клиента. Если разбирать передвижение более подробно, то оно реализуется пакетом "0x01 MoveBackwardToLocation". В нём присутствует два набора координат - где стоим и куда хотим попасть. После этого пакета сервер начинает нас шаг за шагом двигать в желаемую нами точку. Причём, с каждым шагом он не посылает нам новые координаты! Для того, чтобы клиенту узнать в какой точке в данный момент он находится, посылается пакет "0x48 ValidatePosition". То есть, в целом, мы посылаем пакет с координатами куда хотим попасть, а потом просто периодически проверяем, грубо говоря, на сколько мы продвинулись. Но это так, для общего развития, так сказать =) |
|
| |
ARMIA |
Дата: Пятница, 19.09.2008, 16:11 | Сообщение # 15 |
Vip
Группа: Проверенные
Сообщений: 394
Репутация : 39
Статус: Offline |
11. Прикол с SocialAction (0x1b) Что такое SocialAction, думаю, объяснять не надо. Оказалось, что помимо смеха, приветствия, победы и тд, анимация при LVL UP'е является таким же SocialAction'ом. А, насколько вам известно, запрос на произведение SocialAction отправляет клиент, то есть мы сами можем в любой момент сделать себе lvlup =) Только анимацию, разумеется. Вот формат SocialAction-пакета: 1b // Тип пакета (SocialAction) 0f 00 00 00 // номер action'а (0f - lvlup) 12. Баг c Ride (0x6a) Запрос "Ride" посылает клиент, когда хочет забраться на страйдера или виверена. Формат: 6a // тип пакета 00 00 00 00 // 0/1 слезть/залезть 00 00 00 00 // номер питомца: 1 - страйдер, 2 вивирен Когда у вас вызван страйдер и вы посылаете запрос "Ride", на самом деле, страйдер исчезает (то есть выходит из игры и теряет свой OID - этим как раз объясняется то, что когда вы с него слезаете, он пропадает), а садитесь вы уже не конкретно на своего страйдера, а на некий эталон страйдеров smile Немного некорректно выразился, ну да ладно. Оказалось, что на некоторых ла2-серверах отсутствует проверка на то, а вызывали ли вы вообще страйдера, перед тем как на него сесть. То есть ни с того, ни с сего, послав пакет: 6a 01 00 00 00 01 00 00 00 Вы сядете на страйдера, хоть и не вызывали его. Причём, даже если у вас нет дудки. Таким же образом можно садится и на виверен. Этот баг, также как и прикол с SocialAction был найден человеком под ником Maddaemon. Гратз ему. 13. Выкидываем из игры чаров Этот баг я открыл случайно, изучая всё тех же мутантов. Меня мучал вопрос, почему когда при создании чара указываешь несуществующую рассу (число больше 4-ёх), всегда создаётся чар с текстурами human'а? Причём, этот human не может учить скиллы у NPC human'ов, то есть ничего кроме текстур его с людьми не объединяло. Так вот, оказалось, что в виде human'а таких чаров воспринимает _только_ С1/C3 клиенты. С4 же для таких чаров текстуры просто не находит и вылетает с ошибкой. То есть, как только в зону видимости la2 C4 клиента попадает такой чар, он падает. Под зоной видимости я подразумеваю не то, что вы видите на экране, а приблизительно зону видимости команды "/target". Так, например, поставив такого персонажа рядом с замком на время осады, у нападающих не будет шанса, т.к. ботами захватывать замок крайне проблематично, а клиентом зайти в игру они просто не смогут. Я испытал это на трёх крупных отечественных С4 серверах (не l2j), везде работало. Такими чарами, кстати, можно проверять персонажей на ботов ) Если не упал, значит бот. Но это способ для ГМов-садистов имхо. |
|
| |