Введение или руководящая идея
Будем исходить из того, что основным орудием хакера является дизассемблер и отладчик (а при анализе упакованных программ к ним еще добавляется и дампер). Существует множество хитроумных трюков, затрудняющих трассировку и отравляющих дизассемблеру жизнь, однако, они только подогревают интерес хакера и зачастую вызывают непредсказуемые конфликты, что не есть хорошо.
А давайте просто спрячем защитный код там, где никто не станет его искать? Программные комплексы наших дней содержат миллионы строк кода и потому никогда не анализируются целиком. Если хакер встречает вызов API-функции LoadLibrary, он искренне верит, что это действительно LoadLibrary, а не что-то еще. Теоретически, в API-функцию можно заглянуть отладчиком, однако, практически она представляет "черный ящик". Анализируя аргументы и последовательность вызов API-функций (этим занимаются API-шпионы), хакер получает общее представление о работе защитного механизма и, зачастую, прибегать к отладчику/дизассемблеру уже нет необходимости.
Мыщъх предлагает защищаться так: берем какую-нибудь ненужную API-функцию, которая заведомо не используется, и копируем поверх нее свой собственный код (далее по тексту называемый X-кодом), выполняющий что-то полезное, например, проверяющий серийный номер или ну я не знаю. Тут главное фантазию иметь! Выбирать лучше всего неброскую, ненапряженную функцию с названием не вызывающим у хакера никаких подозрением, например, GetTimeZoneInformation. Естественно, перед копированием необходимо присвоить атрибут записи, что достигается вызовом VirtualProtect с флагом PAGE_EXECUTE_READWRITE, а после копирования вернуть исходные атрибуты защиты обратно.
Модификация API-функций носит сугубо локальный характер. Механизм Copy-on-Write автоматически "расщепляет" все измененные страницы и потому изменения может увидеть только тот процесс, который их записал. Это значит, что за конфликты с другими процессами можно не волноваться. Заботиться о восстановлении оригинального содержимого API-функций так же не нужно.
Поскольку, адреса API-функций не остаются постоянными и варьируются одной системы к другой, X-код не может привязываться к своему расположению в памяти и должен быть полностью перемещаем. Чтобы не заморачиваться можно разместить X-код внутри нашей программы, а в начало API-функции внедрить jump. Конечно, это будет намного более заметно. Стоит хакеру заглянуть отладчиком в API-функцию, как он тут же поймет, что она пропатчена, а вот при копировании X-кода поверх API-функции это уже не так очевидно. Так что свой путь каждый выбирает сам.
Развивая мысль дальше, можно не затирать ненужное API, а взять общеупотребляемую функцию типа CreateFile и слегка "усовершенствовать" ее, например, незаметно расшифровывать содержимое файла или просто мухлевать с аргументами. Допустим, программа открывает файл "file_1". X-код, внедренный в CreateFile, заменяет его на "file_2", передавая управление оригинальной CreateFile – пусть она его открывает!
Фактически, мы приходим к идее создания API-перехватчика (ака шпиона), только шпионить он должен не за чужими процессорам, а за своим собственным, перехватывая нужные API-функции и скрытно выполняя некоторые дополнительные действия. Это серьезно затрудняет дизассемблирование, поскольку ключевые моменты защитного алгоритма идут мимо хакера, который ни хрена не может понять как это работает и почему (например, можно внедрить в CreateFile процедуру проверки ключевого файла, а в самой программе только имитировать его выполнение, заставляя хакера анализировать километры совершенного левого кода).