PDA

Просмотр полной версии : [FASM] Хук DispatchNetworkQueue


ALF
17.04.2011, 14:50
И так всем привет!
Столкнулся с проблемой...
Если с сервер приходит пакет (например если на сервере сделать новый пакет, которого нету в клиенте по умолчанию) мы его анализируем и выполняем какой то код..
В общем что есть...
Структура NetworkPacket
по идеи так. (не знаю правильно или нет, так как до этого только рисованием в клиенте занимался)
struct NetworkPacket
union
id db ?
align_ dd ?
ends
cb dd ?
data db ?
ends
Так же по каком то примере от GoldFish на С++ был какой то хук
Я его попытался переделать в ФАСМ
proc DispatchNetworkQueueHook

push esp+04h
call [pDispNetwork]
test eax,eax
jz skip_
mov edx,[esp+4]
push eax
push edx
stdcall DrawPackets
pop eax
skip_:
ret 4
endp
Что делать дальше?
Этот хук надо сплайсить с
szDispNetwork db '?DispatchNetworkQueue@UNetworkHandler@@UAEHPAPAUN etworkPacket@@@Z',0
...
..
GetProcAddress([pEngine],szDispNetwork) ; pDispNetwork:=GetProcAddress(pEngine,szDispNetwork );
mov dword [pDispNetwork], eax

Подскажите пожалуста алгоритм что за чем, и если можете примеры....
Заранее спасибо

Aries
18.04.2011, 20:10
Честно, не вникал в код, что ты там пытаешься сделать, но самый простейший способ перехватить метод - заменить его адрес в таблице вызова(хотя если дела касаются руоффа, то это наверно самый палевный способ)

В кратце логика подмены в таблице имен такая:
1) находим адрес объекта "?AddNetworkQueue@UNetworkHandler@@UAEHPAUNetworkPa cket@@@Z"
2) находим адрес объекта "??_7UNetworkHandler@@6BUObject@@@"
3) начиная с адреса из пункта 2 организуем поиск ячейки со значением адреса (п.1)
4) затем заменяем там найденный адрес на адрес своей функции и радуемся жизни (и мб. ждем банан)))

ALF
19.04.2011, 00:36
Так это же тогда надо будет полностью писать функцию свою...
А как то же сплайсингом нельзя?
Просто в начале вызова ?AddNetworkQueue@UNetworkHandler@@UAEHPAUNetworkPa cket@@@Z
Поставить какой то call (E8) или же jmp (E9) на свою функцию а там Проверять какой id пакета.?

Вот я сделал отдельно функцию для сплайсинга
proc Splaising Adr,Hook
mov eax, [Adr]
mov ebx, eax
mov edx, [Hook]
add ebx, 05h
sub edx, ebx ; calc (hook - (orig + 5))
mov byte [eax], 0E8h ; call
mov dword [eax+1], edx ; rel32
ret
endp

Aries
19.04.2011, 01:24
Сплайсингом можно и даже лучше по сути)))
Про таблицу - просто проще (как мне кажется), если на начальном этапе)) Функцию свою надо будет писать ровно настолько, сколько тебе нужно выполнить в ней, а в конце уже вызывать реальную функцию AddNetworkQueue

ALF
19.04.2011, 01:53
То есть просто потом jmp [Original]?
А как тут получить параметр.. А именно айди пакета.

Morfik
19.04.2011, 03:31
То есть просто потом jmp [Original]?
А как тут получить параметр.. А именно айди пакета.

1) jmp на функцию, объявленную так же как и перехватываемая (у которой будет один параметр - указатель на пакет)
2) в своей функции надо сразу сохранить содержимое ecx
3) перед вызовом оригинала восстановить переписанные 5 байт (джамп) запихнуть с ecx то что оттуда сохраняли, и уже теперь вызывать оригинал
4) снова поставить хук (так как для вызова мы его снимали)

зы: тут нету волшебных 5 байт в начале ф-ии которые можено переписать без последствий

Aries
19.04.2011, 10:19
По поводу id пакета и т.п. дам тебе тот же совет, что когда-то дали мне, берешь пакетхак и там есть инишники с описанием большинства (мб и всех, хотя врядли) пакетов))


