Как сделать эмулятор ключа на лицензию интач. Мини HASP ключ из любого устройства USB. Интервью с экспертом

Инструкция

Ключ HASP представляет собой устройство размером с . Он может подключаться к компьютеру через LPT-порт, но наибольшее распространение получили ключи в формате USB-брелока. Внутри каждого ключа находится защищенный микроконтроллер. Внутри чипа размещен криптопроцессор, используемый для шифрования и дешифровки потоков данных, посылаемых в процессе работы от защищенной программы ключу и обратно. Это означает, что программа не будет работать без конкретного ключа HASP, к которому она привязана. В результате, продавая ключи, разработчик может контролировать процесс распространения программы, ограничивать количество пользователей.

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

В результате желание скопировать ключ появляется у лицензированных покупателей продукта. Сам процесс создания клона весьма сложен, поскольку ключи специально разрабатывались для того, чтобы максимально затруднить их дублирование. Первым этапом при копировании HASP-ключа является снятие дампа.

Скачайте набор оригинальных драйверов HASP HL Installer. Распакуйте и установите драйверы ключа, это описано в приложенной инструкции. Перезагрузите компьютер. Установите и запустите логгер TORO Dongle Monitor. Установите и запустите защищенную программу, некоторое время поработайте в ней. Внизу окна логгера должны появиться следующие строки:
Hasp In:> HaspInitPacket
PW1=XXXXX (0x1234) , PW1=YYYYY (0x5678)
Это пароли для ключа. В той же паке где и логгер также лежит дампер памяти ключа. Закройте логгер и запустите дампер с параметрами в командной строке:
h5dmp.exe 0x1234 0x5678
В результате работы программа создаст в корне диска C: файл с дампом ключа.

Обратите внимание

Создание эмуляторов ключа пользователем, который не покупал лицензию на программу, противоречит статьям 272, 273 УК РФ.

Источники:

  • дамп hasp
  • Распечатать информацию о программе HASP Crack

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

Вам понадобится

  • - программа Dekart Key Manager.

Инструкция

Для того, чтобы слить дамп ключа флеш-карты, воспользуйтесь специальным программным обеспечением. В основном все утилиты, предназначенные для этого, платные. Вы можете воспользоваться программой Dekart Key Manager или ее аналогами.

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

Запустите программу и ознакомьтесь с ее интерфейсом. В левой части главного окна вы найдете список устройств с ключами, подключенных к вашему компьютеру через USB-интерфейс, а в правой части – содержимое выделенного вами носителя информации. Сделайте копию информации, находящейся на ключе при помощи меню программы. Для этого воспользуйтесь меню сохранения данных из файла.

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

Обратите внимание, что при возникновении проблем с использованием программы в режиме совместимости необходимо в обязательном порядке с операционной системой Windows XP. В противном случае при копировании информации на съемный накопитель в дальнейшем могут возникнуть проблемы с дальнейшим ее считыванием.

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

Полезный совет

Заранее заказывайте копии ключей.

Файл малого дампа создается системой каждый раз при возникновении неисправимой ошибки, вызвавшей сбой компьютера. Он может быть полезен при небольшом объеме жесткого диска, но именно из-за своих малых размеров не всегда содержит достаточное количество информации для исправления диска.

Инструкция

Нажмите кнопку «Пуск» для вызова главного меню системы и перейдите в пункт «Настройки» для выполнения операции настройки параметров запуска и восстановления с помощью файда малого дампа памяти.

Перейдите на вкладку «Дополнительно» открывшегося окна приложения и нажмите кнопку «Параметры» в разделе «Загрузка и восстановление».

Откройте программу браузера и перейдите на страницу http://www.microsoft.com/whdc/devtools/debugging/default.mspx . Скачайте программу WinDbg, предназначенную для чтения памяти малого дампа памяти компьютера.

Установите загруженное приложение (по умолчанию - C:/Program FilesDebugging Tools for Windows) и вернитесь в главное меню «Пуск».

Перейдите в пункт «Выполнить» и введите значение cmd в поле «Открыть» для инициации процедуры открытия программы WinDbg.

Нажмите кнопку OK для подтверждения выполнения команды и введите в поле командной строки для перехода к папке приложения значение cd c:program filesdebugging tools for windows.

Нажмите функциональную клавишу Enter для подтверждения выбранных изменений и введите следующее значение:windbg -y путь_сивола -i путь_образа -z путь_файла дампа .Здесь путь_символа - путь к локальной папке с загруженными символами и реальными двоичными файлами; путь_образа - путь к папке C:WindowsI386, содержащей файлы, скопированные из папки I386 установочного диска Windows; путь_файла_дампа - путь и имя выбранного файла дампа памяти.

Используйте команду!analyze -show для отображения кода и параметров неустранимой ошибки системы.

Укажите команду!analyze -v для отображения более подробных сведений о произошедшей ошибке.

Выберите команду Im N T для отображения списка загруженных драйверов.

Используйте команду dump c:windowsminidumpminidump.dmp для выполнения процедуры анализа файла малого дампа памяти компьютера.

Обратите внимание

Приложение WinDbg для чтения файла малого дампа памяти, как и аналогичная служебная программа Dump Check, не входят в состав поставки операционной системы Windows.

Полезный совет

Список всех файлов малого дампа расположен в папке %SystemRoot%Minidump.

Источники:

Наверное, многим пользователям знакома ситуация, когда при попытке записать информацию на карту памяти появлялось уведомление о том, что она защищена от . Конечно, это вызывает желание снять защиту. Ведь зачем же тогда нужна карта памяти, если не для хранения и копирования информации? А снимается она довольно просто.

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

Хочу обратить внимание, что ошибка появилась на компьютере, на котором было 2 сетевые карты с 2мя разными сетями. Почему то сразу значения данному моменту не придал. Видимо, потому что монитор HASP обнаруживал данные ключи отлично, из-за чего искал проблему в 1С. В результате чего убил пол дня рабочего времени. Проблема действительно крылась в двух сетевых картах, а если сказать точнее, 2 разные сети, решение было в файле C:\Program Files\1cv81\bin\conf\nethasp.ini

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

Начну с маленького ликбеза:

1С:Предприятие 8 используется систему защиты с помощью аппаратных ключей HASP , скачать драйвер, программу мониторинга и службу HASP Loader можно на сайте http://www.aladdin-rd.ru/, а конкретно в разделе поддержки http://www.aladdin-rd.ru/support/downloads/hasp/.

Ключи защиты для 1С подразделяются на:

1. Однопользовательские (обязательно должны физически быть подключены к компьютеру, на котором запускается 1С)

модель HASP HL Basic (синего цвета ), данный ключ имеет маркировку H4 M1 ORGL8 , не имеет встроенной памяти и персонального ID, не хранит в себе никаких параметров и настроек. Поставляется продуктами имеющими лицензию на одно рабочее место.

Сетевой ключ HASP

2. Многопользовательские (ключ находится в сети, 1С может запускаться на любых компьютера в пределах локальной сети или домена)

Сетевые клиентские ключи включают серию (красного цвета ). Имеют внутреннюю память, в которой хранится количество лицензий, и уникальный ID. Существуют разновидности на 5, 10, 20, 50 и 100 пользователей. Имеет маркировку NETXX ORGL8 , где ХX - количество лицензий (например NET5 ORGL8 ). Существуют также ключи на 300 и 500 пользователей которые имеют маркировку NET250+ ORG8A и NET250+ ORG8B . Поставляются с продуктами имеющими лицензию на 5 рабочих мест, а также отдельно, в виде дополнительных клиентских лицензий.

Ключ для Сервера 1С

3. Серверные (обязательно должны физически быть подключены локально к компьютеру, на котором установлен и работает сервер агента 1С Предприятие)

Ключи для сервера 1С Предприятие бывают только локальные . 32-битная версия имеет ключ защиты HASP HL Pro (фиолетового цвета ), который имеет внутреннюю память и уникальный ID. Имеет маркировку ENSR8 , поставляется вместе с лицензией на сервер 1С Предприятие.

Для 64-битного сервера используется ключ HASP HL Max (зеленого цвета ) с внутренней памятью и уникальным ID. Имеет маркировку EN8SA и поддерживает также 32-битный сервер. Т.е. имея лицензию на 64-битный сервер можно, не меняя ключа, использовать 32-битную версию, но не наоборот.

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

Для многопользовательского (сетевого) ключа защиты необходимо:
1. Установить драйвер ключа защиты на одну из машины в сети, которая будет являться сервером ключа - HASP4_driver_setup.zip
2. Установить сервер (службу) ключа защиты на эту же машину - HASP_LM_setup.zip
3. Вставить ключ защиты в сервер в USB порт
4. Установить 1С на клиентские машины

В общем случае, данных действий для работы 1С достаточно. В процессе запуска и дальнейшей работы 1С:Предприятие 8 на локальных машинах, система будет обращаться с помощью broadcast-запроса по порту 475 и искать ключ защиты. В случае не удачного поиска будет выдано сообщение „не обнаружен ключ защиты программы“ и работы 1С:Предприятие прервется.

Если вы столкнулись с сообщением „не обнаружен ключ защиты программы “ необходимо проверить:
1. наличие ключа защиты в порту usb сервера ключа
2. проверить запущен ли сервер ключа на сервере (процесс с именем „Hasp loader“)
3. проверить командой telnet доступность сервера ключа с локальной машины по порту 475 (например: telnet 192.168.100.100 475)

Если все проверки прошли успешно, но ошибка осталась, переходим к более детальным настройкам. В папке установки 1С:Предприятие 8 (как правило, c:\program files\1cv81\bin\conf или c:\program files\1cv8\bin\) имеет файл nethasp.ini . Это файл настройки ключа защиты, он разбит на секции, нас интересует секция . При установке 1С, по умолчанию, в данной секции все параметры отделены двойными знаками ";", что означает игнорирование данных настроек. При этом драйвер ключа ведет себя следующим образом:
1. посылается пакет типа broadcast по локальной сети по порту 475 в поисках сервера ключа защиты
2. если ответ не получен - ошибка

Недостатки конфигурации по умолчанию:
1. на broadcast уходит какое-то время
2. не все сервера отвечают на подобные пакеты
3. broadcast какая-никакая, но нагрузка на сеть

Для решения данной проблемы необходимо сделать следующее:
1. укажем конкретный адрес где искать сервер ключа (например: NH_SERVER_ADDR = 192.168.100.100)
2. запретим broadcast поиск (NH_USE_BROADCAST = Disabled)
3. и ограничим типы пакетов только TCP-протоколом (NH_TCPIP_METHOD = TCP)

Как показывает практика, скорость запуска 1С:Предприятие 8 после такой настройки возрастает заметно!

Но есть и кое-какие недостатки данного метода:

необходимо следить за тем, чтобы адрес сервера ключа защиты не изменился, иначе придется на всех локальных машинах перенастраивать файл nethasp.ini!

Хотел бы так же уточнить несколько моментов по работе с ключами, с которыми пришлось сталкиваться при работе:

1. Monitor HASP не показывает ключ

Сам по себе монитор может показать только наличие менеджера лицензий на том или ином адресе. Ключ он сможет увидеть только после того, как защищенное приложение успешно откроет хотя бы одну сессию с ключом. Кроме того, следует учитывать, что Aladdin Monitor работает только по протоколу UDP, порт 475. Таким образом, отсутствие данных о ключе в мониторе еще не означает, что ключ недоступен для приложения.

2. Два ключа защиты 1С HASP на одном компьютере

При установке двух и более ключей защиты программного обеспечения HASP на один компьютер следует учитывать, что:

  • Ключи, имеющие разные серии, будут работать нормально. (по отношению к 1С: 1 серверный и 1 сетевой будут работать нормально)
  • Ключи одной серии будут работать, если такая возможность была реализована разработчиком защищенного ПО. Если же разработчиком данная возможность не была реализована, то ключи, относящиеся к одной серии, не будут работать совместно на одном компьютере, будет виден только один из них: либо ближний к порту (в случае с LPT-ключами), либо размещенный на порту с младшим адресом (в случае с USB-ключами защиты программ HASP). (по отношению к 1С , - 2 локальный или 2 сетевых ключа на одном компьютере работать корректно, скорее всего не будут)
  • не рекомендуется ставить вместе локальный и сетевой ключ, это связано с особенностью защиты 1С Предприятия: находя локальный ключ программа никогда не будет искать сетевой.

