Привет! 1. Что означает конструкция if () {}: if - это условный оператор. Все, что идет в круглых скобках - это тело условия. Оно подчиняется законам булевой алгебры и результат всегда должен приводиться к bool, оно же Boolean, оно же (удивительно, но факт!) int. Значения может быть всего два - ноль и не ноль. Работает оно примерно так: if ( 1 == 1 ); /* вернет True, или 1, потому что единица равна единице */ if ( 1 != 1 ); /* вернет False, или 0, потому что "не равна ли единица единице" - это ложь */ if ( 2*2 == 4 ) /* вернет True, потому что 2*2 действительно равно 4 */ Бывает: равно (1 == 1) не равно (1 != 0) больше (1 > 0) меньше (0 < 1) больше или равно (2 >= 1) меньше или равно (1 <= 2) Не одним if едины, еще есть else. Работает он следующим образом: if (условие) { действие А } else { действие Б } Если условие истинно (возвращает True), то проваливается в действие А, иначе (если условие ложно и возвращает False) - в действие Б. PS: Внутри условия еще действует дискретная математика - это всякие веселые штучки вроде &&, || и другие. Для начала знать нужно только эти две веселые штучки. Поясняю подробнее. if ( (1 == 1) && (2 == 2) ) /* Если условие 1 И условие 2 истинны, то проваливаемся внутрь, иначе - идем дальше или в ветку else. && - значит, что оба (все) условия должны выполниться */ if ( (a != c) || (b == 0) ) /* Если условие 1 ИЛИ условие 2 истинны, то см. выше. || - значит что хоть одно условие должно выполниться */ 2. Можно ли создать отдельный указатель имени функции? Да, можно. По большому секрету скажу, что имя функции - это указатель на нее. Синтаксически я могу и ошибиться, но проверил этот код в gcc: #include <stdio.h> int foo() { return 0; } int main() { int (*bar)() = &foo; return bar(); } 3. Поиск в d3d по сигнатуре байт. DirectX - это набор COM-объектов. За подробностями - в [википедию], а я объясню на пальцах. Это чудо-технология от Microsoft, позволяющая вынести некоторый код, лежащий чаще всего в DLL, практически на уровень всей системы. Т.е. Это очень абстрактная фигня - пользоваться можно, а сделать себе хорошую такую копию, которую можно пощупать - нельзя. Ты можешь подгрузить себе нужную dll и попросить видеокарту что-нибудь нарисовать, но сделать "объект" и приказывать ему, как объекту класса - не получится. Так как вся высокоуровневая фигня в любом случае упирается в указатели, то выглядит это как указатель на указатель на таблицу указателей. Да, это не опечатка. Таблица эта висит где-то в виртуальном адресном пространстве игры и дергается вский раз, когда игра хочет что-нибудь нарисовать. Для определенных версий directx(?) и для определенных игр(?) эта таблица ищется при помощи сигнатуры байт, потому что это простое и быстрое решение. Дальше в таблице ищется смещение до нужной функции, указатель по этому смещению меняется на свой - вуаля, hook готов. 4. Как сделать code-injection на С++. Сразу предупрежу, что не буду приводить код, а только лишь опишу алгоритм. Во-первых, неужели тебе никогда не было любопытно, как инъекция выглядит в СЕ? Напомню: 0x11223344 - адрес для инъекции. alloc(1024) a; a: nop nop nop ret 0x11223344: jmp a nop Это - типичная секция [ENABLE], пусть и в псевдокоде. Я когда-то рисовал для одного нашего не очень опытного любителя поломать NFS картинки, но сейчас их под рукой нету. В общем, что происходит, когда мы нажимаем на кнопку [ENABLE]? А вот что: 0. По адресу "a" (который в CE обозначается буквами чисто для удобства) выделяется кусок памяти в 1024 байта. 1. В этот кусок записывается ассемблерный код инъекции. В нашем случае - nop nop nop jmp 0x11223344+5. 2. По адресу 0x11223344 записывается команда "jmp a nop", потому что jmp+адрес - это 4 байта, а нам нужно 5 для сохранения целостности кода. Потому что все прыжки по коду - относительные, т.е. по строгим смещениям. 3. Готово! Вы великолепны! Когда игра добегает до адрес 0x11223344, она там видит команду безусловного перехода. Послушно прыгает, выполняет нашу инъекцию, а затем прыгает обратно (0x11223344+5 - сразу после jmp a nop). Вопрос, как нам такую штуку реализовать программно? Рассмотрим случай, что мы не внутри адресного пространства dll. У нас есть адрес, куда нужно сделать инъекцию, и код. Делаем: 0. Получаем все нужные права через OpenProcess и VirtualProtectEx. 1. Выделяем себе кусок памяти в адресном пространстве игры через VirtualAllocEx. 2. Через WriteProcessMemory записываем в него код инъекции (в 16-ричной системе счисления. На конце - jmp. Все ассемблерные команды - в опкодах, т.е. как бы после компиляции). 3. Берем адрес для инъекции. Берем место, куда записали код. Нам нужно сделать относительный прыжок, верно? Отнимаем один адрес из другого. Все время путаю, какой откуда, но это можно проверить в отладчике. 4. Разворачиваем задом наперед этот адрес (в 16-ричном представлении!), сохраняем куда-нибудь. 5. Берем адрес, куда записали код инъекции + длину инъекции в байтах + 4. Отнимаем этот адрес из адреса для инъекции + еще пять байт. Потому что сначала мы прыгаем из игры в наш код, а потом из нашего кода обратно в игровой. +5, чтобы не прыгнуть на то место, с которого прыгали изначально - прыгать нужно _после_ этого места. 6. Записываем через тот же WriteProcessMemory адрес в конец кода инъекции (чтобы было jmp + адрес). 7. Записываем в место инъеции "jmp + смещение для кода инъекции + nop". 8. Готово! Все это - в идеальном случае, т.к. у нас может или не быть места под jmp + смещение (слишком короткая команда) - в этом случае ее нужно будет перенести внутрь кода инъекции, или наоборот - команда слишком длинная, так что для сохранения порядка байт нужно будет после jmp + смещение подставить большее количество nop. Я это первый раз давным-давно делал на ассемблере - сломал камаз граблей и убил пару недель времени. Лучше всего наблюдать за процессом через отладчик (рекомендую OllyDbg) и запастись не игрой, а программой, которая маленькая и быстро запускается. Ибо вылетать она будет часто. 5. Как правильно писать .h-файлы. Тут я помочь мало чем смогу - разве что отослать к прочтению какого-нибудь учебника по Си (не по С++), а так же документации по самим хидерам и по стандартным хидерам, которые подсовывает в проект visual studio. 6. Почему хуки через сигнатуры можно использовать в игре А, а в игре Б - нельзя? Как сделать, чтобы было можно? На этот вопрос я уже частично ответил в предыдущем вопросе по этой теме, если коротко - сигнатуры отличаются. Как сделать, чтобы было можно - трудно, нудно и долго, потому что очень много совершенно вырвиглазной отладки. У меня ушла пара месяцев на первую сколько-нибудь стабильно работающую версию под DX9. Сейчас она все еще сыровата, но доделывать уже работающее - гораздо проще и приятнее, чем ковырять с нуля. Если коротко - я создаю временный dx-интерфейс для невидимого окна размером 1х1 пиксель, сохраняю его адрес и потом ищу такой же в куче (heap) целевого приложения. Для этого никакие сигнатуры не нужны и это работает всегда, потому что версия dx - единая в рамках компьютера, на котором запускается мой сканер и приложение. Докрутить dx10-11-12 (когда последний выйдет) и OpenGL - дело времени, которого толком нет. Одна проблема - подмена указателей на функции работает довольно хреново, сплайсинг тоже - приходится постоянно мониторить состояние каждой функции и ежели что не так - чинить, пока игра не обрушилась. Примерно такой же метод используется в Steam и Fraps. Как результат - я могу рисовать в любой игре и что захочу.