оментах.
В первом случае может понадобиться разрабатывать достаточно сложную систему с целью эмуляции генератора отчета. Это очень труднореализуемо. В каком-то смысле придется повторить большую часть функциональности АРМ студента. Так, если в отчете будут храниться вопросы, которые были заданы студенту, то, фактически, придется работать с этой базой вопросов и случайно выбирать из них. В противном случае, если использовать строго определенный набор, то у всех, кто воспользуется такой системой взлома, будут совпадать отчеты. Это может привести к подозрению со стороны преподавателя. Таким образом, в грамотно и сложно организованной АСДО этот подход практически не применим.
Остался второй путь, заключающийся в генерации обратного алгоритма. Здесь на пути и встает многовариантность кода. Невозможно применить маску с целью поиска функциональных блоков, а следовательно, и просто их выделить. Можно только написать высокоинтеллектуальный анализатор кода, который превратит алгоритм в псевдокод, а уже затем по нему построит обратный. Это очень сложная задача. Причем, для написания такой программы придется досконально изучить код виртуальной машины. В том случае, когда исходные коды отсутствуют, все это может превратиться в непосильную задачу. Точнее сказать, в слишком дорогой в своей реализации, и доступной в написании только высококвалифицированному специалисту.
Если кто-то реализует второй вариант программы, то небольшого расширения базы блоков в исходных кодах будет достаточно, чтобы всю работу понадобилось проделать заново.
На мой взгляд, созданная система достаточно сложна в плане анализа и может эффективно помочь защищать АСДО и другие программы от несанкционированных действий.
3.3. Особенности реализации модуля защиты
Разрабатываемый модуль защиты Uniprot будет представлять собой файл типа dynamic link library (DLL) с именем Uniprot.dll.
Для организации взаимодействия модуль защиты предоставляет набор интерфейсов с использованием технологии COM. Для описания интерфейсов используется специальный язык - IDL, по своей структуре очень похожий на С++. В определении интерфейса описываются заголовки входящих в него функций с указанием их имен, возвращаемых типов, входных и выходных параметров, а также их типов. Подробно с предоставляемыми интерфейсами можно будет ознакомиться в разделе 4.2. Интерфейсы, описанные в IDL файле, преобразуются IDL-компилятором (MIDL.EXE) в двоичный формат и записываются в файл с расширением TLB, который называется библиотекой типов. Этот файл будет необходим, например, для использования модуля Uniprot.dll из среды Visual Basic. С процессом подключения TLB файлов в Visual Basic можно ознакомиться в разделе 4.4.2.
Для регистрации модуля в системе необходимо вызвать в нем функцию DllRegisterServer, которая внесет нужные изменения в реестр. Для этих целей можно воспользоваться утилитой regsvr32.exe. Она поставляется вместе с операционной системой, а потому должна находиться на любой машине. Regsvr32 должна загрузить СОМ-сервер и вызвать в нем функцию DllRegisterServer, которая внесет нужные изменения в реестр.
Организация работы с зашифрованными файлами строится на основе механизмов дескрипторов (или описателей файла). Каждому открытому или созданному файлу назначается уникальный (в рамках данного процесса) идентификатор, представляющий собой число в формате short. Этот идентификатор возвращается вызывающей программе, после чего она может проводить над этим файлом набор операций. Все номера открытых файлов хранятся во внутренней таблице модуля, и каждому из них соответствует структура данных, необходимая для работы с ним. В частности, там хранится текущая позиция для чтения данных, алгоритм для шифрования/расшифрования данных. Когда работа с файлом закончена, программа должна закрыть файл с соответствующим идентификатором. Он будет удален из таблицы, и в следующий раз тот же самый идентификатор может послужить для работы с другим файлом. Если файл не будет закрыт, то после завершения программы, использующей модуль защиты, файл будет поврежден, и работа с ним в дальнейшем будет невозможна.
3.4. Защита исполняемых файлов
Одним из средств, входящих в комплект разрабатываемой системы должна стать программа для защиты их от модификации. Было принято решение использовать уже имеющиеся механизмы шифрования, основанные на полиморфный алгоритмах. О преимуществах такого метода говорилось ранее. Во- первых, это большая сложность создания универсального взломщика, а, во-вторых, возможность запрещения запуска программ без наличия соответствующего файла с алгоритмом расшифрования.
Разработанная программа имеет два возможных режима запуска. Первый - для генерации зашифрованного файла из указанного исполняемого модуля. Второй -для запуска защищенного модуля. Рассмотрим шаги, которые выполняет механизм шифрования исходного файла.
1. Инициализация библиотеки Uniprot.
2. Чтение исполняемого файла в память.
3. Запуск исполняемого файла с флагом остановки. То есть программа загружается, но управления не получает.
4. Чтение частей загруженной программы и поиск ее соответствующих частей в прочитанном файле. Найденные части кода сохраняются отдельно. После чего их места в буфере с прочитанным файлом заменяются случайными значениями.
5. Генерация алгоритма шифрования и расшифрования.
6. Запись в зашифрованный файл буфера с прочитанным, а затем измененным файлом. В этот же файл пишутся выделенные фрагменты кода.
7. Удаление файла шифрования, так как он более не предоставляет интереса.
Теперь рассмотрим шаги, которые выполняет механизм запускающий зашифрованный файл на исполнение.
1. Поиск соответствующего файла с алгоритмом расшифрования.
2. Создание временного исполняемого файла и запись в него "испорченного" файла (см. механизм шифрования, пункт 4).
3. Запуск "испорченного" исполняемого файла с флагом остановки. То есть программа загружается, но управления не получает.
4. Восстановление "испорченных" мест в памяти. Изначальный код для исправления также хранится в зашифрованном файле.
5. Передача управления расшифрованному файлу.
6. Ожидание окончания выполнения запущенной программы.
7. Удаление временного файла.
Как видно из описания, данная программа достаточна проста в своем устройстве и достаточна эффективна.
ГЛАВА 4. ПРИМЕНЕНИЕ СИСТЕМЫ ЗАЩИТЫ
4.1. Состав библиотеки Uniprot
В состав библиотеки входят следующие компоненты:
1. Исходные тексты COM модуля Uniprot.dll.
2. Исходные тексты программы ProtectEXE.exe.
3. Отдельно собранные файлы, необходимые для подключения Uniprot.dll. Этими файлами являются: export.cpp, export.h, Uniprot.tlb.
4. Файл reg_uniprot.bat для регистрации COM модуля Uniprot.dll.
5. Руководство программиста по использованию модуля Uniprot.dll.
6. Руководство программиста по использованию программы ProtectEXE.exe.
7. Набор примеров написанных на Visual Basic, демонстрирующих работу с библиотекой Uniprot.
4.2. Руководство программиста по использованию модуля Uniprot.dll
Вначале опишем вспомогательный тип CreateMode, используемый в методе Create. Он описывает тип создаваемого зашифрованного файла. В данной версии модуля Uniprot он может иметь два значения: DEFAULT и DISABLE_ARC. Первый из них сообщает функции, что будет создан обыкновенный зашифрованный файл. Данные в нем будут вначале упакованы библиотекой zlib, а затем уже зашифрованы. Это может дать существенный выигрыш в плане уменьшения размера выходного файла, например, на картинках в формате BMP или простом тексте. Использование DISABLE_ARC приведет к созданию зашифрованного, но не сжатого файла. Это даст выигрыш по времени при распаковке и упаковке, но не уменьшит размер зашифрованного файла. Это также может быть полезно при шифровании уже сжатых файлов. Примером могут являться картинки в формате JPG.
enum CreateMode
{
DEFAULT = 0,
DISABLE_ARC = 1
} CreateMode;
Теперь опишем функции, предоставляемые интерфейсом IProtect. В этот интерфейс собраны функции общего плана и генерации файлов с полиморфными алгоритмами шифрование и расшифрования.
interface IProtect : IDispatch
{
[id(1), helpstring("method GetInfo")]
HRESULT GetInfo(
[out] short *version, [out] BSTR *info);
[id(2), helpstring("method Generate UPT files")]
HRESULT GenerateUPTfiles(
[in] BSTR algorithmCryptFileName,
[in] BSTR algorithmDecryptFileName);
[id(3), helpstring("method Generate Time Limit UPT files")]
HRESULT GenerateTimeLimitUPTfiles(
[in] BSTR algorithmCryptFileName,
[in] BSTR algorithmDecryptFileName,
[in] long LimitDays);
[id(4), helpstring("method Generate Time Limit UPT files")]
HRESULT GenerateTimeLimitUPTfiles2(
[in] BSTR algorithmCryptFileName,
[in] BSTR algorithmDecryptFileName,
[in] long LimitDaysCrypt,
[in] long LimitDaysDecrypt);
};
Теперь опишем каждую из функций интерфейса IProtect.
HRESULT GetInfo([out] short *version, [out] BSTR *info);
Функция GetInfo возвращает строку с краткой информации о данном модуле и его версии. Может быть использована для получения рядя сведений о модуле. Например, имя автора и год создания. Версия хранится в виде числа следующим образом: 0x0100 - версия 1.00, 0x0101 - версия 1.01, 0x0234 - версия 2.34 и так далее.
Описание используемых параметров:
version - сюда будет занесена версия модуля.
info - сюда будет занесена строка с краткой информацией о модуле.
HRESULT GenerateUPTfiles(
[in] BSTR algorithmCryptFileName,
[in] BSTR algorithmDecryptFileName);
Функция GenerateUPTfiles генерирует два файла-ключа. Они представляют собой сгенерированные полиморфным генератором алгоритмы шифрования и расшифрования. При этом расшифровать зашифрованный файл можно только соответствующим алгоритмом расшифрования. Генерируемая пара ключей на практике уникальна. Вероятность генерации двух одинаковых пар составляет: (2^32*3)^5 3.5*10^50. Где 2^32 - случайно используемая константа для шифрования. 3 - количество возможных операций над числом. 5 - максимальное количество проходов для шифрования.
Описание используемых параметров:
algorithmCryptFileName - имя выходного файла с алгоритмом шифрования.
algorithmDecryptFileName - имя выходного файла с алгоритмом расшифрования.
HRESULT GenerateTimeLimitUPTfiles(
[in] BSTR algorithmCryptFileName,
[in] BSTR algorithmDecryptFileName,
[in] long LimitDays);
Функция GenerateTimeLimitUPTfiles генерирует два файла-ключа, ограниченных в использовании по времени. В целом функция эквивалентна GenerateUPTfiles, но генерируемые ею алгоритмы имеют дополнительное свойство. Их использование ограничено определенным временем. Количество дней, в течении которых они будут работать, указывается в третьем параметре LimitDays. Отсчет начинается с текущего дня. Это может быть полезно, например, для ограничения срока использования проектов. Естественна защита сама по себе ненадежна, так как невозможно защититься от перевода часов на компьютере или модификации кода модуля защиты с целью удаления соответствующих проверок. Но тем не менее это может дать дополнительные свойства защищенности, по крайней мере от рядовых пользователей.
Описание используемых параметров:
algorithmCryptFileName - имя выходного файла с алгоритмом шифрования.
algorithmDecryptFileName - имя выходного файла с алгоритмом расшифрования.
LimitDays - количество дней, в течении которых будут функционировать сгенерированные алгоритмы.
HRESULT GenerateTimeLimitUPTfiles2(
[in] BSTR algorithmCryptFileName,
[in] BSTR algorithmDecryptFileName,
[in] long LimitDaysCrypt,
[in] long LimitDaysDecrypt);
Функция GenerateTimeLimitUPTfiles2 генерирует два файла-ключа, ограниченных в использовании по времени. В отличие от функции GenerateTimeLimitUPTfiles, время ограничения использования алгоритма шифрования и расшифрования задается не общее, а индивидуальное.
Описание используемых параметров:
algorithmCryptFileName - имя выходного файла с алгоритмом шифрования.
algorithmDecryptFileName - имя выходного файла с алгоритмом расшифрования.
LimitDaysCrypt - количество дней, в течении которых будут функционировать сгенерированный алгоритм шифрования.
LimitDaysDecrypt - количество дней, в течении которых будут функционировать сгенерированный алгоритм расшифрования.
Следующий предоставляемый модулем защиты интерфейс имеет имя IProtectFile. В нем собраны функции работы с зашифрованными файлами, такие как создание зашифрованного файла, запись в него, чтение и так далее. Идеология работы с зашифрованными файлами построена на дескрипторах. При создании или открытии зашифрованного файла ему в соответствие ставится дескриптор, с использованием которого в дальнейшем и ведется работа с файлом.
interface IProtectFile : IDispatch
{
[id(1), helpstring("method Create New File")]
HRESULT Create(
[in] BSTR name,
[in] CreateMode mode,
[in] BSTR uptFileNameForWrite,
[out, retval] short *handle);
[id(2), helpstring("method Open File")]
HRESULT Open(
[in] BSTR name,
[in] BSTR uptFileNameForRead,
[in] BSTR uptFileNameForWrite,
[out, retval] short *handle);
[id(3), helpstring("method Close File")]
HRESULT Close(
[in] short handle);
[id(4), helpstring("method Write To File")]
HRESULT Write(
[in] short handle,
[in] VARIANT buffer,
[out, retval] long *written);
[id(5), helpstring("method Read From File")]
HRESULT Read(
[in] short handle,
[out] VARIANT *buffer,
[out, retval] long *read);
[id(6), helpstring("method Write String To File")]
HRESULT WriteString(
[in] short handle,
[in] BSTR buffer,
[out, retval] long *written);
[id(7), helpstring("method Read String From File")]
HRESULT ReadString(
[in] short handle,
[out] BSTR *buffer,
[out, retval] long *read);
[id(8), helpstring("method From File")]
HRESULT FromFile(
[in] short handle,
[in] BSTR FileName,
[out, retval] long *read);
[id(9), helpstring("method To File")]
HRESULT ToFile(
[in] short handle,
[in] BSTR FileName,
[out, retval] long *written);
};
Опишем функции в данном интерфейсе.
HRESULT Create(
[in] BSTR name,
[in] CreateMode mode,
[in] BSTR uptFileNameForWrite,
[out, retval] short *handle);
Функция Create служит для создания новых зашифрованных файлов. Поскольку во вновь созданный файл можно только писать, то функции необходим для работы только файл с алгоритмом шифрования. Имя файла с этим алгоритмом передается третьим параметром и является обязательным. Параметр mode имеет тип CreateMode, для чего он служит, было сказано ранее. При успешном создании файл, в handle возвращается его дескриптор. По окончании работы с файлом, его обязательно нужно закрыть, используя функцию Close.
Описание используемых параметров:
name - имя создаваемого файла.
mode - тип создаваемого файла (см. ранее описание типа CreateMode)
uptFileNameForWrite - имя файла с алгоритмом шифрования.
handle - возвращаемый дескриптор созданного файла.
HRESULT Open(
[in] BSTR name,
[in] BSTR uptFileNameForRead,
[in] BSTR uptFileNameForWrite,
[out, retval] short *handle);
Функция Open открывает уже ранее созданный зашифрованный файл. Файл может быть открыт как для чтения так и для записи. После чего производить с ним можно только одну из двух операций - чтение или запись данных. Это обусловлено тем, что записи в файле представляют собой блоки различного размера. Данная особенность является следствием необходимости хранения такого типа данных, как VARIANT. Таким образом, запись к данным в файле может быть только последовательная. И если после открытия файла произвести в него запись, то прочитать старые данные из него будет уже невозможно. Можно сказать, что открытие файла для записи эквивалентно его созданию, за парой исключений. Первое исключение состоит в том, что при открытии файла не указывается его тип. То есть нет необходимости указывать, следует паковать данные перед шифрованием или нет. Информация о типе берется из уже существующего файла. Второе состоит в том, что для открытия файла, в отличии от создания, обязательно необходим файл с алгоритмом расшифрования. Режим открытия файла зависит от того, указан ли файл с алгоритмом шифрования. Имя файла с алгоритмом расшифрования является обязательным параметром. Файл с алгоритмом расшифрования - нет. Если он не будет указан, то из такого файла возможно будет только чтение. Если указан, то будет возможно как чтение, так и запись. При успешном открытии файла в handle возвращается дескриптор этого файла. По окончании работы с файлом его обязательно нужно закрыть, используя функцию Close.
Описание используемых параметров:
name - имя открываемого файла.
uptFileNameForRead - имя файла с алгоритмом расшифрования.
uptFileNameForWrite - имя файла с алгоритмом шифрования.
handle - возвращаемый дескриптор открытого файла.
HRESULT Close(
[in] short handle);
Функция Close закрывает ранее созданный или отрытый файл. Если программа при своей работе создаст новый зашифрованный файл или откроет уже существующий файл для записи, но не вызовет функцию Close до своего завершения, но файл будет поврежден. После закрытия файла дескриптор становится поврежденным и его более нельзя использовать в качестве параметра для других функций.
Описание используемых параметров:
handle - дескриптор закрываемого файла.
HRESULT Write(
[in] short handle,
[in] VARIANT buffer,
[out, retval] long *written);
Функция Write производит запись в файл данных, переданных в переменной типа VARIANT. Запись производится в файл связанный с дескриптором, передаваемый в параметре handle. В возвращаемом значении written после завершения работы функции, будет указано количество байт записанных в файл.
Поскольку при разработке модуля защиты изначально был заложен принцип возможности использования его в программах, написанных на различных языках, то немаловажным вопросом является программный интерфейс. Именно по этой причине и был выбран типа VARIANT.
Тип VARIANT предназначен для представления значений, которые могут динамически изменять свой тип. Если любой другой тип переменной зафиксирован, то в переменные VARIANT можно вносить переменные разных форматов. Шире всего VARIANT применяется в случаях, когда фактический тип данных изменяется или неизвестен в момент компиляции. Переменным типа VARIANT можно присваивать любые значения любых целых, действительных, строковых и булевых типов. Для совместимости с другими языками программирования предусмотрена также возможность присвоения этим переменным значений даты/времени. Кроме того, вариантные переменные могут содержать массивы переменной длины и размерности с элементами указанных типов. Все целые, действительные, строковые, символьные и булевы типы совместимы с типом VARIANT в отношении операции присваивания. Вариантные переменные можно сочетать в выражениях с целыми, действительными, строковыми, символьными и булевыми. При этом, например, все необходимые преобразования Delphi выполняет автоматически.
Правда, сразу оговоримся, что передавать модулю защиты в переменных VARIANT можно не совсем все что угодно. Например, нельзя передать адрес на COM интерфейс, что логичною, так как неясно, как подобные данные интерпретировать.
Описание используемых параметров:
handle - дескриптор файла для записи.
buffer - записываемое значение.
written - возвращает размер записанных данных в байтах.
HRESULT Read(
[in] short handle,
[out] VARIANT *buffer,
[out, retval] long *read);
Функция Read читает из файла данные и возвращает их в виде переменной типа VARIANT. Чтение производится из файла связанного с дескриптором, передаваемого в параметре handle. В возвращаемом значении read после завершения работы функции будет указано количество прочитанных из файла байт.
Описание используемых параметров:
handle - дескриптор файла для чтения.
buffer - возвращаемые данные.
read - возвращает размер прочитанных данных в байтах.
HRESULT WriteString(
[in] short handle,
[in] BSTR buffer,
[out, retval] long *written);
Функция WriteString служит для записи в зашифрованный файл строки. Отметим, что строку можно записать, используя функцию Write, так как тип VARIANT позволяет хранить строки. Эта функция заведена для большего удобства, так как строковый тип широко распространен. По крайней мере, как показала практика, он очень часто встречается в системах обучения и тестирования.
Описание используемых параметров:
handle - дескриптор файла для записи.
buffer - записываемая строка.
written - возвращает размер записанных данных в байтах.
HRESULT ReadString(
[in] short handle,
[out] BSTR *buffer,
[out, retval] long *read);
Функция ReadString служит для чтения строки из зашифрованного файла.
Описание используемых параметров:
handle - дескриптор файла для чтения.
buffer - возвращаемая строка.
read - возвращает размер прочитанных данных в байтах.
HRESULT FromFile(
[in] short handle,
[in] BSTR FileName,
[out, retval] long *read);
Функция FromFile позволяет записать в зашифрованный файл данные, прочитанные из другого файла. Иначе говоря, данная функция сохраняет целиком произвольный файл в зашифрованном файле. Это может быть удобно, если, например, следует сохранить и зашифровать набор картинок в формате jpg. Если бы данная функция отсутствовала, то пришлось бы вначале программно считывать эти файлы в память, а уже затем записывать в зашифрованный файл. Чтобы облегчить задачу программисту и была создана эта функция. Обратным действием - извлечением файла из зашифрованного хранилища - занимается функция ToFile. В результате получается искомый файл в незашифрованном виде. Это может показаться слабым местом в организации защиты. Но в этом есть смысл с точки зрения удобства адаптации уже существующих программный комплексов обучения и тестирования. Сразу хочется заметить, что если есть желание обойтись без временных файлов в незашифрованном виде, то никаких сложностей нет. Рассмотрим на примере jpg файла. Достаточно записать такой файл в зашифрованном виде, используя функцию Write. Это достаточно просто, так как тип VARIANT может хранить массивы байт. В дальнейшем этот массив байт будет возможно непосредственно считать в память и отобразить на экране, не прибегая к временным фалам не диске. Но дело в том, что часто это требует существенной доработки уже существующего программного обеспечения. И проще, по крайней, мере на начальном этапе внедрения системы защиты, за счет некоторого понижения степени надежности, быстро модифицировать уже имеющуюся программу. Эта может быть весьма важным моментом. Как только файл будет отображен на экране, этот временный файл можно тут же стереть.
Описание используемых параметров:
handle - дескриптор файла для чтения.
FileName - имя файла добавляемого в зашифрованное хранилище.
read - возвращает размер прочитанных данных в байтах.
HRESULT ToFile(
[in] short handle,
[in] BSTR FileName,
[out, retval] long *written);
Функция ToFile производит обратное действие относительно FromFile. Она извлекает файл из хранилища.
Описание используемых параметров:
handle - дескриптор файла для чтения.
FileName - имя извлекаемого файла.
written - возвращает размер записанных данных в байтах.
Интерфейс IProtectConformity объединяет набор вспомогательных функций, призванных облегчить использование системы с большим количеством файлов, с алгоритмами и зашифрованными данными. Например, возьмем АРМ преподавателя. В этой системе может быть большое количество различных данных, связанных с определенными студентами. Если эти данные зашифрованы, то необходимо знать, каким именно файлом с алгоритмом это сделано. Все эти взаимосвязи необходимо хранить. В случае, если такая система написана с использованием СУБД, сложностей возникнуть не должно. Если же нет, то придется вносить некоторую дополнительную функциональность, которая является подмножеством возможности СУБД. Чтобы облегчить адаптацию таких проектов, не использующих БД, предназначены функции описываемого интерфейса. Фактически, они позволяют строить и работать с таблицами соответствий. Такая таблица представляет собой набор пар, содержащий имя зашифрованного файла и имя соответствующего файла алгоритма для шифрования или расшифрования. В такой таблице возможен поиск, как по имени зашифрованного файла, так и по имени файла с алгоритмом. В дальнейшем файлы, хранящие информацию о соответствии файлов с данными и соответствующими файлами с алгоритмами, будем называть файлами соответствий. Отметим также, что файлы соответствий тоже подвергаются шифрованию.
interface IProtectConformity : IDispatch
{
[id(1), helpstring("method Create Conformity File")]
HRESULT CreateConformityFile(
[in] BSTR name,
[in] BSTR uptFileNameForRead,
[in] BSTR uptFileNameForWrite,
[in] BSTR ArrayOfStrings);
[id(2), helpstring("method Easy Create Conformity File")]
HRESULT EasyCreateConformityFile(
[in] BSTR name,
[in] BSTR uptFileNameForCreate,
[in] BSTR ArrayOfStrings);
[id(3), helpstring("method Read Conformity File")]
HRESULT ReadConformityFile(
[in] BSTR name,
[in] BSTR uptFileNameForRead,
[out, retval] BSTR *ArrayOfStrings);
[id(4), helpstring("method Get UptAlgName by FileName")]
HRESULT GetAlgName(
[in] BSTR Strings,
[in] BSTR SearchName,
[out, retval] BSTR *ResultStr);
[id(5), helpstring("method Get FileName by UptAlgName")]
HRESULT GetDataName(
[in] BSTR Strings,
[in] BSTR SearchName,
[out, retval] BSTR *ResultStr);
[id(6), helpstring("method Get UptAlgName by FileName From File")]
HRESULT GetAlgFromFile(
[in] BSTR FileName,
[in] BSTR uptFileNameForRead,
[in] BSTR SearchName,
[out, retval] BSTR *ResultStr);
[id(7), helpstring("method Get FileName by UptAlgName From File")]
HRESULT GetDataFromFile(
[in] BSTR FileName,
[in] BSTR uptFileNameForRead,
[in] BSTR SearchName,
[out, retval] BSTR *ResultStr);
};
Теперь опишем каждую из функций интерфейса IProtect.
HRESULT CreateConformityFile(
[in] BSTR name,
[in] BSTR uptFileNameForRead,
[in] BSTR uptFileNameForWrite,
[in] BSTR ArrayOfStrings);
Функция CreateConformityFile создает новый файл соответствий и записывает в него соответствующую таблицу. Таблица предается в виде одной строки, в которой последовательно записаны имена файлов. Все нечетные - имена файлов с данными, все четные - соответствующие алгоритмы шифрования или расшифрования. Имена должны быть заключены в двойные кавычки. Это связано с тем, что иначе невозможно работать с именами файлов, содержащими пробелы. Между кавычкой в конце имени одного файла и кавычкой перед именем второго может стоять произвольное количество пробелов и символов табуляции или возврата каретки и переноса строки. Поддержка одновременного хранения информации как о файлах для шифрования, так и для расшифрования не осуществлена. Это сделано по двум причинам. Во-первых, совсем не сложно завести два файла, а интерфейс функций и их количество существенно сокращается. Во-вторых, данная функциональность соответствия двух файлов может быть применена и для других целей. Хочется сделать ее более абстрактной. Следует дать следующий совет если для шифрования большого количества файлов одним алгоритмом: удобно создать соответствующий каталог, в который помещаются шифруемые файлы, записать в файл соответствий имя этого каталога и соответствующий алгоритм шифрования/расшифрования для работы с файлами в этом каталоге.
Файлы с алгоритмом шифрования и расшифрования для работы с файлом соответствий будут автоматически созданы, и будут иметь имена переданные в качестве аргументов функции.
Описание используемых параметров:
name - имя создаваемого файла, для хранения информации о соответствии.
uptFileNameForRead - имя создаваемого файла с алгоритмом расшифрования.
uptFileNameForWrite - имя создаваемого файла с алгоритмом шифрования.
ArrayOfStrings - строка с информацией о соответствиях.
HRESULT EasyCreateConformityFile(
[in] BSTR name,
[in] BSTR uptFileNameForCreate,
[in] BSTR ArrayOfStrings);
Функция EasyCreateConformityFile подобна функции CreateConformityFile, но в отличие от нее, не создает новые файлы с алгоритмами шифрования и расшифрования. Она использует уже существующий алгоритм шифрования.
name - имя создаваемого файла, для хранения информации о соответствии.
uptFileNameForCreate - имя файла с алгоритмом шифрования.
ArrayOfStrings - строка с информацией о соответствиях.
HRESULT ReadConformityFile(
[in] BSTR name,
[in] BSTR uptFileNameForRead,
[out, retval] BSTR *ArrayOfStrings);
Функция ReadConformityFile читает содержимое файла соответствий и возвращает его в виде строки. Строка имеет тот же формат, что и передаваемая например в функцию CreateConformityFile.
Описание используемых параметров:
name - имя зашифрованного файла c информацией о соответствиях.
uptFileNameForRead - имя файла с алгоритмом расшифрования.
ArrayOfStrings - возвращаемая строка с информацией о соответствиях.
HRESULT GetAlgName(
[in] BSTR Strings,
[in] BSTR SearchName,
[out, retval] BSTR *ResultStr);
Функция GetAlgName, используя имя файла с данными, возвращает соответствующий алгоритм шифрования или расшифрования. Поиск производится в переданной строке. Формат строки эквивалентен формату, с которым работают и другие функции. Например, EasyCreateConformityFile или ReadConformityFile.
Описание используемых параметров:
Strings - строка с информацией о соответствиях.
SearchName - имя файла с данными, для которого будет произведен поиск соответствующего алгоритма.
ResultStr - возвращаемое имя файла с алгоритмом.
HRESULT GetDataName(
[in] BSTR Strings,
[in] BSTR SearchName,
[out, retval] BSTR *ResultStr);
Функция GetDataName, используя имя файла с алгоритмом, возвращает имя соответствующего файла с данными. Поиск производится в переданной строке. Формат строки эквивалентен формату, с которым работаю и другие функции. Например EasyCreateConformityFile или ReadConformityFile.
Описание используемых параметров:
Strings - строка с информацией о соответствиях.
SearchName - имя файла с алгоритмом, для которого будет произведен поиск соответствующего файла с данными.
ResultStr - возвращаемое имя файла с данными.
HRESULT GetAlgFromFile(
[in] BSTR FileName,
[in] BSTR uptFileNameForRead,
[in] BSTR SearchName,
[out, retval] BSTR *ResultStr);
Функция GetAlgFromFile, подобно функции GetAlgName, возвращает соответствующий алгоритм шифрования или расшифрования по имени файла с данными. В отличие от нее, на входе она получает не строку с информацией о соответствиях, а имя с этой информацией и алгоритм для ее расшифрования. Функция может быть более удобна в плане ее использования, но она менее эффективна. Так, если требуется активно работать с таблицами соответствий, то для ускорения работы рекомендуется отказаться от использования функции GetAlgFromFile. Эффективнее будет однократно прочитать информацию о соответствиях, используя функцию ReadConformityFile, а затем использовать функцию GetAlgName.
Описание используемых параметров:
FileName - имя файла с зашифрованной информацией о соответствиях.
uptFileNameForRead - файл с алгоритмом расшифрования.
SearchName - имя файла с данными, для которого будет произведен поиск соответствующего алгоритма.
ResultStr - возвращаемое имя файла с алгоритмом.
HRESULT GetDataFromFile(
[in] BSTR FileName,
[in] BSTR uptFileNameForRead,
[in] BSTR SearchName,
[out, retval] BSTR *ResultStr);
Функция GetDataFromFile, подобно функции GetDataName, возвращает имя соответствующего файла с данными, по имени файла с алгоритмом. В отличии от нее, на входе она получает не строку с информацией о соответствиях, а имя с этой информацией и алгоритм для ее расшифрования. Функция может быть более удобна в плане ее использования, но она менее эффективна. Так, если требуется активно работать с таблицами соответствий, то для ускорения работы рекомендуется отказаться от использования функции GetDataFromFile. Эффективнее будет однократно прочитать информацию о соответствиях, используя функцию ReadConformityFile, а затем использовать функцию GetDataName.
Описание используемых параметров:
FileName - имя файла с зашифрованной информацией о соответствиях.
uptFileNameForRead - файл с алгоритмом расшифрования.
SearchName - имя файла с алгоритмом, для которого будет произведен поиск соответствующего файла с данными.
ResultStr - возвращаемое имя файла с данными.
4.3. Руководство программиста по использованию программы ProtectEXE.exe
Программа ProtectEXE.EXE предназначена для защиты исполняемых файлов от модификации. Под исполняемыми модулями понимаются EXE файлы в формате PE (Portable Executables). Защита исполняемых модулей основана на их шифровании. Особенностью утилиты ProtectEXE является то, что она шифрует каждый исполняемый файл уникальным полиморфным алгоритмом. Это затрудняет возможность использования программного взломщика, основанного на модификации определенных кодов в программе. Поскольку каждый исполняемый файл зашифрован своим методом, то и модифицировать их единым методом невозможно. Утилита ProtectEXE.EXE не позволяет защититься от динамического модифицирования в памяти. Это слишком сложно и не может быть достигнуто без существенной переделки исходного текста самой защищаемой программы. Но в рамках защиты дистанционных средств обучения такая защита должна быть достаточно эффективна, так как создание взламывающей программы экономически мало целесообразно, а следовательно и скорее всего не будет осуществлено.
Модуль ProtectEXE.EXE имеет два возможных режима запуска. Первый режим предназначен для генерации зашифрованного файла из указанного исполняемого модуля. Второй режим служит непосредственно для запуска защищенного модуля.
Опишем этап создания зашифрованного файла. Для создания зашифрованного файла необходимо запустить ProtectEXE.EXE, указав в качестве параметра имя шифруемого исполняемого файла. Можно указать не только имя, но и путь. В результате буду сгенерированы два файла. Если было указано только имя, то файлы будут располагаться в текущем каталоге. Если был указан путь к файлу, то сгенерированные файлы будут созданы в том же каталоге, где расположен и шифруемый файл. Первый файл будет иметь расширение upb. Он представляет собой непосредственно зашифрованный исполняемый файл. Второй файл будет иметь расширение upu. Он представляет собой ключ, необходимый для расшифровки исполняемого файла. При разработке ProtectEXE было принято решение хранить зашифрованный файл и ключ для его расшифровке не в едином файле, а раздельно. Это было сделано с целью большей гибкости. Если хранить все в одном файле, это будет означать, что его всегда будет возможно запустить. Раздельное хранение ключа позволяет создавать систему, где запуск определенных программ будет запрещен. Например, программа дистанционного обучения может позволять запускать набор определенных программ только тогда, когда будет выполнен ряд условий. Допустим, после сдачи определенного набора работ. Когда определенные работы будет сданы и защищены, АРМ преподавателя выдает студенту необходимые для дальнейшей работы ключевые файлы. Можно было бы, конечно, выдавать сразу расшифрованный бинарный файл, но программа может быть достаточно большой, и это просто нерационально. И, тем более, тогда нет никаких сложностей скопировать ее другому студенту, которому она еще не должна быть выдана.
Теперь опишем второй режим работы. Это непосредственно запуск зашифрованного модуля. Для его запуска необходимо запустить ProtectEXE, указав в качестве параметра путь и имя зашифрованного файла с расширением upb. Если будет найден ключевой файл с тем же именем, но с расширением upu, то программа будет запущена. При этом будет создан временный файл с расширением exe. Он будет располагаться в том же каталоге, где нахолодятся фалы с расширением upb и upu. Этот файл является временным и будет удален после завершения работы программы. Данный файл, хоть и носит расширение exe, не является исполняемым файлом. В чем можно убедиться, попытавшись запустить его. Результатом будет его зависание. Поэтому не следует бояться, что это расшифрованный файл, и студент сможет скопировать его, когда он будет создан.
4.4. Описание использования системы защиты на примерах
4.4.1. Подключение модуля защиты к программе на языке Visual C++
Распишем шаги, которые наобходимо проделать, чтобы подключить COM модуль Uniprot к программе, написанной на Visual C++.
1. Создайте новый или откройте уже существующий проект.
2. Создайте новую папку в каталоге с проекта или выберете уже существующую и скопируйте в нее необходимые для подключения библиотеки файлы. Это файлы: export.h, export.cpp, Uniprot.tlb.
3. Откройте MFC ClassWizard. Для этого выбирете в меню пункт
View->ClassWizard.
4. Нажмите на кнопку Add Class и выберете пункт "From a type library…".
5. Укажите путь к файлу Uniprot.tlb и откройте его.
6. В диалоге Confirm Classes вам скорее всего будет достаточно сразу нажать кнопку "Ok". Но если вы не согласны с продложенными установками по умолчанию, то можете внести в них соответсвующие изменения.
7. Закройте диалог MFC ClassWizard.
8. Включите в проект файлы export.h, export.cpp.
9. Добавить include "export.h" в те модуле, где вы планируете использовать библиотеку Uniprot.
10. Проверьте, что у вас инициализируется работа с COM. То есть вызывается функция CoInitialize.
11. Теперь вы можете работать с библиотекой COM например так.
IProtect ProtectObj;
IProtectFile ProtectFileObj;
ProtectObj.CreateDispatch(UniprotLibID);
ProtectFileObj.CreateDispatch(UniprotLibID);
LPDISPATCH pDisp = ProtectFileObj.m_lpDispatch;
HRESULT hr = pDisp ->QueryInterface(
IProtectFileIntarfaceID,
(void**)&ProtectFileObj.m_lpDispatch);
VERIFY(hr == S_OK);
4.4.2. Подключение модуля защиты к программе на языке Visual Basic
Распишем шаги, которые наобходимо проделать, чтобы подключить COM модуль Uniprot к программе, написанной на Visual Basic.
12. Создайте новый или откройте уже существующий проект.
13. Создайте новую папку в каталоге с проекта или выберете уже существующую и скопируйте в нее необходимый для подключ ...........
Страницы: 1 | 2 | 3 | [4] | 5 |
|