Слайд 1Защищенные вычисления (SenseLock), Аппаратные ключи типа HASP. Принципы работы. Принципы
взлома. Примеры
Слайд 2ЗАЩИЩЕННЫЕ ВЫЧИСЛЕНИЯ
Задачу конфиденциальных вычислений, которая решается посредством многостороннего интерактивного протокола
можно описать в следующей постановке. Имеется n участников протокола или n процессоров
вычислительной системы, соединенных сетью связи. Изначально каждому процессору известна своя "часть" некоторого входного значения x. Требуется вычислить f(x), f некоторая известная всем участникам вычислимая функция, таким образом, чтобы выполнились следующие требования:
корректности
конфиденциальности
Слайд 3Вынесенные вычисления
Суть вынесенных вычислений заключается в проведении вычислений в доверенной
среде, оболочке - электронном ключе или безопасном месте пространства программы.
Слайд 4Где это нужно
Обеспечение безопасности вычислений в автоматизированных системах(большинство ЭВМ, военная
техника, промышленные установки, космическая отрасль).
Выпуск носителей с лицензионной информацией,
информацией, защищенной авторскими правами(борьба с пиратством).
Слайд 5Электронные ключи
Электронный ключ - это небольшое устройство, подсоединяемое к компьютеру и
используемое для защиты программного обеспечения от несанкционированного использования. Основная функциональность
состоит в хранении небольшого количества данных и преобразования данных по неизменяемому встроенному алгоритму.
Слайд 6SENselock.
Основой ключей SenseLock служит микропроцессор, построенный на базе многослойного высокозащищенного
ядра компании Philips, используемого при производстве современных банковских смарт-карт, имеющий
сертификат безопасности EAL5+.
Слайд 7Процессор senselock
Процессор имеет внутри себя все необходимые компоненты, такие как:
встроенный
USB интерфейс;
EEPROM емкостью от 32 до 64 килобайт памяти;
RAM;
ROM (c
операционной системой ключа);
Математический сопроцессор;
Средства противодействия физическому взлому;
Встроенный тактовый генератор.
Слайд 8Память Senselock
Память ключа выполнена в виде файловой системы, работающей с
папками и файлами. Сами файлы могут быть трех видов:
исполняемый модуль
(часть программы перенесенной в ключ);
файл данных;
файл с ключами RSA.
Каталоги файловой системы защищены специальным PIN кодом для контроля доступа к ним.
Слайд 9Основные возможности
Основные возможности
Возможность выполнения внутри электронного ключа программ, написанных на
стандартном языке "Си".
Встроенные в электронный ключ аппаратные алгоритмы шифрования RSA-1024,
DES, TripleDES, а также алгоритм хэширования данных SHA-1.
Возможность работы в режиме HID-устройства без использования каких-либо дополнительных драйверов.
Встроенные часы реального времени (модели SenseLock EL-RTC и SenseLock EL-NET RTC) могут быть использованы для ограничения времени работы программы. Таймер не может быть изменен и надежно защищен от любых (программных и аппаратных) попыток воздействия на него.
Самостоятельная установка разработчиком числа пользователей (от 1 до 255) в сетевых версиях электронного ключа (модели SenseLock EL-NET и SenseLock EL-NET RTC) без какой-либо дополнительной оплаты.
Слайд 10Принцип работы
Фактически, разработчик программного обеспечения самостоятельно создает "черный ящик" со
своими собственными алгоритмами, которые будут уникальны только для его программы.
Например,
созданная программа вычисляет по уникальному алгоритму силы поверхностного натяжения жидкостей в зависимости от изменения их вязкости. Разработчик переносит часть кода, выполняющего все расчеты, в электронный ключ, а вместо него вставляет вызов функции электронного ключа, которой передаются параметры для рассчетов и получаются результаты выполнения. Таким образом, решаются сразу две проблемы: сама программа надежно защищена от копирования, а использованный в ней алгоритм не менее надежно защищен от изучения и клонирования конкурентами.
Слайд 12Защита от физического взлома
Противодействие физическому взлому, кристалла спроектированного изготовителем:
Детекторы пониженного
и повышенного напряжения питания, тактовой частоты, температуры;
Самотестирование топологии кристалла;
Очистка RAM
при сбросе или срабатывании детекторов;
Защита от высокочастотных помех;
Генератор случайных тактов ожидания;
Шифрование внутренних шин;
Прозрачное шифрование RAM, ROM, EEPROM;
Аппаратная защита чтения областей ROM, EEPROM, РRОM;
Защита от использования в нештатных режимах работы;
Шифрование или скремблирование внутренних RAM и EEPROM.
Слайд 13HASP
HASP - мультиплатформенная аппаратно-программная система защиты программ и данных от
нелегального использования и несанкционированного распространения, разработанная компанией Aladdin Knowledge Systems
Ltd. Основой ключей HASP является специализированная заказная микросхема - ASIC (Application Specific Integrated Circuit), имеющая уникальный для каждого ключа алгоритм работы.
Слайд 14Защита HASP включает в себя:
электронный ключ HASP;
специальное программное обеспечение для «привязки» к электронному
ключу, защиты приложений и для кодирования данных;
схемы и методы защиты
программ и данных, обнаружения и борьбы с отладчиками, контроля целостности программного кода и данных.
Слайд 15Программа
Запрос
Ответ
Обработка
Как работает HASP
( Hardware Against Software Piracy )
Принцип защиты состоит
в том, что в процессе выполнения защищённая программа опрашивает подключённый
к компьютеру ключ HASP.
Слайд 16Взлом HAsP
Существуют средства обхода аппаратной защиты — битхак (например Sable) или
программное эмулирование как самого ключа, так и, например, USB-шины с
виртуальным ключом.
Слайд 17С программной начинки ключа снимается дамп, который потом используется для
симуляции присутствия.
Обработка
Программа
Программа
снятия
дампа
Программа
восстановления
Hasp Emulator PE
Как взломать HASP
Слайд 18ПрИмер. перехват и эмуляция
Фрагмент кода функции, устанавливающей ловушку:
NTSTATUS HookDevice(LPWSTR lpDevice)
UNICODE_STRING
DeviceName;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
RtlInitUnicodeString(&DeviceName, lpDevice);
IoGetDeviceObjectPointer(&DeviceName, 1u, &FileObject, &DeviceObject);
Заменим адреса обработчиков и
функций выгрузки драйвера на свои:
NTSTATUS HookDevice(LPWSTR lpDevice)
gDriverObject = DeviceObject-> DriverObject;
gDeviceControl = gDriverObject-> MajorFunction[IRP_MJ_DEVICE_CONTROL];
gDriverObject-> MajorFunction[IRP_MJ_DEVICE_CONTROL] = HookDispatch;
gInternalDeviceControl = gDriverObject-> MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL];
gDriverObject-> MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HookDispatch;
gDriverUnload = gDriverObject->DriverUnload;
gDriverObject->DriverUnload = HookUnload;
ObfDereferenceObject(FileObject);
Чтобы снять ловушку, нужно просто восстановить прежние обработчики IRP-пакетов:
void UnhookDevice(void)
gDriverObject-> MajorFunction[IRP_MJ_DEVICE_CONTROL] = gDeviceControl;
gDriverObject-> MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = gInternalDeviceControl;
gDriverObject->DriverUnload = gDriverUnload;
Реализуем правильную выгрузку драйверов.
void HookUnload(PDRIVER_OBJECT DrvObj)
UnhookDevice();
gDriverUnload(DrvObj);
Слайд 20Перехватчик
Создадим объект драйвера, который содержит символьное имя (например \DosDevices\Hook) и
точки входа CREATE, CLOSE, READ.
IoCreateDevice(DriverObject, 0, &usDeviceName, FILE_DEVICE_NULL, 0, 0,
&pDeviceObject);
IoCreateSymbolicLink(&usSymbolicDeviceName, &usDeviceName);
DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverDispatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverDispatch;
DriverObject->MajorFunction[IRP_MJ_READ] = DriverDispatch;
DriverObject->DriverUnload = DriverUnload;
Код 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[IRP_MJ_DEVICE_CONTROL]( 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;
}
Слайд 24Брутфорс(полный перебор):
unsigned short Key;
unsigned char RefKey[8], VerKey[8];
for (Key = 0;
Key
{
HL_LOGOUT();
Break;
}
}
return Key;
Прототипы функций HL_LOGIN, HL_LOGOUT:
WORD HL_LOGIN(WORD ModAd, Word Access, Byte *RefKey, Byt *VerKey);
WORD HL_LOGOUT(void);
Слайд 25Обработчик
Логика перехватчика будет иметь такой вид:
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;
}
}
Слайд 26Код 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;
}
}
Слайд 27ЛИТература
http://open-security.org/bezopasnostj_po_ks/
http://senselock.ru
http://softwaresecurity.org/forum
http://www.xakep.ru/post/57901/