Возможные решения данной проблемы:

  • Замена нескольких ключей защиты программ HASP на один, с бОльшим количеством лицензий (об этом хорошо написано тут: http://v8.1c.ru/predpriyatie/questions_licence.htm).
  • Установка ключей защиты на разные компьютеры с последующей установкой и настройкой менеджеров лицензий при каждом ключе.

3. Два и более менеджеров лицензий (License Manager) в сети

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

На машине где установлен ключ находим файл nhsrv.ini в папке с менеджером лицензий. За имя сервера лицензий отвечает параметр NHS_SERVERNAMES, оно может состоять из латинских букв и цифр и содержать не более 7 символов.

NHS_SERVERNAMES = NAME1

После чего на клиентских машинах желательно отредактировать файл nethasp.ini, явным образом указав адреса и имена менеджеров лицензий:

NH_TCPIP = Enabled NH_SERVER_ADDR = 192.168.0.10, 192.168.0.11 NH_SERVER_NAME = NAME1, NAME2

Ну вроде все нюансы описал, если чего вспомню, обязательно дополню! Всем пока!

С Уважением, Mc.Sim!


В статье речь пойдет о реализации аппаратно-программной защиты на основе любой флешки. Но следует учитывать, что предложенная методика не является серъезным конкурентом существующих аппаратных ключей таких как HASP HL (с обновляемой прошивкой) от Alladin , Sentinel, Rockey и др…

Вы никогда не задумывались, для чего может сгодиться обычная флешка? Многие сразу ответят: "… что за вопрос? Конечно для хранения информации…". Но, это если рассматривать с точки зрения обывателя. А если взлянуть на нее "глазами компьютера"? Очевидно, что этот процесс достаточно непрост, это и протокол обмена по USB, переходные процессы, идентификаторы и GUID (Globally Unique IDentifier)…

Немного теории...
HASP (Hardware Against Software Piracy) - это система защиты программы (ПО) и аппаратуры от нелегального использования. Основой большинства ключей HASP - обычно является заказной чип c уникальным ПО, как например в получивших сейчас широкое распространение в дверной автоматике таблетках iBUTTON от Dallas Semiconductor.

Принцип защиты состоит в том, что в процессе запуска программа опрашивает ключ, подключённый к компьютеру по I2C, LPT, PCMCIA или USB. Если ключ отвечает "правильно", то программа выполняется нормально. Иначе, она блокирует доступ к определенным функциям или просто не запускается. Таким образом, любая защищаемая программа состоит непосредственно из самой программы и механизмов проверки ключа. Задача этих механизмов - проверить наличие ключа, получить его уникальный идентификатор, прочитать или изменить содержимое встроенной памяти.

Предпосылки защиты ПО. Существующие решения
Основными критериями для использования аппаратных ключей являются:

  • цена используемых ключей должна быть неизмеримо меньше цены софта
  • длительный срок жизни программного продукта
  • индивидуальный алгоритм взаимодействия
Первый критерий обеспечивается довольно легко: с интенсивной разработкой новых видов памяти, таких как PRAM*, цены на SSD (Solid State Disk) носители уже составляют от 5 долларов. Таким образом разработчик без ущерба для бюджета может распространять продукт на самом ключе.

* PRAM (Phasechange Random Access Memory) - память с произвольным доступом, основанная на фазовых переходах вещества - халькогенида, обладающую скоростью доступа порядка 10 нс, что сравнимо с современными ОЗУ.


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

Существует множество вариаций ключей: без собственной памяти, с защищенной памятью, со встроенными REAL TIME часами, со встроенными сетевыми протоколами.

В то же время, кроме предлагаемого в статье встраиваемого решения в виде компонента, существуют такие продукты как StarForce и HASP Envelope от компании Alladin, позволяющие уже на этапе продажи добавлять защитные модули обмена с ключом в готовые программы, интегрируя их в код продукта. Но у них есть издержки, связанные с затратами на покупку самих HASP ключей, стоимость которых составляет от 25 до 50 долларов за штуку (в зависимости от модели ключа) и ПО для встраивания (от 200 долларов), при стоимости защищаемой программы от 20 долларов.

Разработка ПО и средства отладки
Как известно, метод защиты HASP основан на привязке программы к некоему или совокупности уникальных параметров ключа и даже оборудования. Так как мы будем использовать устройство USB, то априори достаточно считать серийник и ID флешки**, поскольку они не меняются при их форматировании.

** не все флеш-накопители имеют данный номер, к примеру некоторые чипы от LG


Для работы необходимо следующее:

  • среда Borland Delphi 5-7
  • утилита Dependency Walker из комплекта Visual C++ 6.0
В средах NT/XP информацию о устройствах предоставляет стандартная системная библиотека SetupApi.dll . Чем и воспользуемся... Рассмотрим экспортируемые ею функции с помощью Dependency Walker, и для удобства разработчика встроим в компонент (в дальнейшем он будет использоваться как базис механизма защиты)
... CM_Get_Device_IDA:function(dnDevInst: DWORD; Buffer: PChar; BufferLen: DWORD; ulFlags: DWORD): DWORD; stdcall; SetupDiGetClassDevsA:function(ClassGuid: PGUID; Enumerator: PChar; hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall; SetupDiEnumDeviceInfo:function(DeviceInfoSet: HDEVINFO; MemberIndex: DWORD; DeviceInfoData: PSP_DEVINFO_DATA): boolean; stdcall; SetupDiDestroyDeviceInfoList:function(DeviceInfoSet: HDEVINFO): boolean; stdcall; CM_Get_Device_ID_Size:function(pulLen: PDWORD; dnDevInst: DWORD; ulFlags: DWORD): DWORD; stdcall; SetupDiCallClassInstaller:function(InstallFunction: DWORD; DeviceInfoSet: DWORD; DeviceInfoData: PSP_DEVINFO_DATA): BOOL; stdcall; SetupDiGetDeviceRegistryPropertyA:function(DeviceInfoSet: DWORD; DeviceInfoData: PSP_DEVINFO_DATA; Propertys: DWORD; PropertyRegDataType: PWORD; PropertyBuffer: PByte; PropertyBufferSize: DWORD; RequiredSize: PWORD): BOOL; stdcall; SetupDiSetClassInstallParamsA:function(DeviceInfoSet: DWORD; DeviceInfoData: PSP_DEVINFO_DATA; ClassInstallParams: PSP_CLASSINSTALL_HEADER; ClassInstallParamsSize: DWORD): BOOL; stdcall; FLib: THandle; ...

для их использования - осуществим динамическое их подключение в компоненте

Function LinkProc(ProcName: string):Pointer; begin try result:= GetProcAddress(FLib,PChar(ProcName)); Win32Check(Assigned(Result)) except end end; ... CM_Get_Device_IDA:= LinkProc("CM_Get_Device_IDA"); SetupDiGetClassDevsA:= LinkProc("SetupDiGetClassDevsA"); SetupDiEnumDeviceInfo:= LinkProc("SetupDiEnumDeviceInfo"); SetupDiDestroyDeviceInfoList:= LinkProc("SetupDiDestroyDeviceInfoList"); CM_Get_Device_ID_Size:= LinkProc("CM_Get_Device_ID_Size"); SetupDiCallClassInstaller:= LinkProc("SetupDiCallClassInstaller"); SetupDiGetDeviceRegistryPropertyA:= LinkProc("SetupDiGetDeviceRegistryPropertyA"); SetupDiSetClassInstallParamsA:= LinkProc("SetupDiSetClassInstallParamsA"); ...

при создании компонента инициализируем опрос USB:

Var Info: TDevBroadcastDeviceInterface; //интерфейс- ... Info.dbcc_size:= SizeOf(DEV_BROADCAST_DEVICEINTERFACE); Info.dbcc_devicetype:= DBT_DEVTYP_DEVICEINTERFACE; Info.dbcc_classguid:= FClassGUID; FNotifyHandle:= RegisterDeviceNotification(FWnd,@Info,DEVICE_NOTIFY_WINDOW_HANDLE); // таймер на CountDiskEnum ftimer:= ttimer.Create(self); ftimer.Enabled:= false; ftimer.interval:= FPoolingInterval; ftimer.ontimer:= tmr; ftimer.Enabled:= true ...

Покажем на практике как это работает. Встроим компонент в уже готовую программу и в меню осуществим активацию режима "мини HASP" (см. рис.)


после того как флешка будет вставлена, наступает событие DBT_DEVICEARRIVAL

... //--- читаем очередь сообщений и отлавливаем момент подключения-съема USB procedure TDUSB.WndProc(var Msg:TMessage); begin with Msg do if (Msg=WM_DEVICECHANGE)and ((wParam=DBT_DEVICEARRIVAL)or(wParam=DBT_DEVICEREMOVECOMPLETE)) then try DoDeviceChange(wParam,PDevBroadcastDeviceInterface(lParam)); except end else Result:= DefWindowProc(FWnd,Msg,wParam,lParam) end; ...

производим считывание серийного номера, ID и GUID

Var VID,PID: Word; Serial,GUID: string; const USBNameMask="\\?\USB#Vid_%x&Pid_%x#%s#%s"; begin if (Device.dbcc_devicetype=DBT_DEVTYP_DEVICEINTERFACE)and Assigned(FOnChange) and ParseDeviceName(USBNameMask,PChar(@Device.dbcc_name), [@VID,@PID,@Serial,@GUID]) then case Event of DBT_DEVICEARRIVAL: FOnChange(Self,VID,PID,Serial,GUID,doInsert); DBT_DEVICEREMOVECOMPLETE: FOnChange(Self,VID,PID,Serial,GUID,doRemove) end end; ...


для того, чтобы программа знала о наличии нужного нам "девайса" в любой момент времени, а не только в момент съема, воспользуемся функцией SetupDiGetClassDevsA все той же библиотеки - setapi.dll

Procedure TDUSB.CountDiskEnum; // вызов по таймеру ftimer- const GUID_DEVCLASS_DISKDRIVE: TGUID = (D1: $4D36E967; D2: $E325; D3: $11CE; D4: ($BF, $C1, $08, $00, $2B, $E1, $03, $18)); var hDevInfoSet: HDEVINFO; DevInfo: SP_DEVINFO_DATA; i: Integer; s: string; pp: boolean; begin DevInfo.cbSize:= sizeof(SP_DEVINFO_DATA); hDevInfoSet:= SetupDiGetClassDevsA(@GUID_DEVCLASS_DISKDRIVE, nil, 0, 2); i:= 0; list.Clear; // обнуляем stringlist // if hDevInfoSet INVALID_HANDLE_VALUE then begin while (SetupDiEnumDeviceInfo(hDevInfoSet, i, @DevInfo)) do begin s:= GetDevName(DevInfo.DevInst); //фильтрация строки вида- //USBSTOR\DISK&VEN_KINGSTON&PROD_DATATRAVELER_2.0&REV_PMAP\5B661B004102&0 //USBSTOR\DISK&VEN_SAMSUNG&PROD_MIGHTY_DRIVE&REV_PMAP\07521094081F&0 if pos("USB",s)=1 then // наполняем список подключенных- list.Add(sel_ser(s)); Inc(i) end; SetupDiDestroyDeviceInfoList(hDevInfoSet) end; ...

введем алгоритм простейшей защиты на основе функции BlockInput из библиотеки - user32.dll

Procedure BlockInput; external "user32.dll"; ... //проверка на блокировку ПК- pp:= false; if (FActive)and(fblock"") then begin for i:= 0 to list.Count-1 do if list[i]= fblock then begin pp:= true; break end; if pp then UnBlock else block end; // FSerChange(Self,list) // возврат события компонента- ...

Полные исходные тексты компонента и тестовый монитор доступны по .


Рис. - Тестовый монитор USB
Рис. - Компонент мини HASP

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

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

  • Cайт Alladin http://www.alladin.ru
  • Dependency Walker из комплекта Visual C++ 6.0 http://ra-xp.narod.ru/zip/dll.zip
  • Модификация системы управления ПК http://ra-xp.narod.ru/zip/ram.zip
  • Компонент miniHASP for DELPHI и компиляция тестового проекта http://ra-xp.narod.ru/zip/hsp.zip

Контактная информация:

[email protected]

В этой статье описаны способы обхода аппаратных систем защиты. В качестве примера рассмотрена технология HASP (Hardware Against Software Piracy), разработанная компанией Aladdin Knowledge Systems Ltd. В прошлом данная технология являлась одной из самых популярных аппаратных систем защиты ПО.

Мощью аппаратной защиты HASP пользуются многие серьезные разработчики софта, которые не хотят, чтобы их продукт несанкционированно распространялся. Хаспом, например, защищаются пакеты «1С.Бухгалтерия» или «1С.Предприятие», без которых не может прожить ни одно более или менее организованное дело. Популярный юридический справочник «КонсультантПлюс» также защищает доступ к данным с помощью электронных ключиков. Чтобы воспользоваться вышеупомянутым или другим не менее дорогостоящим софтом, не платя никому ни копейки, недостаточно просто полазить по Сети в поисках txt’шника с ключиками. Однако хакер всегда разберется, что делать с защитой, пусть и аппаратной. И паяльник ему для этого не понадобится.

Взглянем

Утрируя, можно сказать, что HASP состоит из двух частей: аппаратной и программной. Аппаратная часть - это электронный ключик в виде USB-брелка, PCMCIA-карты, LTP-девайса или вообще внутренней PCI-карты. Установленный софт будет работать только на той машине, в которую воткнут электронный ключ. Собственно, неплохо было бы отучить софт от такой неприятной для кошелька привычки.

Программная часть - это драйвера электронного ключа и различный софт, привязывающий электронные ключи с их драйверами непосредственно к защищаемому продукту или к каким-то зашифрованным данным. В статье мы рассмотрим и обойдем защиту, использующую USB-брелок - наверное, наиболее популярный электронный ключ на сегодня.

Механизм системы защиты

Сам брелок нас почти не интересует, в отличие от ПО в его комплекте. Для нас наибольший интерес представляет модуль hardlock.sys. Не углубляясь в подробности, отмечу, что этот драйвер отвечает за взаимодействие с аппаратным ключом. Он имеет два объекта устройства, один из которых обладает символьным именем DeviceFNT0. Используя этот объект, защищенное приложение посредством диспетчера ввода-вывода проверяет лицензию на использование данного ПО.

Главным недостатком такой системы защиты является возможность перехвата вызовов диспетчера ввода-вывода и эмулирования аппаратного ключа. Существует также вариант разработки драйвера виртуального ключа, но это гораздо более сложная техническая задача, нежели перехват вызовов.
Как тебе известно, модель драйвера описывается в структуре DRIVER_OBJECT при загрузке модуля. Она хранит массив обработчиков сообщений. Причем никто не мешает переписать эти адреса и получить управление, выполнив наш код. Таким образом, можно перехватывать и подменять IRP-пакеты, подставляя лицензионные данные. Другими словами, имея дамп ключа защиты, можно передать его программе, проверяющей верность лицензионных данных!

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

Перехват и эмуляция

Как уже отмечалось, идея перехвата состоит в перезаписи обработчиков IRP-пакетов. Для этого необходимо иметь возможность изменять поля структуры DRIVER_OBJECT. К счастью, существует функция IoGetDevicePointer, которая возвращает указатель на объект вершины стека именованных устройств и указатель на соответствующий файловый объект. Вот фрагмент кода функции, устанавливающей ловушку:

UNICODE_STRING DeviceName;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;

RtlInitUnicodeString(&DeviceName, lpDevice);
IoGetDeviceObjectPointer(&DeviceName, 1u, &FileObject, &DeviceObject);

Получив указатель на структуру DEVICE_OBJECT, имеем указатель на DRIVER_OBJECT. Теперь заменим адреса обработчиков и функций выгрузки драйвера на свои:

NTSTATUS HookDevice(LPWSTR lpDevice)

gDriverObject = DeviceObject-> DriverObject;

gDeviceControl = gDriverObject-> MajorFunction;
gDriverObject-> MajorFunction = HookDispatch;

gInternalDeviceControl = gDriverObject-> MajorFunction;
gDriverObject-> MajorFunction = HookDispatch;

gDriverUnload = gDriverObject->DriverUnload;
gDriverObject->DriverUnload = HookUnload;

ObfDereferenceObject(FileObject);

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

Так как указатель на объект драйвера защиты сохранeн, то чтобы снять ловушку, нужно просто восстановить прежние обработчики IRP-пакетов:

void UnhookDevice(void)

gDriverObject-> MajorFunction = gDeviceControl;
gDriverObject-> MajorFunction = gInternalDeviceControl;
gDriverObject->DriverUnload = gDriverUnload;

Конечно, надо добавить соответствующие проверки на валидность указателей и прочее.

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

void HookUnload(PDRIVER_OBJECT DrvObj)

UnhookDevice();
gDriverUnload(DrvObj);

Здесь происходит восстановление полей структуры DRIVER_OBJECT, и передаeтся управление на оригинальный код выгрузки драйвера перехваченного устройства.

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

Принцип работы эмулятора

Перехватчик

Зная основные принципы простейшего перехвата IRP-пакетов, приступим к реализации пока только самого перехватчика для дальнейшего анализа. Для этого создадим объект драйвера, который содержит символьное имя (например DosDevicesHook) и точки входа CREATE, CLOSE, READ.

IoCreateDevice(DriverObject, 0, &usDeviceName, FILE_DEVICE_NULL, 0, 0, &pDeviceObject);
IoCreateSymbolicLink(&usSymbolicDeviceName, &usDeviceName);

DriverObject->MajorFunction = DriverDispatch;
DriverObject->MajorFunction = DriverDispatch;
DriverObject->MajorFunction = DriverDispatch;
DriverObject->DriverUnload = DriverUnload;

Это нужно для того, чтобы работать с нашим перехватчиком как с файлом, используя функции CreateFileReadFileCloseHandle. При такой реализации обмена данными между приложением и перехватчиком невозможно сразу же отправить их пользовательской программе, поэтому необходимо создать некоторую структуру для хранения необходимых данных о пойманном пакете. Например односвязный список, как это реализовано мной. Теперь следует определиться, какую информацию нужно буферизировать. Это общая информация о пакете (тип, флаги, прочее) и, конечно, буферы. Также можно добавить время перехвата. При копировании содержимого буферов нужно помнить об их типе, иначе - крах. Забегая вперед, отмечу, что драйвер защиты использует буферизированный ввод-вывод, это немного упрощает код.

Код HookDispatch

if (idlTail->IrpData.InputLength)
{
idlTail->InputBuffer = ExAllocatePool(NonPagedPool, idlTail->IrpData.InputLength);
RtlCopyMemory(idlTail->InputBuffer, Irp->AssociatedIrp.SystemBuffer, idlTail->IrpData.InputLength);
}

if (IoSL->MajorFunction == IRP_MJ_DEVICE_CONTROL)
Status = pHookedDriverDispatch(DeviceObject, Irp);

if (idlTail->IrpData.OutputLength)
{
idlTail->OutputBuffer = ExAllocatePool(NonPagedPool, idlTail-> IrpData.OutputLength);
RtlCopyMemory(idlTail->OutputBuffer, lpBuffer, idlTail->IrpData.OutputLength);
}

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

Код DriverDispatch

Length = IoSL->Parameters.Read.Length;
if (Length == sizeof(IRP_DATA) && idlHead)
RtlCopyMemory(Irp->UserBuffer, &idlHead->IrpData, Length);
else if (idlHead && Length == (idlHead-> IrpData.InputLength + idlHead-> IrpData.OutputLength))
{
RtlCopyMemory(Irp->UserBuffer, idlHead-> InputBuffer, idlHead->IrpData.InputLength);
RtlCopyMemory((PVOID)((ULONG)Irp->UserBuffer + idlHead->IrpData.InputLength), idlHead-> OutputBuffer, idlHead->IrpData.OutputLength);
}
else if (Length == 1 && idlHead)
{
if (idlHead->InputBuffer)
ExFreePool(idlHead->InputBuffer);
if (idlHead->OutputBuffer)
ExFreePool(idlHead->OutputBuffer);

idlTemp = idlHead->ldlNext;
ExFreePool(idlHead);
idlHead = idlTemp;
if (!idlTemp)
idlTail = NULL;
}

Когда перехватчик готов, запускаем сначала его, а затем - защищенное приложение с ключами и без. Из полученных логов становится видно, какие управляющие коды посылаются и их результаты. Также можно видеть, что запросы и ответы на два различных кода (9c402450, 9c4024a0) не изменяются. Казалось бы, можно построить табличный эмулятор, но после серии запусков убеждаемся, что это невозможно, так как содержимое буферов различно, и неизвестно, как оно образуется.

Перехваченные пакеты без ключа

Перехваченные пакеты с ключом

Затем возможны несколько вариантов дальнейших действий:

  • изучать дебри драйвера защиты;
  • воспользоваться информацией самих разработчиков системы.

Оба варианта дают необходимую информацию. Итак, оказывается, содержимое пакетов шифруется публичным симметричным алгоритмом AES (Advanced Encryption Standard). Логичной целью является получение ключа шифрования.

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

Пример дампа ключа

Поэтому первое, что нужно сделать, это получить ключ. Поставленную задачу может решить обычный брутфорс:

unsigned short Key;
unsigned char RefKey, VerKey;

for (Key = 0; Key <= 0x7fff, Key++)
{
if (!HL_LOGIN(Key, 1, RefKey, VerKey))
{
HL_LOGOUT();
Break;
}
}

Функции HL_LOGIN, HL_LOGOUT доступны из HASP SDK для разработчиков приложений, защищенных на этой платформе, и имеют следующие прототипы:

WORD HL_LOGIN(WORD ModAd, Word Access, Byte *RefKey, Byt *VerKey);
WORD HL_LOGOUT(void);

Первая функция служит для открытия сессии работы с ключом защиты посредством драйвера, вторая – завершает сессию. Это прототипы старых версий HASP SDK, но работают они и с новыми типами ключей, так как разработчики обеспечили обратную совместимость.

Новый API мало отличается от старого, и это никак не сказывается на принципе работы брутфорса. Подробную документацию Hasp API, готовые реализации брутфорса и дампера ключей можно найти на .

Обработчик

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

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

NTSTATUS HookDispatch():

PIO_STACK_LOCATION Stack = Irp-> Tail.Overlay.CurrentStackLocation;
ULONG IoControlCode;
if (Stack->MajorFunction == 14)
{
IoControlCode = Stack.DeviceIoControl.IoControlCode;
If (IoControlCode != 0x9c402458)
{
Return gDeviceControl(DeviceObject, Irp);
}
else
{
Encrypt(Irp->AssociatedIrp.SystemBuffer);
Crypt(Irp->AssociatedIrp.SystemBuffer, Key, DumpMemory);
}
}

Return STATUS_FAILED;

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

Код Encrypt()

void Encrypt(BYTE * Buffer)
{
WORD Seed = ((WORD )Buffer + 0x5e);
WORD Ver = ((WORD )Buffer + 0xba);

if (Ver)
{
for (int i = 0; i < 0xB9; i++) {
(WORD )(Buffer + i) += Seed;
Seed = (Seed >> 15) | (Seed << 1);
Seed -= (WORD )(Buffer + i) ^ i;
}

for (int i = 0xBE; i < 0xFF; i++) {
(WORD )(Buffer + i) -= Seed;
Seed = (Seed >> 15) | (Seed << 1);
Seed += (WORD )(Buffer + i) ^ i;
}

((WORD )Buffer + 0xba) = Seed;
}
}

Видно, что алгоритм гораздо сложнее, чем обычный сдвиг и исключающее «или». А вот алгоритм дешифрования:

Код Decrypt()

void Decrypt(BYTE* Buffer)
{
WORD Seed = ((WORD )Buffer + 0x5e);
WORD Ver = ((WORD )Buffer + 0xba);

if (Ver) {
for (int i = 0xFE; i > 0xBD; i—) {
Seed -= (WORD )(Buffer + i) ^ i;
Seed = (Seed << 15) | (Seed >> 1);
(WORD )(Buffer + i) += Seed;
}

for (int i = 0xB8; i >= 0; i—) {
Seed += (WORD )(Buffer + i) ^ i;
Seed = (Seed << 15) | (Seed >> 1);
(WORD )(Buffer + i) -= Seed;
}

((WORD )Buffer + 0xba) = Seed;
}
}

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

В заключение отмечу, что построение табличного эмулятора, основанного на перехвате DeviceIoControl, - достаточно трудная задача. Но такой принцип эмулятора можно использовать и на другом уровне взаимодействия: создать виртуальную USB-шину.

Заключение

Это не единственный способ избавиться от системы защиты. Существуют и другие, более совершенные методы. Изложенные в статье принципы можно использовать и для анализа работы драйверов, перехватывая IRP-пакеты. Таким образом можно добавить неплохой инструмент в свой сделанный на коленке набор. Удачи!




Top