20140818

Дальнейшее развитие блога.


Комментарии - в студию!

20140803

D3D: Chameleon Wallhack

Привет, ребята! Для начала, вот видео:


А [вот] ссылка на репозиторий с исходным кодом.

Значит, скачали вы исходники, взяли любимый компилятор и любимую IDE, скомпилировали это дело и ничего не поняли. В видео я, отсылась к предыдущим статьям и урокам, рассказываю о том, что мы написали логгер, позволяющий нам узнать некоторую необходимую для нашей бурной деятельности информацию. А именно - stride, или номер куска экрана, который мы сейчас будем рисовать, и NumVertiles, аргумент функции [DrawIndexedPrimitive], который показывает нам количество вершин того куска, который мы будем рисовать. Мир игры состоит из моделек, модельки - из полигонов. Полигон - это треугольник, то есть у него три вершины. На модельки, собственно, сверху натянуты текстуры, чтобы было видно, что металл - это металл, оружие - это оружие, а враги - это враги. Нашли мы, значит, нужную нам текстуру. Дальше видим такой кусок кода:

pDev->SetRenderState(D3DRS_ZENABLE, false);
pDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
pDev->SetTexture(0, red);
oDrawIndexedPrimitive(pDev, PrimType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
pDev->SetRenderState(D3DRS_ZENABLE, true);
pDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
pDev->SetTexture(0, green);

Что мы тут делаем? А всё просто, как выяснилось. Функция [SetRenderState] позволяет нам задать параметры отображения того, что мы сейчас будем отображать. Тут важно помнить, что мы ещё пока ничего рисовать не пытались. У этой самой функции всего два аргумента - что мы меняем и на что мы меняем. Первым вызовом мы утверждаем, будто нужно выключить буфер глубины. Что это такое? Это перспектива, если вдруг так будет понятнее. Экран монитора - он плоский, а игра хочет казаться трёхмерной, так что ей нужно как-то трёхмерность симулировать. Вот эта вот штука отвечает за то, что мы видеть должны, а что - нет. Например, когда какой-то объект находится за стеной. Игра при отрисовке постоянно думает, что и как ей рисовать. Вот небольшая схемка:

0            1             2
             |                   
X -----------|-------------O
             | 

X - это мы. Палочки - это стена перед нами, а O - это нечто за этой стеной. Циферки обозначают позицию одного относительно другого в этом самом буфере глубины. У кого цифра 1 - того мы и видим, у кого больше - значит он чем-то от нас закрыт. Если товарищ О выйдет из-за стены, то у него Z-order (позиция в буфере глубины) станет равным 1, так что игра должна будет его перед нами отрисовать и в результате мы его увидим.

Если отключить буфер глубины, то игра решит, что все игровые объекты в поле нашего зрения находятся перед нами - то есть нету никаких препятствий и никто никого не перекрывает. Получится каша, потому что одновременно будут рисоваться стены, мебель, пол, потолок, оружие, гранаты, люди, враги, союзники, словом - всё. Для того, чтобы вычленить из этой каши то, что нам нужно, мы и использовали наш логгер. В общем-то, только у нужных нам объектов мы буфер глубины и отключили. Давайте вернёмся к коду, а то я заболтался. Отключив буфер глубины, мы говорим, что текущий объект мы будем рисовать сплошным цветом. Сразу после этого мы вызываем функцию [SetTexture], которая указывает, что мы будем использовать текстуру по имени red - красненькую. Напомню, что пока мы ещё ничего не рисовали и не пытались даже. Что мы делаем следующей строчкой? Верно, рисуем, вызвав оригинальную функцию рисования вместо нашей перехваченной.

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

Что получается в результате таких жутких махинаций? А получается так, что выбранная нами моделька рисуется через стены красным, а перед нами - зелёным. Эта фича отличает Chameleon wallhack от обычного. В обычном мы просто выключали бы буфер глубины и всё, а тут удобно, с подсветочкой.

Тэк-с. Я упоминал текстуры. Собственно, чуть ниже, в перехваченной функции [EndScene], мы их и создаём. Тут я в подробности вдаваться не буду, так как этот кусок кода я нашёл и честно скопировал себе, скажу только, что цвет мы задаём вот в этой строчке:

((PDWORD)d3dlr.pBits)[xy] = 0xFF00FF00;

Тут нас интересуют последние три пары чисел шестнадцатиричного значения. Догадливые уже поняли, что это RGB, он же - Red Green Blue, то есть три цветовых канала. Первые две цифры в том числе выше - это прозрачность, которая не используется в данном случае, как я понял. Собственно, FF0000 - это красный, 00FF00 - это зелёный, а 0000FF - это синий. Значения лежат в пределах от 00 до FF. Подходящий цвет можно выбрать в любом графическом редакторе или же в интернете найти.

В той же перехваченной EndScene мы первой строчкой узнаём ViewPort - это, собственно, то, куда мы смотрим, когда играем. Узнаём мы его затем, чтобы выводить туда текст, так что после создания текстур мы создаём шрифт и пишем им на экран, в данном случае - включён ли наш wallhack.

На этом, в принципе, можно бы было и остановиться, но есть ещё одна важная деталь. В комментариях некоторые люди жаловались, что игра вылетает с ошибкой при попытке сделать alt+tab или поменять разрешение экрана. Это чинится перехватом функции [Reset], в которой мы уничтожаем наши текстуры и шрифт, чтобы они не засоряли видеокарту и пересоздались, дабы игра снова могла их рисовать.

Вот теперь - всё. До новых встреч! (:

20140124

Про гитхаб.

Ребята, как вы заметили, я теперь в постах привожу ссылки на свой [репозиторий] на гитхабе. Я не знаю, как лучше организовать процесс, т.к. я там тоже что-то пишу и что-то может не работать или работать не так, как задумано, в тот или иной момент времени. Хранить 100500 папок\архивов с исходниками мне банально негде. Так что варианта два - тащим себе весь репозиторий и разбираемся, попутно глядя в блог и поставив себе 2013-студию, или же смотрим нужный кусок кода и копируем себе в проект. Сейчас это, по сути, песочница для экспериментов, так как я, как и вы, с темой знаком довольно поверхностно.

20140122

D3D: Рисуем прицел.

Привет!

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


Что-то объяснять, кроме комментариев в самом коде, я не буду - всё и без этого понятно. (:

Полный исходник - на [гитхабе]!

20140119

[Опрос] Перепись видеоуроков.

В комментах к этому посту я прошу вас указать те видеоуроки с [ютуба], которые хорошо бы переписать. Пока что я займусь приведением канала в порядок.

Новости по блогу.

Итак, уважаемые! Раз уж у меня нашлись время и силы возобновить публикации своих скромных потуг, то возникает пара вопросов:

Редизайн блога. Переписывание всех старых видео (одно из которых зачем-то удалил гадкий гугл), заливка видео на какой-нибудь другой хостинг или обменник (торренты!). Были мысли понаписать серию статей с красивыми картинками из какого-нибудь abode illustrator, потому что в виндовом пейнте рисовать как-то не слишком солидно. Так же были мысли создать три отдельных секции - Ассемблер, C\C++, C#.

Дело тут всё в том, что си ришотка (C#) достаточно фигово подходит для геймхакинга - он слишком высокоуровневый со всякими своими ООП и прочими классами, не даёт вменяемый доступ к WinAPI, потому что safe code и всё такое, но он красивый-быстрый-удобный для создания GUI, интерфейса, т.е.

Вообще, лично я придерживаюсь такого мнения, что ООП в целом плохо подходит для наших задач, поэтому предпочтение отдаю чистому Си и Ассемблеру. Почему? Потому что я их учил давно, когда компьютеры были медленные и оперативки было мало, так что я люблю компактность и скорость. Если моё с вашим мнение расходится - то извините, я верю что читатель достаточно умён чтобы взять мои исходники и переписать под свой язык. Нет, правда. Я изначально учу не код писать, а общим концепциям, алгоритмам и принципам.

Посему, на данный момент, мой инструментарий:

1. MSVS Express 2013. Потому что привык. Планирую перелезть на GCC.
2. Cheat Engine. Потому что удобно инжектить DLL-ки и в будущем понадобится для прочих исследований относительно взлома.
3. Olly Debugger. Использую в качестве основного отладчика, так же в силу привычки. Могу написать серию уроков по нему, но не вижу большого смысла - поменяются полторы кнопки на клавиатуре, да и уроков\статей по этому отладчику в сети есть куча.

Ещё один момент - игры на заказ мне ломать не очень хочется. Отчасти потому, что игра (чаще всего) стоит денег, а в основном потому, что это "повторение пройденного", но в другой обёртке. Прошу не обижаться, но это всё ещё не блог "кенг! сломай мне игру N!". Исключение - если попадётся какая-то нестандартная опция (это не повод с сего момента присылать мне по 9000 писем с предложениями).

Но всё ещё - feel free to присылать мне письма, любые. Общие рекомендации я дать могу, что-то подсказать или объяснить.

Вектор развития блога на данный момент:
Мы занялись D3D и графикой в целом. Мне не нравится текущий подход, используемый большинством - а именно конкретные адреса или указатели, поиски по сигнатурам и всё в том же духе. Я решил покопать поглубже и стремлюсь к автоматизации - как вы помните, нашему хуку нужны только смещения функций в табличке указателей интерфейса. Этот подход работает на DX 9, которая до сих пор используется крайне широко. В дальнейшем мы проапгрейдимся до поддержки DX 10 и 11, а затем и до OpenGL - это не так сложно. Так как наше приложение всё ещё очень хочет быть движком для трейнеров, добавим поддержку записи в память, codecave-ов, поиска сигнатур. Может, какой-то конструктор напишем, чтобы из файла брать адреса и названия функций и сразу пихать их в собранный exe. А, да, объединим загрузчик и хук в один исполняемый файл, чтобы не таскать их оба с собой.

Пока что - вот так.

D3D: Трагически наступившее "скоро".

Всем привет!

У меня нашлось время и я решил ещё немного поковыряться с D3D и прочими неприличными словами. (:

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

Это всё, конечно, круто, но не очень сильно впечатляет и далековато от наших амбиций. Итак, встречаем:


Вот эта самая функция нам и понадобится. Я, честно сказать, фигово разбираюсь в 3д-графике и рисовании в целом, так что гуру этой области прошу меня сильно не пинать - объяснять буду, как понял сам.

Как мы помним, читали или где-нибудь слышали, нельзя просто так взять и нарисовать оружие, машину или нечто такое. Видеокарточки туповаты и рисовать умеют только примитивы - точки, линии, треугольники. Захотели квадрат - сложили два треугольника вместе. Эти штуки ещё иногда зовут полигонами, ага. Дык вот эта самая функция используется для отрисовки примитивов, если очень кратко. Нас там будет интересовать параметр BaseVertexIndex, в суть которого я тоже вник крайне смутно и пытаться объяснить это кому-то пока что не стану - давайте просто звать эту штуку индексом. Ещё пара крутых штук ждёт нас чуть дальше, когда я код приведу. Так как у меня возникли некоторые трудности с перехватом этой функции, то перехватывать мы её будем не вручную, а при помощи библиотечки detours от microsoft (все необходимые файлы идут в комплекте с исходниками), так что код слегка видоизменился. Вот, например:



Тут сразу бросаются в глаза последние три строчки - это, собственно, и есть перехват. Делает библиотека всё то же самое - мы скармливаем ей адрес найденной фунции, которую нужно перехватить, в её начало дописывается переход (JMP 00112233) на перехваченную функцию, а перехваченная выставляет всё, как было, отрабатывает и возвращает хук на место. Едем дальше:



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

1. Каждый вызов у нас есть некие данные (Stride и BaseVertexIndex) , которые нам надо узнать и запомнить для использования уже в чите. Они характеризуют тот или иной объект на экране.
2. Каждый раз, когда игра пытается что-нибудь нарисовать, мы заносим структуру этих данных в массив.
3. В логгере есть кнопки, позволяющие управлять процессом - менять значения Stride и BaseVertexIndex, выбранные на данный момент будут подсвечиваться зелёным цветом.
4. Задача - натыкать такое значение, чтобы нужный нам объект(-ты) подсветился(-лись) зелёным. Запомнить цифры.

Скомпилируется всё это дело в DLL, которую надо будет заинжектить в процесс игры (я не парюсь и продолжаю делать это через Cheat Engine). Поддерживаются любые игры, которые рисуют при помощи D3D9.

ВНИМАНИЕ тем, кто запускает игры из Steam (как я, например): В стиме в свойствах игры надо отрубить steam overlay ui, так как он работает точно так же - иначе получим вылет.

ВНИМАНИЕ тем, кто до сих пор не использует MS Visual Studio 2013 (как я, например): Если вам лень ставить 13-ю студию, то просто слейте все исходники и создайте новый проект (DLL). Ему понадобится в свойствах указать путь до include и lib для MS DirectX SDK (полгига которого можно спокойно скачать в гугле), если заругается на отсутствие detours.lib - она лежт в папке проекта.

Результат:


А вот и [ссылка] на все исходники. На днях будем учить этих инопланетных парней просвечивать сквозь стены. (: