20120529
20120528
[Видеоурок] И что же, всё-таки, делать с указателями?
[Ссылочка].
Смотрим ещё раз, как ищутся указатели, подробно разбираем код из [статьи].
PS: Совсем забыл! Чтобы узнать именно адрес значения (например, чтобы затем записать туда что-нибудь) - просто остановитесь на предпоследнем шаге - не читайте значение адреса, прочитайте последний уровень указателя - результатом будет адрес значения, куда можно писать, используя уже готовые процедуры.
Смотрим ещё раз, как ищутся указатели, подробно разбираем код из [статьи].
PS: Совсем забыл! Чтобы узнать именно адрес значения (например, чтобы затем записать туда что-нибудь) - просто остановитесь на предпоследнем шаге - не читайте значение адреса, прочитайте последний уровень указателя - результатом будет адрес значения, куда можно писать, используя уже готовые процедуры.
20120525
Про рисование.
Сижу, разбираюсь с графикой. Ну, вы знаете - тема будущих уроков, всякие там wallhack и прочие радости.
Очень сложный материал, особенно для подачи, мне бы самому разобраться как следует. С чего начать - пока думаю, скорее всего, покодим немного самостоятельно - сначала порисуем под Windows при помощи GDI\GDI+ (почитать про это можно [тут]), затем будем осваивать [DirectX] и [OpenGL].
Если очень вкратце, то GDI (и его расширение, GDI+) - это интерфейс (набор функций, но если хочется подробностей - [пожалуйста]) для работы с двухмерной (плоской) графикой в винде. Грубо говоря всё, что вы видите на мониторе, рисуется при помощи функций этого интерфейса - окна, кнопки, буквы и так далее. Если почитать подробности в MSDN, можно найти примеры рисования линий, точек, геометрических фигур, работу с кистями и много чего интересного.
Одна проблема - работает эта штука довольно медленно, что не устраивает производителей игр, для которых придумали DirectX - набор интерфейсов для отрисовки графики, работы со звуком и прочими вещами, связанными с играми и OpenGL - ещё одну (полностью открытую) библиотеку для рисования графики. Фишка этих двоих в том, что они рисуют быстро - на порядки быстрее, чем GDI\GDI+, так что все более-менее требовательные к железу игры используют эти технологии.
Их-то нам и предстоит ковырять (или смотреть, как их ковыряю я, попивая чаёк с бутерами), но для ковыряния нужна какая-никакая подготовка.
Для начала, почитайте вот про [эту] функцию. Теперь смотрим на код:
Значит, два цветных крестика - как раз те самые (10;10) и (30;30), красный и синий, соответственно. Представили, да? Важно тут запомнить, что начало отсчёта (ноль) - верхний левый угол, а не нижний левый, как на геометрии.
После того, как прямоугольник (а в нашем случае - квадрат, но никто не мешает задать другие координаты) нарисовался, мы красноречиво сообщаем, чтохватит это терпеть рисование закончено - вызываем [EndPaint], сообщая ей всё тот же хэндл окна и контекст устройства.
Воот, как-то так. На целую лекцию тянет! Уф. В общем, пока я разбираюсь дальше и привожу в порядок кашу в голове (т.к. сам изучаю эту тему практически с нуля), попрактикуйтесь - найдите в MSDN другие функции для рисования, почитайте про них, посмотрите примеры, попробуйте порисовать сами. Удачи, это ведь так интересно!
Очень сложный материал, особенно для подачи, мне бы самому разобраться как следует. С чего начать - пока думаю, скорее всего, покодим немного самостоятельно - сначала порисуем под Windows при помощи GDI\GDI+ (почитать про это можно [тут]), затем будем осваивать [DirectX] и [OpenGL].
Если очень вкратце, то GDI (и его расширение, GDI+) - это интерфейс (набор функций, но если хочется подробностей - [пожалуйста]) для работы с двухмерной (плоской) графикой в винде. Грубо говоря всё, что вы видите на мониторе, рисуется при помощи функций этого интерфейса - окна, кнопки, буквы и так далее. Если почитать подробности в MSDN, можно найти примеры рисования линий, точек, геометрических фигур, работу с кистями и много чего интересного.
Одна проблема - работает эта штука довольно медленно, что не устраивает производителей игр, для которых придумали DirectX - набор интерфейсов для отрисовки графики, работы со звуком и прочими вещами, связанными с играми и OpenGL - ещё одну (полностью открытую) библиотеку для рисования графики. Фишка этих двоих в том, что они рисуют быстро - на порядки быстрее, чем GDI\GDI+, так что все более-менее требовательные к железу игры используют эти технологии.
Их-то нам и предстоит ковырять (или смотреть, как их ковыряю я, попивая чаёк с бутерами), но для ковыряния нужна какая-никакая подготовка.
Для начала, почитайте вот про [эту] функцию. Теперь смотрим на код:
format PE GUI 4.0
entry start
include 'win32ax.inc'
section '.data' data readable writable
ps PAINTSTRUCT ?
hDC dd ?
section '.text' code readable executable
start:
invoke GetModuleHandle,0
invoke DialogBoxParam,eax,37,HWND_DESKTOP,DialogProc,0
or eax,eax
jz exit
exit:
invoke ExitProcess,0
proc DialogProc hwnddlg,msg,wparam,lparam
push ebx esi edi
cmp [msg],WM_INITDIALOG
je .wminitdialog
cmp [msg],WM_COMMAND
je .wmcommand
cmp [msg],WM_CLOSE
je .wmclose
cmp [msg],WM_PAINT
je .wmpaint
cmp [msg],WM_LBUTTONDOWN
je .move
cmp [msg],WM_RBUTTONUP
je .wmclose
xor eax,eax
jmp .finish
.move:
invoke SendMessage,[hwnddlg],WM_NCLBUTTONDOWN,2,0
jmp .processed
.wmpaint:
invoke BeginPaint,[hwnddlg],ps
mov [hDC],eax
invoke Rectangle,[hDC],10,10,30,30
invoke EndPaint,[hwnddlg],ps
jmp .processed
.wminitdialog:
jmp .processed
.wmcommand:
jmp .processed
.wmclose:
invoke EndDialog,[hwnddlg],0
.processed:
mov eax,1
.finish:
pop edi esi ebx
ret
endp
section '.idata' import data readable writeable
library kernel,'KERNEL32.DLL',\
user,'USER32.DLL',\
gdi,'GDI32.DLL'
import kernel,\
GetModuleHandle,'GetModuleHandleA',\
ExitProcess,'ExitProcess';,\
import user,\
DialogBoxParam,'DialogBoxParamA',\
SendMessage,'SendMessageA',\
EndDialog,'EndDialog',\
BeginPaint,'BeginPaint',\
EndPaint,'EndPaint'
import gdi,\
Rectangle,'Rectangle'
section '.rsrc' resource data readable
directory RT_DIALOG,dialogs
resource dialogs,\
37,LANG_ENGLISH+SUBLANG_DEFAULT,demonstration
dialog demonstration,'Create message box',70,70,190,175,WS_POPUP
enddialog
В процедуре работы диалогового окна (DialogProc) у нас появился обработчик нового события - [WM_PAINT]. Это крутое событие вызывается всякий раз, когда окно хочет, чтобы его нарисовали. Тем самым GDI, да-да. Следовательно, если у нас есть обработчик этого события - обязательно надо там что-нибудь нарисовать (в голову лезут неприличные слова и забор)!
Что нам для этого нужно? Для начала, сообщить винде, что мы собрались рисовать. Та самая функция, про которую я предложил почитать чуть выше (BeginPaint), этим и занимается. Для работы ей нужно сообщить хэндл нашего окна и адрес специальной структуры (PAINTSTRUCT), которая хранит всю нужную информацию - размеры окна и т.д., но в принципе она нам не интересна - мы просто её объявили в секции данных и забыли.
Гораздо более интересен нам ответ, который приходит в регистр EAX после выполнения функции. Ответ этот - хэндл на штуковину под названием контекст устройства ([device context]), по сути - структура, описывающая выбранную область рисования, выбранную кисть, её цвет и прочие параметры.
Так, штука важная - сохраняем в отдельной переменной hDC, она нам ещё понадобится. А для чего? Смотрим на следующую строчку и видим вызов функции [Rectangle], которая, как не трудно догадаться из её названия, рисует прямоугольник. Что ей нужно сообщить в аргументах? А всего ничего - контекст устройства (который у нас уже есть) и координаты верхнего правого и нижнего левого угла. Про координаты сделаю небольшую картинку, даже парочку.
Вот как координаты считаются в обычном мире человеков:
Значит, две оси (монитор у нас, как известно, плоский) - абсцисс и ординат, X и Y. Нижний левый угол - ноль. Точка, которую я мастерски нарисовал, имеет координаты (10;10). Всё понятно, правда? На геометрии в школе было то же самое, бррр!
А теперь - как дела обстоят в мире компьютеров:
Всё наоборот, начало координат - верхний левый угол! Предлагаю в верхний правый угол монитора прикрепить бумажку цветную. В общем, привыкнуть придётся. Теперь вспоминаем нашу функцию, рисующую прямоугольник:
invoke Rectangle,[hDC],10,10,30,30Координаты верхнего левого угла - (10;10), нижнего правого - (30;30). Вот картинка работающей программы (крестики я нарисовал):
Значит, два цветных крестика - как раз те самые (10;10) и (30;30), красный и синий, соответственно. Представили, да? Важно тут запомнить, что начало отсчёта (ноль) - верхний левый угол, а не нижний левый, как на геометрии.
После того, как прямоугольник (а в нашем случае - квадрат, но никто не мешает задать другие координаты) нарисовался, мы красноречиво сообщаем, что
Воот, как-то так. На целую лекцию тянет! Уф. В общем, пока я разбираюсь дальше и привожу в порядок кашу в голове (т.к. сам изучаю эту тему практически с нуля), попрактикуйтесь - найдите в MSDN другие функции для рисования, почитайте про них, посмотрите примеры, попробуйте порисовать сами. Удачи, это ведь так интересно!
20120524
Ну очень важно.
Внимание, вопрос!
Про что мне всё-таки записать третью часть видеоурока по трейнерам? Что ещё научимся делать?
Про что мне всё-таки записать третью часть видеоурока по трейнерам? Что ещё научимся делать?
Пилим дальше трейнер на C# - учимся работать с указателями.
Ребята, я написал немного кода, но он такой небольшой, что на видеоурок явно не тянет - ну не знаю я, о чём там рассказывать вслух, поэтому напишу здесь.
Задача у нас такая - есть указатель вида 0x12345+0x1+0x5+0x7, надо суметь его прочитать. Что такое указатель - все помнят? Смотрите:
0x12345 - по этому адресу будет лежать другой адрес (это ведь указатель!). Допустим, 0xA.
Прибавляем к результату первое смещение, получаем 0xA+0x1. Читаем получившийся адрес:
[0xA+0x1] = второй адрес, скажем, 0xB
[0xB+0x2 (второе смещение)] = 0xC.
...
...
[0xD+0x7] = 123 - нужное нам значение, на которое указатель и указывает. Вот код:
Тут у нас указатель такой - 0x55D804 + 0x70 = Значение, причём это float. Читаем значение базового адреса, конвертируем из массива байт в цифры, прибавляем смещение, читаем получившийся адрес, конвертируем во float - вуаля! Всё просто. Но код можно улучшить, если у нас много смещений. Смотрите:
В принципе, всё довольно просто, если не понимаете - почитайте что-нибудь про циклы, там всё понятно. Вызывать эту функцию нужно вот так:
Задача у нас такая - есть указатель вида 0x12345+0x1+0x5+0x7, надо суметь его прочитать. Что такое указатель - все помнят? Смотрите:
0x12345 - по этому адресу будет лежать другой адрес (это ведь указатель!). Допустим, 0xA.
Прибавляем к результату первое смещение, получаем 0xA+0x1. Читаем получившийся адрес:
[0xA+0x1] = второй адрес, скажем, 0xB
[0xB+0x2 (второе смещение)] = 0xC.
...
...
[0xD+0x7] = 123 - нужное нам значение, на которое указатель и указывает. Вот код:
public int ReadBytes()
{
if (pID != 0) //Проверяем, что игра найдена
{
var dwAddress = 0x55D804; //Базовый адрес указателя
byte[] buffer = new byte[4]; //Буфер, массив из четырёх байт, куда будут читаться значения
int bytesread; //Переменная-заглушка, хранящая количество прочитанных байт
var handle = OpenProcess(0x001F0FFF, false, pID); //Получаем хэндл процесса игры
ReadProcessMemory(handle, (IntPtr)dwAddress, buffer, 4, out bytesread); //Читаем значение базового адреса
var result = BitConverter.ToInt32(buffer, 0); //Конвертируем массив байт в циферки
result += 0x70; //Прибавляем первое смещение
ReadProcessMemory(handle, (IntPtr)result, buffer, 4, out bytesread); //Читаем получившийся адрес
var temp = BitConverter.ToSingle(buffer, 0); //Конвертируем результат во float
CloseHandle(handle); //Закрываем хэндл игры
return temp; //Возвращаем результат
}
return -1; //Если не нашли игру - возвращаем -1.
}
Тут у нас указатель такой - 0x55D804 + 0x70 = Значение, причём это float. Читаем значение базового адреса, конвертируем из массива байт в цифры, прибавляем смещение, читаем получившийся адрес, конвертируем во float - вуаля! Всё просто. Но код можно улучшить, если у нас много смещений. Смотрите:
//В аргументах присылаем базовый адрес указателя + массив смещений
public int ReadBytes(int baseAddress, byte[] offsets)
{
if (pID != 0 && baseAddress != 0 && offsets.Length != 0) //Проверяем, что всё на месте
{
byte[] buffer = new byte[4]; //Буфер для чтения
int bytesread; //Заглушка
var handle = OpenProcess(0x001F0FFF, false, pID); //Получаем хэндл
ReadProcessMemory(handle, (IntPtr)baseAddress, buffer, 4, out bytesread); //Читаем базовый адрес
for (var i = 0; i < offsets.Length; i++) //Бежим в цикле, пока не кончатся смещения
{
baseAddress = BitConverter.ToInt32(buffer, 0); //Конвертируем результат в циферки
baseAddress += offsets[i]; //Прибавляем смещение
ReadProcessMemory(handle, (IntPtr)baseAddress, buffer, 4, out bytesread); //Читаем
}
//Как только смещения в массиве закончились
CloseHandle(handle); //Закрываем хэндл
var result = BitConverter.ToSingle(buffer, 0); //Конвертируем результат во float
return result; //Возвращаем результат
}
return -1; //Иначе - ошибка
}
В принципе, всё довольно просто, если не понимаете - почитайте что-нибудь про циклы, там всё понятно. Вызывать эту функцию нужно вот так:
var address = 0x55D804; //Базовый адрес
var offsets = new byte[] {0x70}; //Массив со смещениями
var myFloat = ReadBytes(address, offsets); //Читаем!
[Видеоурок] Ломаем Split Second!
[Ссылка] на урок. Заранее извиняюсь за небольшое отставание звука (не критичное) - какие-то проблемы с видеоредактором.
В уроке демонстрируется поиск и взлом неизвестного значения (экранной полоски). С нуля, совсем. Из инструментов - голый [Cheat Engine]. Начинаем с поиска значения, заканчиваем уже готовым скриптом (или трейнером, если вы рукастые), попутно стараюсь комментировать свои действия, т.к. уроки на эту тему уже были.
Следующий урок - не за горами!
В уроке демонстрируется поиск и взлом неизвестного значения (экранной полоски). С нуля, совсем. Из инструментов - голый [Cheat Engine]. Начинаем с поиска значения, заканчиваем уже готовым скриптом (или трейнером, если вы рукастые), попутно стараюсь комментировать свои действия, т.к. уроки на эту тему уже были.
Следующий урок - не за горами!
Подписаться на:
Сообщения (Atom)