В продолжении темы опкодов, немного о клиентских пакетах.
(примеры не с актуальной вресии, адреса отличаются)
Вопрос обхода фемиды, приведения исходника в божеский вид и обработку RTTI оставим в стороне.
Имеется - список vtable для всех пакетов. Требуется вытащить ID.
Выбираем понравившийся клиентский пакет.
Код:
396D3A54 0003 struct X2::CAEnterWorldPacket: struct X2::ClientToAuthPacket, struct INetPacket; [SI]
Переходим к его vtable.
Код:
.rdata:396D3A50 ; struct X2::CAEnterWorldPacket: struct X2::ClientToAuthPacket, struct INetPacket; [SI] O: 0, A: 0 (Class Informer)
.rdata:396D3A50 dd offset const X2::CAEnterWorldPacket::`RTTI Complete Object Locator'
.rdata:396D3A54 const X2::CAEnterWorldPacket::`vftable' dd offset sub_39381D60
.rdata:396D3A54 ; DATA XREF: sub_39365B30+A8o
.rdata:396D3A54 ; sub_39366010+312o
.rdata:396D3A58 dd offset sub_390196E0
.rdata:396D3A5C dd offset sub_39366B80
К слову о методах. Первый возвращает класс пакета (я табличку выше постил).
Второй пишет в поток тип пакета, метод один и тот же для всех пакетов (запомните это, упомяну ещё раз).
Третий пишет все остальные данные пакета.
На данный момент это не интересно.
Интересны 2 ссылки на vtable. Очевидно, что одна из них (а в нашем случае, так вообще обе) указывают сюда из конструктора.
Код:
.text:39365BB4 mov ds:dword_15CC4[esi], ecx
.text:39365BBA mov ds:word_15D08[esi], 0
.text:39365BC3 mov ds:dword_15D18[esi], ecx
.text:39365BC9 mov ds:dword_15D1C[esi], ecx
.text:39365BCF mov [esi+7Bh], bl
.text:39365BD2 mov edx, ds:dword_39EB6770
;Следующие 2 строчки как раз конструктор
.text:39365BD8 mov [ebp+var_20], offset const X2::CAEnterWorldPacket::`vftable'
.text:39365BDF mov [ebp+var_1C], 0Bh
;Ка видим, он очень капитально заинлайнился
.text:39365BE6 mov ecx, [edx+1Ch]
.text:39365BE9 mov eax, [ecx]
.text:39365BEB mov edx, [eax+60h]
.text:39365BEE xorpd xmm0, xmm0
.text:39365BF2 push offset aTest_world_que ; "test_world_queue"
.text:39365BF7 movlpd [ebp+var_8], xmm0
.text:39365BFC call edx
.text:39365BFE mov edx, [eax]
.text:39365C00 mov ecx, eax
.text:39365C02 mov eax, [edx+8]
.text:39365C05 call eax
Пакет создаётся на стеке и сразу уходит в обработку. Я тут кучу лишнего кода привёл, а интересна нам всего лишь цифра 0x0B в конструкторе, которая и является опкодом этого пакета.
И вот что у нас выходит - конструктор инлайнится и он не в 100% случаев такой тривиальный. Запись опкода может идти сразу, а может через пару инструкций. К слову серверные пакеты конструируются так же, но потом складываются в очень удобную табличку, откуда достаются в один проход скрипта (А то как складываются, заслуживает отдельной статьи на тему "почему разработчикам надо вовремя отрывать руки?").
Желающие могут руками протыкать все пакеты и составить список, ну или придумать что повеселее. У меня скрипт для сборки клиентских пакетов не получился.
Есть ещё вариантик, может кому покажется более простым.
Помните второй метод? Который тип пакета пишет.
Код:
.text:390196E0 sub_390196E0 proc near ; DATA XREF: .rdata:3968F718o
.text:390196E0 ; .rdata:3968F968o
.text:390196E0 ; .rdata:3968F978o ...
.text:390196E0
.text:390196E0 var_4 = dword ptr -4
.text:390196E0 arg_0 = dword ptr 8
.text:390196E0
.text:390196E0 push ebp
.text:390196E1 mov ebp, esp
.text:390196E3 push ecx
.text:390196E4 push esi
.text:390196E5 mov esi, ecx
.text:390196E7 mov ecx, [ebp+arg_0]
.text:390196EA mov eax, [ecx]
.text:390196EC mov edx, [eax+1Ch]
.text:390196EF call edx
.text:390196F1 mov ecx, [ebp+arg_0]
.text:390196F4 push 0
.text:390196F6 test al, al
.text:390196F8 jnz short loc_39019718
.text:390196FA movzx eax, word ptr [esi+4]
.text:390196FE mov [ebp+var_4], eax
.text:39019701 mov edx, [ecx]
.text:39019703 mov edx, [edx+40h]
.text:39019706 lea eax, [ebp+var_4]
.text:39019709 push eax ; Наш опкод.
.text:3901970A push offset aType_3 ; "type"
.text:3901970F call edx
.text:39019711 pop esi
.text:39019712 mov esp, ebp
.text:39019714 pop ebp
.text:39019715 retn 4
.text:39019718 ; ---------------------------------------------------------------------------
.text:39019718
.text:39019718 loc_39019718: ; CODE XREF: sub_390196E0+18j
.text:39019718 mov eax, [ecx]
.text:3901971A mov eax, [eax+40h]
.text:3901971D lea edx, [ebp+var_4]
.text:39019720 push edx
.text:39019721 push offset aType_3 ; "type"
.text:39019726 call eax
.text:39019728 movzx ecx, word ptr [ebp+var_4]
.text:3901972C mov [esi+4], ecx
.text:3901972F pop esi
.text:39019730 mov esp, ebp
.text:39019732 pop ebp
.text:39019733 retn 4
.text:39019733 sub_390196E0 endp
Через этот метод проходят все пакеты. Кто владеет отладчиком лучше чем дизассемблером, могут попытать своё счастье здесь. Это виртуальный метод пакета. На входе в метод в ecx лежит пакет(если я ничего не перепутал, но даже если перепутал - посмотрите, он где-то рядом), первое его поле это указатель на vtable. Опкод отмечен комментарием.