ЗЫ Сначала хотел сказать, что Морфик наркоман, потом выпил кофе проснулся, и понял что похоже на правду)))
ЗЫЫ Морфик, ты сейчас кстати полностью извне работаешь с клиентом или все-таки инжетишься и юзаешь экспортируемые функции без перехвата?

mira
19.04.2011, 11:17
Сплайс неочень хорошая идея так как востанавливать и перезаписывать функцию не лушее решение. Защита хукающая вмт тоже наивное решение. Дестр имхо твою защиту там перехукает быстрее чем ты это реализуеш) нада гдето из сокета брать пакет желательно юзая другую шифрацию недоводя даже до адднетворка и покрыть код фимой. Правда хз как такой пакет будет слать сервер и в каком виде у тя серверная часть защиты.

Morfik
19.04.2011, 20:26
По поводу id пакета и т.п. дам тебе тот же совет, что когда-то дали мне, берешь пакетхак и там есть инишники с описанием большинства (мб и всех, хотя врядли) пакетов))


ЗЫ Сначала хотел сказать, что Морфик наркоман, потом выпил кофе проснулся, и понял что похоже на правду)))
ЗЫЫ Морфик, ты сейчас кстати полностью извне работаешь с клиентом или все-таки инжетишься и юзаешь экспортируемые функции без перехвата?

полностью из вне работать никак не выйдет, если канешна не знаешь алгоритмов фроста =) ингжект и работа без перехватов - возможностей мало, но зато максимум безопасности

ALF
19.04.2011, 21:29
В общем суть такова
Сервер на клиент отправляет пакет
(айди допустим 0x99, структура cSSSSS)
в 5 строк.... Имена чаров)
Потом методами клиента рисуем эти ники (топ пвп которые в игре)
Ну рисовалку я уже знаю как сделать)
А вот с пакетиками (клиент часть) пока что туговато)

Добавлено через 1 час 1 минуту
P.S. А как именно определить, какой айди приходит?
Вот при вызове UNetworkHandler::DispatchNetworkQueue функции передается в аргумент пакет (DispatchNetworkQueue(np:NetworkPacket)
Структура NetworkPacket выглядит както так
struct NetworkPacket
union
id db ?
align_ dd ?
ends
cb dd ?
data db ?
ends
Зная __thiscall аргументы передаются по стеку.
Очевидно что можно оттуда достать и сам пакет и проанализировать его... Только вот как.....

Aries
19.04.2011, 23:45
полностью из вне работать никак не выйдет, если канешна не знаешь алгоритмов фроста =) ингжект и работа без перехватов - возможностей мало, но зато максимум безопасности

ок, спс)) А то я стал уже голову ломать, зачем тебе нужен был РидПроцессМемори) уж думал, что ты полностью извне с памятью линейки работаешь))

Добавлено через 22 минуты
В общем суть такова
Сервер на клиент отправляет пакет
(айди допустим 0x99, структура cSSSSS)
в 5 строк.... Имена чаров)
Потом методами клиента рисуем эти ники (топ пвп которые в игре)
Ну рисовалку я уже знаю как сделать)
А вот с пакетиками (клиент часть) пока что туговато)

Добавлено через 1 час 1 минуту
P.S. А как именно определить, какой айди приходит?
Вот при вызове UNetworkHandler::DispatchNetworkQueue функции передается в аргумент пакет (DispatchNetworkQueue(np:NetworkPacket)
Структура NetworkPacket выглядит както так
struct NetworkPacket
union
id db ?
align_ dd ?
ends
cb dd ?
data db ?
ends
Зная __thiscall аргументы передаются по стеку.
Очевидно что можно оттуда достать и сам пакет и проанализировать его... Только вот как.....
Ну структура пакета рабочая вот: (на АСМе хз как оно)
struct NetworkPacket
{
unsigned char id, _padding1, exid, _padding2;
unsigned short size, _padding3;
unsigned char* data;
};

Соответственно первый параметр и есть id пакета.
Теперь про то как это выдернуть...
Смотри, если ты vmt хукаешь (про что говорил я), тогда как раз эта структура и передается твоей функции (точнее указатель), поэтому ничего выдергивать не надо...
Если Сплайсом(как Морфик говорил), тогда дергаешь из стека адрес, и по этому адресу уже лежит структура...

ALF
20.04.2011, 00:04
pop eax сохранит стек в EAX?
Туплю что то я со стеком(
Закинуть в стек - вроде понятно всё)
А вытолкнуть со стека какой то 1 параметр... В то время когда их там огого)
Или там будет указатель на сам пакет?)

