Доброе время суток дамы и господа!
В данной статье я решил описать процесс создания трейнера на языке Visual Basic. Что побудило меня на это? Да просто достало однообразие трейнеров, созданных в Detective Story, Magic Trainer Creator и т.п., хотелось чего то своего, чтобы все нужное находилось на своих местах. Немного погуляв по сети, я нашел пример на chemax.ru, но он оказался устаревшим и нерабочим. Попыхтев пару часов над кодом, я все таки нашел и исправил ошибки, и получился таки вполне работоспособный вариант :14: Приступим к написанию..
Откроем Visual Basic и создадим стандартный проект. Кликнем два раз по нашей форме и объявим нужные нам функции:
PHP код:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAcess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAdress As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddess As Any, ByVal lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWriten As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Описание каждой уже есть в статье на www.chemax.ru, но вкратце о каждой:
FindWindow - возвращает дескриптор окна по заголовку или классу окна (в нашем случае по заголовку)
GetWindowThreadProcessId - возращает идентификатор процесса, с помощью которого создано окно
OpenProcess - получает доступ к процессу
WriteProcessMemory - записывает данные в память процесса
ReadProcessMemory - читает данные из памяти процесса
CloseHandle - закрывает доступ к процессу. Ну это как я понимаю
Также объявим константу:
PHP код:
Private Const Process_All_Access As Long = &H1F0FFF
Она пригодится нам для получения полного доступа к процессу.
Т.к. данные записываются в память процесса в шестнадцатиричном виде, то добавим еще пару-тройку полезных функций в код:
PHP код:
Private Function GetByte(Txt As String, num As Integer) As Byte
GetByte = Asc(Mid$(Txt, num, 1))
End Function
Private Function Hex2Str(ByVal data As String) As String
Dim i As Integer
If Len(data) \ 2 = Int((Len(data) - 1) \ 2) Then data = 0 & data
For i = 1 To Len(data) Step 2
Hex2Str = Chr(Val("&H" + Mid$(data, i, 2))) & Hex2Str
Next i
End Function
Private Function Str2Hex(ByVal Txt As String) As String
Dim i As Integer
Dim buff As String
For i = 1 To Len(Txt)
buff = Hex(GetByte(Txt, i))
If Len(buff) = 1 Then buff = "0" & buff
Str2Hex = buff & Str2Hex
Next i
End Function
GetByte - извлекает нужный нам байт из строки
Hex2Str - переводит шестнадцатеричный код в текст
Str2Hex - наоборот текст в шестнадцатитеричный код
Это то, чего так не доставало в проекте трейнера на chemax'е, и в память записывалось не знамо что. Далее я добавил еще две фунции для удобства, чтобы не писать код каждый раз, а просто вызывать их с нужными параметрами. Первая:
PHP код:
Private Function WriteMemory(WindowName As String, Adress As Long, Value As Long)
Dim hWnd As Long, pid As Long, pHandle As Long ' объявляем переменные
hWnd = FindWindow(vbNullString, WindowName) 'ищем наше окно и передаем ее hWnd переменной
If (hWnd = 0) Then 'если окно не найдено выходим из функции, предварительно выдав ошибку
MsgBox "Окно не найдено! Вероятно, программа не запущена", 32
Exit Function
End If
GetWindowThreadProcessId hWnd, pid 'ищем идентификатор процесса
pHandle = OpenProcess(Process_All_Access, False, pid) 'открываем полный доступ к памяти
WriteProcessMemory pHandle, Adress, Hex2Str(Hex(Value)), 4, 0& 'запись в память
CloseHandle hProcess 'закрываем доступ
End Function
Функция записывает данные (Value) в заданный адрес (Adress), и ищет процесс по заголовку окна (WindowName). Следует учесть, что адрес в памяти ищется в шестнадцатеричном виде, и поэтому при вызове перед адресом нужно дописать &H. Выглядеть это будет вот так:
PHP код:
WriteMemory "Crusader", &HDF5AE0, 1000000
Вторая - функция чтения данных из памяти:
PHP код:
Private Function ReadMemory(WindowName As String, Adress As Long)
Dim hWnd As Long, pid As Long, pHandle As Long, str As String * 4 ' объявляем переменные
hWnd = FindWindow(vbNullString, WindowName) 'ищем наше окно и передаем ее hWnd переменной
If (hWnd = 0) Then Exit Function 'если окно не найдено выходим из функции
GetWindowThreadProcessId hWnd, pid 'ищем идентификатор процесса
pHandle = OpenProcess(Process_All_Access, False, pid) 'открываем полный доступ к памяти
ReadProcessMemory pHandle, Adress, str, 4, 0& 'читаем память и записываем в переменную
ReadMemory = Val("&H" + Str2Hex(str)) 'преобразуем данные к нормальному виду
If Val(ReadMemory) < 0 Then ReadMemory = 65536 + Val(ReadMemory) 'если число меньше нуля
CloseHandle hProcess 'закрываем доступ
End Function
Функция считывает данные из адреса Adress процесса с заголовком окна WindowName. Выглядеть это будет вот так:
PHP код:
a = ReadMemory("Crusader", &HDF5AE0)
Ну теперь осталось только добавить текстовые поля и пару кнопок и вот он - готовый трейнер!