Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #57, АВГУСТ 2005 г.

Ключик к сердцу

Chingachguk/HI-TECH

Спецвыпуск: Хакер, номер #057, стр. 057-094-6


db 'DEADBEEFBABY'

Next:

Обработчик исключения в драйвере проверит наличие тестовой строки после команды UD и значения регистров. Если он признает исключение "своим", он обработает его соответственно: например, запишет данные из ключа по указателю в edi и передаст управление на метку Next.

Таким образом, мы рассмотрели один из возможных каналов обмена между защищенным приложением и драйвером защиты, работающим на уровне ядра. Их реализация может быть и иной, но, по крайней мере, при анализе следует проверять "свободные" исключения, которые обычно мало используются системой: это устаревшая команда bound (int 5) и некоторые другие. Следует немного ознакомиться с процессором Intel в защищенном режиме и в целом представлять, какие возможности могут быть у защиты для открытия каналов общения с драйвером. Напоследок брошу еще один камешек в огород разработчиков такой защиты. Совсем не удивительно, что процессор тратит длительное время на обработку исключений, а данная защита использует... тысячи вызовов такого типа. Поэтому обращаюсь к разработчикам и говорю: "Не думайте, что Ваши программы просто плохо написаны или даже что они очень умные - просто дайте защите немного потренироваться". Однако стоит отметить, что для следующей версии ключа - HASP4 - разработчики отказались от этой "замечательной" техники и остановились на "обычном" DeviceIoControl.

Драйвер не спрячешь

Перейдем на следующий уровень комплекса защиты и рассмотрим, что происходит в драйвере защиты. Для начала необходимо определить их наличие. Наверное, из стыда защитниками хотелось бы скрыть от пользователя наличие драйвера, но система им этого особо не позволяет, поэтому меню "Установка драйвера защиты" действительно означает то, что в нем указано. Список драйверов можно посмотреть в стандартных настройках Win, а детально рассмотреть его, например, при помощи команды "driver <имя_драйвера>" в SoftIce.

Драйвер выполняет не только функции передачи данных (запросов) из приложения и ответов ключа приложению (транспорт), но и часто содержит в себе часть функциональности, предоставляемой ключом. Так называемые "API ключа" часто разбиваются на две части: обертка реализована внутри драйвера, а нижние функции выполняет сам ключ. Для примера опишу следующую ситуацию. Пусть ключ способен выполнять шифрование четырехбайтных слов:

void Key_EncryptData(DWORD *EntryData)

{

...

*EntryData= ...

}

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

void Driver_EncryptData(void *EntryDataAboveOrEqualThan4Bytes, DWORD DataLen)

{

...

memcpy(EntryDataAboveOrEqualThan4Bytes, ... , DataLen);

}

Видно, что функция Driver_EncryptData может выполнять шифрование массива байт, длина которого может превышать четыре байта. Это может быть сделано по нескольким соображениям: разработчику не хватает шифрования двойных слов; функция ключа Key_EncryptData недостаточно криптоустойчива, и драйвер пытается усилить мощность защиты; проектировщик защиты решил укрепить бастионы на пути к оригинальной функциональности ключа и некоторым другим.

Назад на стр. 057-094-5  Содержание  Вперед на стр. 057-094-7