Aries
20.04.2011, 00:10
pop eax сохранит стек в EAX?
Туплю что то я со стеком(
Закинуть в стек - вроде понятно всё)
А вытолкнуть со стека какой то 1 параметр... В то время когда их там огого)
Или там будет указатель на сам пакет?)

указатель)

ALF
20.04.2011, 00:14
Хм... Сейчас попробую..
Сделаю переменную по типу структуры
Ну то есть
a: NetworkPacket
потом
pop eax
mov [a], eax
...
по идеи по
a.Id будет айди пакета...
Сейчас посмотрим)))

Aries
20.04.2011, 00:17
Я когда изучал, получал тупо адрес, и читал несколько байт после него и пытался понять что это)))

ALF
20.04.2011, 00:28
Ахахах
Ппц докатился)
Смотри сколько инклудов )))
include 'win32a.inc'
include 'encoding\win1251.inc'
include 'macro\if.inc'
include 'hll.inc'
include 'main.inc'
include 'Function.inc'
include 'Guard.inc'
include 'Structures.inc'
include 'NetWork.inc'

Добавлено через 4 минуты
Хз пойдут или нет... Еще не проверял но думаю делать так
proc DispatchNetworkQueueHook

pop eax
mov [pk],eax
push ebp
mov ebp, esp
pushad
; какието stdcall
popad
push 0ffffffffh
push eax
ret
endp
Причем на это будет не JMP а CALL

mira
20.04.2011, 10:15
Не будет это работать)
в pk у тебя будет адрес возврата из процедуры.
Нада чето типа того:
push ebp
mov ebp, esp
mov eax,[ebp+8]
pop ebp
mov pk, eax
где в [ebp+8] пропускаем в стеке адрес возврата 4 байта и еще 4 сохраненого нами ебп. Если вызываеш через call то придетса отступить еще на один адрес возврата [ebp+12]

Добавлено через 6 минут
И разумеетса после этих хуков ты обязан восстановить указатиль стека в соответствии с соглашениями вызова cdecl

Добавлено через 10 минут
Ах и да, если хукашеш диспатч то там еще и проверка нужна) она вызываетса в тике клиента около 100 раз в секунду в активном режиме и намного менше в неактивном, при этом в зависимости от плотности траффика от 99% до 10% она вызываетса вхолостую. Тоесть в ней пакета нет :) и нада проверять есть ли там пакет чтоб сразуже не словить генерал протекшн фолт

ALF
20.04.2011, 21:20
Кстати... Видел код для дампа пакетов...
push [esp+4]
call [OriginalDispatchNetworkQueuePtr]
test eax,eax
jz skip_
mov edx,[esp+4]
push eax
push [edx]
call NetworkPacketDump
pop eax
skip_:
ret 4
Может с него что то взять?
Я просто не совсем разобрался в нем(

mira
21.04.2011, 00:25
Кстати... Видел код для дампа пакетов...
push [esp+4]
call [OriginalDispatchNetworkQueuePtr] // вызываем оригинал
test eax,eax // проверяем не вернул ли вызов ноль
jz skip_ // вернул ноль - значит холостой вызов, ниче не делаем
mov edx,[esp+4] // чето типа суем указатель на пакет в ЕДХ
push eax // сохраняем ЕАХ
push [edx] // передаем указатель на пакет в функцию дампа
call NetworkPacketDump // вызываем функцию дампа
pop eax // восстанавливаем ЕАХ
skip_:
ret 4 // воостанавливаем стек исходя из соглашения cdecl
Может с него что то взять?
Я просто не совсем разобрался в нем(

незнаю откуда этот кусок но я его понимаю примерно так )

ALF
21.04.2011, 09:16
pop eax ; Выталкиваем со стека Адрес Возврата в EAX (4 байта)
push ebp ; Толкаем в стек Адрес , которого начинаются аргументы (глубина стека)
mov ebp, esp ; в ebp теперь "Вершина" стека. Туда будут идти аргументы
mov ebx,[ebp+4] ; тут 4 или 8? мы же вытолкали адрес возврата (4 байта)
pop ebp ; Выталкиваем то стека значения в регистр EBP.
mov NetPk, ebx ; в NetPk у нас будет указатель на пакет
pushad
; какието операции с пакетами типа stdcall
popad
push 0ffffffffh
push eax ; востанавливаем адрес возврата
ret
Проверьте)

