20120630

Котята, начнём потихоньку, DirectX всё-таки!
Вот что нам понадобится:

-Microsoft Visual C++ 2010 Express - [тык].
-DirectX SDK - [тык] (на момент написания сего набора букв - версия от июня 2010).
-Чай\Кофе\Бутерброды.

Итак! Берём и безжалостно устанавливаем вижуал студию. Как только установили - точно так же устанавливаем SDK (Software Development Kit - Набор Инструментов Разработки).
Если при попытке установить последний получаем ошибку S1023 - делаем следующее:

1. Win+R - cmd - Enter.
2. MsiExec.exe /passive /X{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5} - Enter.
3. MsiExec.exe /passive /X{1D8E6291-B0D5-35EC-8441-6616F567A0F7} - Enter.
4. Пробуем ещё раз установить sdk. Должно получиться.
5. Как установили - идём [сюда] и устанавливаем x86 (а если у вас 64-битная винда - то и x86 и x64).

После этого делаем финт ушами - запускаем студию, создаём новый проект, вводим ему имя, говорим, что это будет Win32 Project, жмём OK и дальше везде Next, ничего не трогая. Получаем вот такую тему (которая уже даже запускается):


Что эта чёрная магия умеет делать? По сути - корректно запускаться и корректно закрываться - можно поелозить её по экрану, порастягивать и даже потыкать по менюшкам. Но это - нифига не DirectX! Как так? Вдыхаем поглубже и копируем вместо старого вот этот код:

#include
#include
#include
#include
#pragma comment (lib, "d3d9.lib")

LPDIRECT3D9 d3d;
LPDIRECT3DDEVICE9 d3ddev;

void initD3D(HWND hWnd);
void render_frame(void);
void cleanD3D(void);

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    HWND hWnd;
    WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(WNDCLASSEX));
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = L"WindowClass";
    RegisterClassEx(&wc);
    hWnd = CreateWindowEx(NULL, L"WindowClass", L"Test Direct3D Program", WS_OVERLAPPEDWINDOW, 300, 300, 800, 600, NULL, NULL, hInstance, NULL);
    ShowWindow(hWnd, nCmdShow);
    initD3D(hWnd);
    MSG msg;
    while(TRUE) {
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        if(msg.message == WM_QUIT) break;
        render_frame();
    }
    cleanD3D();
    return msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch(message) {
        case WM_DESTROY: {
                PostQuitMessage(0);
                return 0;
            } 
    }
    return DefWindowProc (hWnd, message, wParam, lParam);
}

void initD3D(HWND hWnd) {
    d3d = Direct3DCreate9(D3D_SDK_VERSION);
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = hWnd;
    d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
}

void render_frame(void) {
    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
    d3ddev->BeginScene();    
    d3ddev->EndScene();
    d3ddev->Present(NULL, NULL, NULL, NULL);
}

void cleanD3D(void) {
    d3ddev->Release();
    d3d->Release();
}

Ничего не понимаем, пробуем запустить. Если до этого всё установили, получаем нечто такое:


Крутая штука заключается в том, что окно теперь синенькое, но не просто синенькое - синеньким его делает уже DirectX!

На созерцании подобного чуда пока остановимся, в следующей статье подробно разберём весь код. Кстати, весь проект целиком можно скачать у меня на сайте - [keng.gamehacklab.ru], раздел Releases.





У меня появилось ещё немного свободного времени, так что я продолжаю усиленно разбираться на тему графики и всего, что с ней связано.

По факту, мы с вами уже научились делать трейнеры. Я так обнадёживающе говорю, что изначально от трейнера требуется всего одна функция - запись в память. Собственно, весь смысл на этом построен - нам нужна возможность изменять память игры.

Но за этими словами кроется довольно громоздкая надстройка в виде горячих клавиш, таймеров, окошек, сканеров сигнатур и прочего сахара, сделанного исключительно из расчёта на удобство использования для конечного пользователя. Как бы, нам-то с вами известно, что надо всего-то по адресу 0x12345 поменять mov eax,ebx на nop,  но вот людям, качающим и использующим трейнеры абсолютно до лампочки - им надо, чтобы нажал кнопку - стал бессмертным.

В давние-давние времена читы и трейнеры встраивались прямо в исполняемый файл игры. Затем это были специальные загрузчики, которые загружались сами, а затем загружали уже игру. Потом начали клепать отдельные файлы трейнеров с горячими клавишами, кнопками и прочими органами управления.

А что может быть круче? Может!

Как мы знаем, почти 90% информации в наши черепушки поступает посредством глаз - т.е. посредством того, что мы видим. Пользователь может взять и не запомнить комбинации клавиш для всех 30-ти опций нашего трейнера, а ведь опций может быть и 50, и 150.

Вот и пошли гениальные умы чуточку дальше - догадались, что можно ведь прямо во время игры (на экране) рисовать меню, отображающее все опции и позволяющее их включать и выключать.

