Прошу вашей помощи.
Задача такая – есть клиент игры. Он посылает серверу пакеты. Нужно написать программу, которая от имени клиента будет слать пакеты серверу. Именно так работает сниффер WPE PRO.
Разумеется, перед тем как написать на форум, я погуглил возможные решения. Вот они:
1. TCPSend http://autoit-script.ru/autoit3_docs/functions/TCPSend.htm - т.е. устанавливаем новое соединение, и начинаем общение с сервером. Фактически придется писать новый клиент. Не пойдет. А если достать указатель на сокет? Увы, как сказали в этой теме: http://autoit-script.ru/index.php?topic=14216.0 «Дескриптор сокета валиден только для процесса, в котором его получили. Поэтому придется инжектить код в целевой процесс игры чтобы работать в контексте ее процесса.» Если это так, то этот вариант не пойдет.
2. Воспользоваться библиотекой Winpcap. Поставить на прослушку сеть и фильтровать пакеты. Но это не то, мне нужно отсылать пакеты, а не перехватывать…
3. Инжект библиотеки Ws2_32.dll. Хороший пример тут: http://www.autoitscript.com/forum/topic/136339-hooking-functions-with-autoit/
4. Инжект библиотеки Kernel32.dll. Тему нашел тут: http://www.cheatsbrasil.org/local/autoit/22274-babyloves-funcoes-para-wyd-intermediario.html
Самыми перспективными мне показались инжекты.
Проанализировав код 4-ого варианта, пришел к выводу, что возможно там привязка к какой-то конкретной игре. Во всяком случае, когда я запустил этот скрипт и попробовал отослать свой пакет, клиент вылетел (а при отсылке через WPE PRO все работает). Если кого заинтересует, могу привести листинг своего скрипта.
Третий вариант не зарубил игры, и даже что-то распечатал в консоли. Допустим, что действительно перехвачен пакет от игры (хотя меня берут сомнения – что-то слишком часто клиент отправляет пакеты, WPE PRO показывает, что они идут реже). Именно перехвачен, а не просто прочитан, как это было с Winpcap. Т.е. теоритически я могу подменить содержимое. Замечательная возможность, но она сейчас не требуется. Нужно отправить новый пакет от имени игры. Вопрос – как это сделать, основываясь на инжекте? Просто вызвать функцию хука? Или? Короче, привожу листинг:
Консоль показывает:
Первый аргумент – это soket id.
Второй – отсылаемый пакет (числовое значение)
Третий – размер пакета (мое предположение)
Четвертый – флаг MSG_OOB
Gesendet wird – это шестнадцатеричное представление пакета.
Если я правильно понимаю, то iParam – это параметры, которые передает клиент игры при вызове метода send. Как их формировать? Я даже посмотреть не могу, что там – сразу выкидывает, как только начинаю совершать действия над этой переменной.
В общем нужен пример вызова send через этот хук. Желательно преобразовать пакет из строки, как в WPE PRO (пример пакета в строковом виде: 'AB AC CB E5 50 5A BD B9 0C 00 00 00 00 00 00 00', размер пакета – 16)
Дополнение:
Обнаружил, что клиент вылетает независимо от того, работаю я с iParam или нет. По всей видимости дело в том, что при завершении скрипта надо деинсталлировать хук. Добавил
И вылеты клиента прекратились. Само значение iParam – это какое-то число (например, 278986220), которое меняется при перезаходе в игру, но постоянно в рамках одной сессии. Следовательно, к отсылке пакета iParam не имеет никакого значения.
Попробовал вызвать myHookFunc($param) и принудительно изменить память длл, поставив туда записанные значения:
Консоль показала, что данные добавились со смешением… Т.е.
Вернуло не 335807180 как я ожидал…
Задача такая – есть клиент игры. Он посылает серверу пакеты. Нужно написать программу, которая от имени клиента будет слать пакеты серверу. Именно так работает сниффер WPE PRO.
Разумеется, перед тем как написать на форум, я погуглил возможные решения. Вот они:
1. TCPSend http://autoit-script.ru/autoit3_docs/functions/TCPSend.htm - т.е. устанавливаем новое соединение, и начинаем общение с сервером. Фактически придется писать новый клиент. Не пойдет. А если достать указатель на сокет? Увы, как сказали в этой теме: http://autoit-script.ru/index.php?topic=14216.0 «Дескриптор сокета валиден только для процесса, в котором его получили. Поэтому придется инжектить код в целевой процесс игры чтобы работать в контексте ее процесса.» Если это так, то этот вариант не пойдет.
2. Воспользоваться библиотекой Winpcap. Поставить на прослушку сеть и фильтровать пакеты. Но это не то, мне нужно отсылать пакеты, а не перехватывать…
3. Инжект библиотеки Ws2_32.dll. Хороший пример тут: http://www.autoitscript.com/forum/topic/136339-hooking-functions-with-autoit/
4. Инжект библиотеки Kernel32.dll. Тему нашел тут: http://www.cheatsbrasil.org/local/autoit/22274-babyloves-funcoes-para-wyd-intermediario.html
Самыми перспективными мне показались инжекты.
Проанализировав код 4-ого варианта, пришел к выводу, что возможно там привязка к какой-то конкретной игре. Во всяком случае, когда я запустил этот скрипт и попробовал отослать свой пакет, клиент вылетел (а при отсылке через WPE PRO все работает). Если кого заинтересует, могу привести листинг своего скрипта.
Третий вариант не зарубил игры, и даже что-то распечатал в консоли. Допустим, что действительно перехвачен пакет от игры (хотя меня берут сомнения – что-то слишком часто клиент отправляет пакеты, WPE PRO показывает, что они идут реже). Именно перехвачен, а не просто прочитан, как это было с Winpcap. Т.е. теоритически я могу подменить содержимое. Замечательная возможность, но она сейчас не требуется. Нужно отправить новый пакет от имени игры. Вопрос – как это сделать, основываясь на инжекте? Просто вызвать функцию хука? Или? Короче, привожу листинг:
Код:
#include "Hooking.au3"
;===================>Global Variables
Global $hHook, $hProc
Global $pString[2] = [0, 0] ;the first element holds the address and the second the length, so its easier to call the _DelString() Function
Global $sProcessName = "Client.exe" ;our target process
;===========>
SetPrivilege("SeDebugPrivilege", 1) ;too trivial
$lpMsgBoxA = _WinAPI_GetProcAddress(_WinAPI_GetModuleHandle("Ws2_32.dll"), "send") ;we are reading the address of MessageBoxA in the RAM
$callback = DllCallbackRegister("myHookFunc", "none", "dword") ;we are registering the callback function
If @error Then
MsgBox(16, "ERROR", "Couldn't initialize Callback")
Exit
EndIf
$ptr = DllCallbackGetPtr($callback)
_VirtualProtect(Number($ptr), 94) ;we have to unprotect the Callbackfunction
$hProc = _OpenProcess($sProcessName) ;we have to open the process
$hHook = _SetHook(number($lpMsgBoxA), 5, Number($ptr), "int;int;int;int", $hProc) ;we are going to hook the MessageBoxA-Function
Do
Sleep(1000)
until NOT ProcessExists($sProcessName) ;waiting
Func myHookFunc($iParam) ;=>our HookFunction
If $pString[0] <> 0 Then _DelString($pString[0], $pString[1], $hProc) ;free the old string
_GetParameter($iParam, $hHook, $hProc) ;get the parameter from the stack
ConsoleWrite("================NEW PAKET WILL BE SENDED==========" & @crlf)
For $i = 2 To 5
ConsoleWrite($i & ". Argument is " & Number(DllStructgetdata($hHook[5], $i)) & @crlf)
next
;==============>String auslesen
$myString = Hex(DllStructgetdata($hHook[5], 3))
Consolewrite("Gesendet wird: " & $myString &@crlf)
;===================>
_SetParameter($iParam, $hHook, $hProc) ;and write it ;)
return ;works much better with return
EndFunc
Консоль показывает:
Код:
================NEW PAKET WILL BE SENDED==========
2. Argument is 1192
3. Argument is 154761420
4. Argument is 28
5. Argument is 0
Gesendet wird: 00000000093978CC
Второй – отсылаемый пакет (числовое значение)
Третий – размер пакета (мое предположение)
Четвертый – флаг MSG_OOB
Gesendet wird – это шестнадцатеричное представление пакета.
Если я правильно понимаю, то iParam – это параметры, которые передает клиент игры при вызове метода send. Как их формировать? Я даже посмотреть не могу, что там – сразу выкидывает, как только начинаю совершать действия над этой переменной.
В общем нужен пример вызова send через этот хук. Желательно преобразовать пакет из строки, как в WPE PRO (пример пакета в строковом виде: 'AB AC CB E5 50 5A BD B9 0C 00 00 00 00 00 00 00', размер пакета – 16)
Дополнение:
Обнаружил, что клиент вылетает независимо от того, работаю я с iParam или нет. По всей видимости дело в том, что при завершении скрипта надо деинсталлировать хук. Добавил
Код:
_UninstallHook($hHook, $hProc)
И вылеты клиента прекратились. Само значение iParam – это какое-то число (например, 278986220), которое меняется при перезаходе в игру, но постоянно в рамках одной сессии. Следовательно, к отсылке пакета iParam не имеет никакого значения.
Попробовал вызвать myHookFunc($param) и принудительно изменить память длл, поставив туда записанные значения:
Код:
DllStructSetData($hHook[5], 3, 335807180) ; добавляем свое значение пакета
DllStructSetData($hHook[5], 4, 16) ; меняем размер пакета на свой
Консоль показала, что данные добавились со смешением… Т.е.
Код:
DllStructgetdata($hHook[5], 3)
Вернуло не 335807180 как я ожидал…
- после деинсталляции хука сомнения исчезли – пакеты идут с нормальной частотой. Кстати, насчет уборки мусора за собой – наверное надо вызвать перед выходом _FreeOpenProcessHandle ($hProcess, $lpHandle)? Но не знаю, откуда брать $lpHandle. Прикладываю файл Hooking.au3 может кто-нибудь подскажет как правильно вызвать функцию в моем примере. Подозреваю, что _FreeOpenProcessHandle ($hProcess, $lpMsgBoxA) но боюсь ошибиться.«хотя меня берут сомнения – что-то слишком часто клиент отправляет пакеты, WPE PRO показывает, что они идут реже»