Добавлено через 8 часов 34 минуты
Сейчас сделал вот так...
;================================================= ================================
proc DispatchNetworkQueueHook
pop eax ; Выталкиваем со стека Адрес Возврата в EAX (4 байта)
push ebp ; Толкаем в стек Адрес , которого начинаются аргументы (глубина стека)
mov ebp, esp ; в ebp теперь "Вершина" стека. Туда будут идти аргументы
pushad
mov ebx,dword[ebp+08h] ; тут 4 или 8? мы же вытолкали адрес возврата (4 байта)
test ebx,ebx
jz skip
mov [pNetPk], ebx ; в NetPk у нас будет указатель на пакет
skip:
popad
push 0ffffffffh
push eax ; востанавливаем адрес возврата
ret
endp


mov eax, dword[pNetPk]
movzx eax, [eax+NetworkPacket.id]
Всё работает, по идеи в EAX должен быть ID пакета. Но у меня там его Размер почему то...)
Структура у меня такая
struct NetworkPacket
id db ?
pad1 db ?
exid db ?
pad2 db ?
_size dd ?
pad3 dd ?
pdata dd ?
ends

mira
21.04.2011, 09:39
Movzx eax,[eax+пакет.id]
оо?

Добавлено через 8 минут
Movzx eax, [eax] это будет точно ид =)

mira
24.04.2011, 19:27
AddMetworkQueue(p : pNetworkPacket)
203C6090: 55 push ebp
203C6091: 8BEC mov ebp, esp
203C6093: 6AFF push FFFFFFFFh //какието константы (переменные)
203C6095: 68ACF84120push 2041F8ACh //какието константы (переменные)

//тут ставитса обработчик исключения типа try-except
203C609A: 64A100000000mov eax, fs:[00h]
203C60A0: 50 push eax
203C60A1: 64892500000000mov fs:[00000000h], esp

203C60A8: 83EC0C sub esp, 0000000Ch
203C60AB: 53 push ebx
203C60AC: 56 push esi
203C60AD: 57 push edi
203C60AE: 8965F0 mov [ebp-10h], esp
203C60B1: 8BF9 mov edi, ecx
203C60B3: C745FC00000000mov [ebp-04h], 00000000h
203C60BA: 8DB76C010000lea esi, [edi+0000016Ch]

//entercriticalsection
203C60C0: 56 push esi
203C60C1: 90 nop
203C60C2: E839AF535C call 7C901000h (ntdll.dll rtlentercriticalsection)

//какаято функция core возвращающая свободный индекс массива
203C60C7: 83C73C add edi, 0000003Ch
203C60CA: 6A04 push 00000004h
203C60CC: 6A01 push 00000001h
203C60CE: 8BCF mov ecx, edi
203C60D0: 90 nop
203C60D1: E84AB4C3F4call 15001520h

//ложим в массив пакет
203C60D6: 8BD8 mov ebx, eax
203C60D8: 8B07 mov eax, [edi]
203C60DA: 8B4D08 mov ecx, [ebp+08h]
203C60DD: 890C98 mov [eax+ebx*4], ecx

//LeaveCriticalSection
203C60E0: 56 push esi
203C60E1: E8FAAF535Ccall 7C9010E0h (ntdll.dll rtlLeaveCriticalSection)
203C60E6: 90 nop

//восстанавливаем обработчик исключений и спасаем регистры
203C60E7: 8BC3 mov eax, ebx
203C60E9: 8B4DF4 mov ecx, [ebp-0Ch]
203C60EC: 64890D00000000mov fs:[00000000h], ecx
203C60F3: 5F pop edi
203C60F4: 5E pop esi
203C60F5: 5B pop ebx
203C60F6: 8BE5 mov esp, ebp
203C60F8: 5D pop ebp
203C60F9: C20400 retn 0004h

никаму ничего странным тут не кажетса?)

ALF
25.04.2011, 00:41
хз...
Кстати
у нас же
DispatchNetworkQueue(struct NetworkPacket * *)
Звёздочка обозначает операцию взятия адреса. Т.к. звёздочки две, то в функцию передаётся указатель на указатель на структуру.
вызываю PaketDump вот так
stdcall PaketDump,[ebp+08h]
proc PaketDump uses ebx, ppnp:DWORD
mov ebx, [ppnp] ; NetworkPacket **
mov ebx, [eax] ; NetworkPacket *
movzx eax, [ebx+NetrowkPacket.id]
...
endp
Но в итоге у меня рисуется все равно адрес... Пробовал не только сплайсингом хукать.... Но и подменой адреса (ну то есть сначало вызывается моя, потом я вызываю оригинал)
Пробовал перед
movzx eax, [ebx+NetrowkPacket.id]
дописать
mov ebx, [ebx]
В итоге клиент критует...

mira
25.04.2011, 01:09
я тебе давал же пример как работает у меня..
нада вызывать вперед оригинал, и еще раз учите ассемблер)

supernewbie
25.04.2011, 02:19
//какаято функция core возвращающая свободный индекс массива
?Add@FArray@@QAEHHH@Z

mira
25.04.2011, 09:32
Ну ее название мне стало искать лень среди тонны экспортов коре. Достаточно что я понял ее смысл)

supernewbie
25.04.2011, 10:41
пусть фрост ставят на серв, хоть весело будет, а то сср ппц какой-то непродвинутый)

и не доказать ниче)

mira
25.04.2011, 11:25
Да не в этом дело
где бы инфу взять по хроникам памагите!

ALF
25.04.2011, 13:05
Рабочий код. Я добился чего хотел)
Спасибо всем за помощь.
;================================================= ================================
proc DispatchNetworkQueueHook
pop eax ; Выталкиваем со стека Адрес Возврата в EAX (4 байта)
push ebp ; Толкаем в стек Адрес , которого начинаются аргументы (глубина стека)
mov ebp, esp ; в ebp теперь "Вершина" стека. Туда будут идти аргументы
pushad
mov edx, [ebp+8]
.if edx > 0
stdcall PaketDump,[ebp+08h]
.endif
popad
push 0ffffffffh
push eax ; востанавливаем адрес возврата
ret
endp

;================================================= ================================
proc PaketDump uses ebx, ppnp:DWORD
mov eax, [ppnp] ; NetworkPacket **
mov ebx, [eax] ; NetworkPacket *
.if ebx > 0
movzx eax, [ebx+NetworkPacket.id]
stdcall IntToStr,eax,10,MAXHPBuff

.endif
ret
endp
;================================================= ================================

mira
25.04.2011, 13:17
И в чем был косяк?) вроде все тоже

ALF
25.04.2011, 13:22
Косяк был в том что проверять надо было 2 раза.
Так как там идет указатель на указатель.
Тик дает указатель, на указатель который нулл.
Я сделал проверку 1 и 2 указателя))
Сплайсингом кстати хукаю)

mira
25.04.2011, 14:13
Я же писал что нужна проверка еще в теме галухи вроде код.
Сплайсинг не есть хорошо) но работать будет если кроме тика другой поток это не вызовет. Если вдруг еще чтото захочет ее вызвать может кончитса плохо

supernewbie
25.04.2011, 15:54
как бэ там крит секции есть, можно хук после входа в них ставить

Добавлено через 45 минут
блин, как ж ты заставляешль его не рисовать не фризя весь поток полностью)

Добавлено через 36 минут
кажеца понял :)

mira
25.04.2011, 18:59
как бэ там крит секции есть, можно хук после входа в них ставить

Добавлено через 45 минут
блин, как ж ты заставляешль его не рисовать не фризя весь поток полностью)

Добавлено через 36 минут
кажеца понял :)

я не уверен что у альфа после них =)

ALF
26.04.2011, 00:12
У меня (судя с твоего сообщения).
Место
203C6090: 55 push ebp
203C6091: 8BEC mov ebp, esp
203C6093: 6AFF push FFFFFFFFh //какието константы (переменные)
Идет call на мою функцию.
В ней уже то что тут.
Вот скрины
оригинал
http://cs5643.vkontakte.ru/u23837494/131637796/y_c0056804.jpg
сплайсинг
http://cs5643.vkontakte.ru/u23837494/131637796/y_85957810.jpg

mira
26.04.2011, 08:57
Ну вот я и говорю что до секции :)