13.4. Борьба технологий защиты и взлома | Телекоммуникации вчера, сегодня, завтра

Последовательность действий при создании объекта радиосвязи

Бланк формы №1 ТАКТИКО-ТЕХНИЧЕСКИЕ ДАННЫЕ РЭС

Поставка оборудования обеспеченного радиочастотами

Витрина



13.4. Борьба технологий защиты и взлома

Разумеется, разработчики протекторов не хотят мириться с тем, что восстановить оригинальную программу так легко. И они всячески стремятся если не сделать восстановление невозможным, то хотя бы максимально усложнить этот процесс и, самое главное, предотвратить полную автоматизацию. Дело в том, что для использования автоматического депротектора не нужно быть гением, достаточно иметь базовые знания. А вот деактивировать действительно серьезную навесную защиту могут буквально единицы — считанные проценты от числа всех людей, серьезно занимающихся исследованием программ (Reverse Engineering), и тысячные доли процента от общего числа пользователей.

Однако, специалисты по исследованию программ тоже не хотят мириться тем, что протектор не удается быстро снять, и придумывают новые методы обхода защиты. Такое неофициальное противостояние продолжается не первый год, и конца ему пока не видно. Но, похоже, именно это противостояние и стимулирует развитие протекторов. Иначе уровень технологических решений, используемых для защиты, остался бы на уровне, достигнутом еще в первых версиях протекторов.

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

Одним из способов достижения такого поведения программы является использование API протектора. То есть программист, разрабатывающий программу, которая позже будет подвергнута обработке протектором, специальным образом описывает, какие области должны быть зашифрованы большую часть времени выполнения программы, и явным образом указывает, в какой момент должны производиться расшифрование фрагмента и его последующее зашифрование, обращаясь к API протектора.

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

Другой способ защиты кода заключается в использовании особенностей работы процессора. Можно модифицировать некоторые фрагменты программы таким образом, чтобы при передаче им управления возникали так называемые исключительные ситуации (Exception). Эти исключительные ситуации будут обработаны кодом протектора, который должен восстановить правильное содержимое модифицированного фрагмента кода, позволить ему выполниться, а затем снова привести к неработоспособному состоянию.

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

Для программ, написанных с использованием "чистого" Win32 API (без библиотек типа Object Windows Library или Visual Components  Library), pecypс окна часто подгружается в память неявно путем вызова функции CreateDialogParam или CreateDialoglndirectParam. При этом не сама Программа, а менеджер диалогов, являющийся частью операционной системы, читает ресурс, описывающий окно, и интерпретирует его, подгружая из ресурсов меню, картинки и т.д.

Однако некоторые средства разработки сохраняют описания диалогов в собственном формате и практически не полагаются на то, как работает с ресурсами менеджер диалогов, встроенный в Windows. Это характерно, например, для программ, созданных при помощи Borland Delphi или C++ Builder с использованием библиотеки Visual Components Library' (VCL).

Ресурс, описывающий диалоговое окно в VCL, хранится как двоичный блок данных RCDATA, и Windows не пытается самостоятельно его читать и интерпретировать. Поэтому протектор может модифицировать программу таким образом, чтобы ресурсы, описывающие диалоги, сохранялись в зашифрованном виде и расшифровывались только в тот момент, когда программа обращается к VCL с запросом на загрузку диалога из ресурсов. Этот метод позволяет лучше защитить ресурсы, но, разумеется, применим далеко не ко всем программам.

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

Для защиты содержимого таблицы адресов импортируемых функций могут применяться весьма разнообразные подходы. Например, протектор может заполнить таблицу импорта ссылками на маленькие функции-переходники, расположенные в теле протектора. А каждый переходник будет передавать Управление нужной функции во внешней библиотеке. Как расширение этого метода, внутрь функции-переходника из библиотечной функции может копироваться несколько первых инструкций, которые будут выполняться в теле протектора. Следовательно, управление будет передаваться не на Первую инструкцию библиотечной функции. Это не только затрудняет восстановление таблиц импорта, но и позволяет обойти точки останова, размеренные в начале библиотечных функций.

Некоторые функции Win32 API во время выполнения процесса всегда возвращают одно и то же значение. Примером такой функции является; GetcommandLine. Протектор может вызвать эту функцию до передачи управления основной программе и запомнить результат, а на запросы программы, к GetcommandLine просто возвращать сохраненное значение. При этом nepe-i дачи управления библиотечной функции вообще не происходит.

Наконец, в распоряжении разработчиков протектора есть довольно сложное в реализации, но очень эффективное средство — трансляция части инструкций в псевдокод и выполнение этого псевдокода на встроенной виртуальной машине. То есть к моменту передачи упра&чения в тело защищенной программы некоторые фрагменты кода, относящиеся или к самой программе, или к импортированным функциям, представлены не в системе команд процессора семейства х86, а в некотором альтернативном виде, и выполнить эти фрагменты кода может только протектор. Следовательно, для снятия защиты необходимо разобраться в системе команд виртуальной машины и перевести защищенные фрагменты из системы команд протектора в систему команд процессора х86, а это весьма трудоемкая задача.

Как уже упоминалось ранее, некоторые средства защиты имеют свой собственный API, позволяющий защищаемой программе обращаться к протектору во время выполнения. Это способствует интеграции протектора с программой и создает очевидные трудности, связанные с необходимостью эмуляции API протектора при снятии защиты.

Также разработчики некоторых протекторов предлагают тем, кто хочет защищать свои программы, различные способы, помогающие установить факт, что с программы была снята защита. Эти способы могут являться частью API протектора, а могут и основываться на характерных признаках, которыми обладает защищенная программа после ее загрузки в память.

Очень многие протекторы усиленно препятствуют использованию средств отладки, включая отладочные регистры. Одним из методов, мешающих использованию аппаратных точек останова, является хранение промежуточных данных протектора в отладочных регистрах, следствием чего является отказ в запуске программы, если содержимое отладочных регистров меняется извне.

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



Поиск по сайту


Смотрите также