Раз немного передохнули, подытожим. Вспомним нашу программку на ассемблере, рисующую прямоугольник. Там это выглядело примерно так:
.wmpaint:
invoke BeginPaint,[hwnddlg],ps
mov [hDC],eax
invoke Rectangle,[hDC],10,10,30,30
invoke EndPaint,[hwnddlg],ps
jmp .processed
Значит, хочет наше окно себя нарисовать. В очередь сообщений прилетает WM_PAINT. Согласно [документации]:
Типа, раз такой праздник произошёл, значит окно хочет себя перерисовать. Перво-наперво ему же надо узнать, где рисовать, да? Вызываем [BeginPaint], сообщаем ему хэндл нашего окна и структуру, для чего-то там необходимую. Нам, в общем-то, до лампочки, для чего именно - она просто есть и всё.
В ответ на бегинпейнт (НачатьРисовать, лол) нам приходит хитрая штука под названием Handle to Device Context, если чуть более по-русски - это хэндл связки видеокарты с монитором. Типа, то место, где рисовать можно, ну то есть холст, потому как видеокарт и мониторов всяких - тьма тьмущая, вот и сделали такое клёвое обощение.
Значит, теперь у нас есть некоторая поверхность (монитор-то плоский!), где можно чего-нибудь эдакого накалякать. Берём и калякаем, вызывав Rectangle, рисующую прямоугольник.
После всего этого безобразия нам надо сообщить, что безобразие закончилось - вызываем EndPaint, ЗакончитьРисовать.
И на выход.
Вот, собственно, с Direct3D всё примерно точно так же обстоит - у нас есть указатель на устройство, очень похожий на hDC, т.е. то, где рисовать. Мы говорим:
BeginScene();
Мол, давай рисовать!
Рисуем...
И затем говорим:
EndScene();
Хватит это терпеть! Довольно!
Вот и во всех играх та же самая фигня происходит. Они делают себе место для рисования, каждый кадр говорят BeginScene(), рисуют всё, что им надо, а затем говорят EndScene() и показывают всё это на экране. Разработчикам не надо париться ни о модели видеокарты, ни о мониторе - просто РИСАТЬ и всё. Удобно!
Тут прискакиваем мы, все в белом и на соответствующем коне, толпы пищащих поклонниц сопровождают нас и кидаются в нас нижним бельём. Нам вдруг ВЗДУМАЛОСЬ игру обмануть и нарисовать в её королевстве что-то ещё. В чём логика:
BeginScene();
РисуемВсёИгровое();
EndScene();
Нам надо взять и нарисовать что-то своё после всего игрового. Удобнее всего это сделать прямо перед вызовом EndScene(), типа вот так:
.wmpaint:
invoke BeginPaint,[hwnddlg],ps
mov [hDC],eax
invoke Rectangle,[hDC],10,10,30,30
invoke EndPaint,[hwnddlg],ps
jmp .processed
The WM_PAINT message is sent when the system or another application makes a request to paint a portion of an application's window.
Типа, раз такой праздник произошёл, значит окно хочет себя перерисовать. Перво-наперво ему же надо узнать, где рисовать, да? Вызываем [BeginPaint], сообщаем ему хэндл нашего окна и структуру, для чего-то там необходимую. Нам, в общем-то, до лампочки, для чего именно - она просто есть и всё.
В ответ на бегинпейнт (НачатьРисовать, лол) нам приходит хитрая штука под названием Handle to Device Context, если чуть более по-русски - это хэндл связки видеокарты с монитором. Типа, то место, где рисовать можно, ну то есть холст, потому как видеокарт и мониторов всяких - тьма тьмущая, вот и сделали такое клёвое обощение.
Значит, теперь у нас есть некоторая поверхность (монитор-то плоский!), где можно чего-нибудь эдакого накалякать. Берём и калякаем, вызывав Rectangle, рисующую прямоугольник.
После всего этого безобразия нам надо сообщить, что безобразие закончилось - вызываем EndPaint, ЗакончитьРисовать.
И на выход.
Вот, собственно, с Direct3D всё примерно точно так же обстоит - у нас есть указатель на устройство, очень похожий на hDC, т.е. то, где рисовать. Мы говорим:
BeginScene();
Мол, давай рисовать!
Рисуем...
И затем говорим:
EndScene();
Хватит это терпеть! Довольно!
Вот и во всех играх та же самая фигня происходит. Они делают себе место для рисования, каждый кадр говорят BeginScene(), рисуют всё, что им надо, а затем говорят EndScene() и показывают всё это на экране. Разработчикам не надо париться ни о модели видеокарты, ни о мониторе - просто РИСАТЬ и всё. Удобно!
Тут прискакиваем мы, все в белом и на соответствующем коне, толпы пищащих поклонниц сопровождают нас и кидаются в нас нижним бельём. Нам вдруг ВЗДУМАЛОСЬ игру обмануть и нарисовать в её королевстве что-то ещё. В чём логика:
BeginScene();
РисуемВсёИгровое();
EndScene();
Нам надо взять и нарисовать что-то своё после всего игрового. Удобнее всего это сделать прямо перед вызовом EndScene(), типа вот так:
BeginScene();
РисуемВсёИгровое();
РисуемЧужое();
EndScene();
Хитрые человеки уже давно смекнули, что можно же сделать инъекцию и подменить собой вызов EndScene:
BeginScene();
РисуемВсёИгровое();
CustomEndScene();
void CustomEndScene() {
DrawRectangle();
DrawText();
EndScene();
Получается, что игра хочет вызвать EndScene, вместо этого попадает в нашу CustomEndScene, где мы сначала дорисовываем что-то своё, а потом уже вызываем оригинальную функцию EndScene. В итоге игра справедливо считает, что так и было задумано. Магия!
Вот таким вот нехитрым образом и работает большинство хаков, связанных с графикой - начиная с wallhack и maphack, заканчивая экранными меню.
Сложность состоит в том, чтобы найти EndScene() и указатель на устройство, который где-то до этого получает игра, потому что только лишь зная указатель на устройство мы можем что либо рисовать. Собственно, скоро мы вооружимся OllyDbg и пойдём наш пример курочить. To be continued!
Комментариев нет:
Отправить комментарий
Не люблю мат и низкий уровень грамотности. Чем конкретнее поставите свой вопрос и чем лучше он будет выглядеть - тем большая вероятность на мой ответ. :)