Собственно, с созданием таких меню я и разбираюсь, просто у меня не так много свободного времени, поэтому разбираюсь от случая к случаю. Но обязательно доразбираюсь и выложу всё в виде уроков.

Вот.

Мы уже немного освоили графику под винду с использованием ассемблера (покрутите блог вниз - там была статья с картинками и рисованием прямоугольничка), следующий шаг - DirectX, но писать мы будем уже на C++, потому что на C# это всё будет довольно криво выглядеть. Не пугайтесь, если не знаете плюсов - нам понадобится исключительно общая концепция работы, а синтаксис там и без этого очень похожий.

20120613

[Видеоурок] Знакомимся с отладчиком OllyDbg.

[Ссылочка] на урок, тыкаем и смотрим\слушаем\хихикаем\комментим.

Пытаюсь на своей глючной и сырой сборке восьмого виндовса продемонстрировать отладку и поиск сигнатуры на примере многострадальной Crimsonland, сломав в ней патроны. Адрес ищем при помощи Cheat Engine, всё остальное делаем в Olly. Скачать отладчик и необходимый для создания сигнатур плагин можно у меня на [сайте].

20120605

Ещё чуток по поводу программирования напишу. Что-то из этого я в блоге уже писал, что-то - не писал, но повторение - это, как известно, зашибись, поэтому пусть будет. Итак!

Вы совершенно ни хрена не понимаете в чёрной магии, но очень хотите научиться. Кто согласен - читаем дальше.

Для взлома игр нам ну вот кровь из носа, но нужен ассемблер, хотя бы на уровне чтения\понимания кода. Для этого я горячо рекомендую:

1. [Рассылку Калашникова] - объясняет с самых основ, просто, понятно, со вкусом и юмором.
2. [Дневники чайника] - длинный, но интересный дневник о том, как один парень изучил ассемблер с нуля. Отладчиком он там пользуется довольно древним - вы можете использовать любой другой, например [OllyDbg].

Если же вы в принципе не представляете, как всё это происходит и в жизни не видели даже Бейсика - добро пожаловать [сюда] и [сюда]. Пусть и не ассемблер, но основы программирования поданы отлично. Предупреждаю! - необходимо знание английского хотя бы на уровне чтения, средненькое.

В принципе, используя СЕ, можно создавать трейнеры и без навыков программирования (помимо ассемблера, который нужен для самого взлома), но если очень приспичит и захочется разгуляться - придётся писать трейнеры самому.

Трейнеры (под Windows, конечно же) пишутся с использованием [WinAPI], прочитав статью, можно понять, что писать при этом можно на любом языке, лишь бы он умел с этими самыми винапи работать. Поэтому - C, C#, C++, Pascal - список можно долго продолжать.

Ребята, честно, просто посмотреть пяток видео научиться чему либо невозможно, если не пытаться это повторять. Это относится и к взлому игр, и к программированию, и к прыжкам на скакалочке. Поэтому пытаться надо, хотя бы по полчасика в день - тогда результат себя ждать не заставит.

Скоро будет видеоурок по созданию трейнеров с использованием самого СЕ, но там ограничены возможности, а программирование вручную ограничивает их только фантазией. :)
Дорогие читатели подали несколько идей для следующих видеоуроков и они уже на подходе! :)

20120528

[Видеоурок] И что же, всё-таки, делать с указателями?

[Ссылочка].

Смотрим ещё раз, как ищутся указатели, подробно разбираем код из [статьи].

PS: Совсем забыл! Чтобы узнать именно адрес значения (например, чтобы затем записать туда что-нибудь) - просто остановитесь на предпоследнем шаге - не читайте значение адреса, прочитайте последний уровень указателя - результатом будет адрес значения, куда можно писать, используя уже готовые процедуры.

20120525

Про рисование.

Сижу, разбираюсь с графикой. Ну, вы знаете - тема будущих уроков, всякие там wallhack и прочие радости.

Очень сложный материал, особенно для подачи, мне бы самому разобраться как следует. С чего начать - пока думаю, скорее всего, покодим немного самостоятельно - сначала порисуем под 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), красный и синий, соответственно. Представили, да? Важно тут запомнить, что начало отсчёта (ноль) - верхний левый угол, а не нижний левый, как на геометрии.

После того, как прямоугольник (а в нашем случае - квадрат, но никто не мешает задать другие координаты) нарисовался, мы красноречиво сообщаем, что хватит это терпеть рисование закончено - вызываем [EndPaint], сообщая ей всё тот же хэндл окна и контекст устройства.

Воот, как-то так. На целую лекцию тянет! Уф. В общем, пока я разбираюсь дальше и привожу в порядок кашу в голове (т.к. сам изучаю эту тему практически с нуля), попрактикуйтесь - найдите в MSDN другие функции для рисования, почитайте про них, посмотрите примеры, попробуйте порисовать сами. Удачи, это ведь так интересно!