Смекни!
smekni.com

Защита информации в системах дистанционного обучения с монопольным доступом

АННОТАЦИЯ


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

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

Диссертациясодержит 168 страниц,12 иллюстраций,1 таблицу.


СОДЕРЖАНИЕ


ВВЕДЕНИЕ………………………………………………………………………...

ГЛАВА1. СОЗДАНИЕЗАЩИТЫ ДЛЯПРОГРАММНЫХПАКЕТОВ, НАПРИМЕРЕ СИСТЕМЫДИСТАНЦИОННОГООБУЧЕНИЯ………………….………..

1.1.Вопросы защитыинформации,стоящие передавтоматизированнымисистемамидистанционногообучения…………………………………..

1.2.Обзор публикацийпо даннойпроблеме…………………………………

1.3.Задачи поставленныеперед создаваемойсистемойзащиты…………...

1.4.Выбор классатребованийк системезащиты……………………………

1.5.Выводы…………………………………………………………………….

ГЛАВА2. ПРЕДЛАГАЕМЫЕМЕТОДЫ СОЗДАНИЯИНТЕГРИРУЕМОЙСИСТЕМЫ ЗАЩИТЫИНФОРМАЦИИ…………………………………………………

2.1.Выбор объектовдля защиты…………………………………………….

2.2.Шифрованиеданных……………………………………………………..

2.2.1.Некоторыеобщие сведения………………………………………

2.2.2.Асимметричныекриптосистемы……………………….………..

2.2.2.1.КриптосистемаЭль-Гамаля…………………………….

2.2.2.2.КриптосистемаРивеста-Шамира-Эйделмана…………

2.2.2.3.Криптосистема,основаннаяна эллиптическихкривых………………………………………………….

2.2.3.Адаптированныйметод асимметричногошифрования………..

2.3.Преимуществапримененияполиморфныхалгоритмовшифрования…………………………………………………….………...

2.4.Функциональностьсистемызащиты…………………………………….

ГЛАВА3. РЕАЛИЗАЦИЯСИСТЕМЫЗАЩИТЫ…………………………..

3.1.Выбор средствразработкии организациисистемы………….…………

3.1.1.Краткая характеристикаязыка программированияС++……….

3.1.2.Краткая характеристикасреды VisualC++…………….………..

3.1.3.Краткая характеристикабиблиотекиATL………………………

3.1.4.Краткая характеристикабиблиотеки ZLIB……………………..

3.2.Полиморфныйгенераторалгоритмовшифрования…………………….

3.2.1.Общие принципыработы полиморфныхалгоритмовшифрованияи расшифрования…………………………………

3.2.2.Виртуальнаямашина длявыполненияполиморфныхалгоритмов………………………………………………….…….

3.2.3.Генераторполиморфногокода…………………………….……..

3.2.3.1.Блочная структураполиморфногокода………………..

3.2.3.2.Алгоритм генерацииполиморфногокода…….……….

3.2.3.3.Таблицы блоковдля генерацииполиморфногокода……………………………………………………...

3.2.4.Уникальностьгенерируемогополиморфногоалгоритма исложностьего анализа…………………………………………...

3.3.Особенностиреализациимодуля защиты.………………………………

3.4.Защита исполняемыхфайлов…………………………………………….

ГЛАВА4. ПРИМЕНЕНИЕСИСТЕМЫЗАЩИТЫ………………….………

4.1.Состав библиотекиUniprot……………………………………………….

4.2.Руководствопрограммистапо использованиюмодуляUniprot.dll……………………………………………………….………...

4.3.Руководствопрограммистапо использованиюпрограммыProtectEXE.exe………………………………………………….….……..

4.4.Описаниеиспользованиясистемы защитына примерах……………….

4.4.1.Подключениемодуля защитык программена языке VisualC++………………………………………………………………...

4.4.2.Подключениемодуля защитык программена языке VisualBasic……………………………………………………………….

4.4.3.Пример использованиямодуля защитыв программена языке VisualBasic……………………………………….………………

4.4.4.Пример использованияпрограммыProtectEXE.exe……………

4.5.Общие рекомендациипо интеграциисистемы защиты………………..

ОСНОВНЫЕВЫВОДЫ ИРЕЗУЛЬТАТЫ………………………………….

СПИСОКИСПОЛЬЗОВАННЫХИСТОЧНИКОВ…………………………

ПРИЛОЖЕНИЕ.ИСХОДНЫЕ ТЕКСТЫБИБЛИОТЕКИUNIPROT………………………………………………………………………..…


7


12


12

14

27

30

33


34

34

38

38

40

41

42


43

43


45

47

48

48

48

49

50

51

52


52


56

59

59

62


63


65

68

69

70

70


71


86

88


88


89


90

98

99

101

102


105



ВВЕДЕНИЕ

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

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

Внастоящее времябольшинствоспециалистовв области образованиявозлагаютнадежды насовременныеперсональныекомпьютеры,рассчитываяс их помощьюсущественноповысить качествообучения вмассовых масштабах,особенно приорганизациисамостоятельнойработы и внешнемконтроле[1, 2, 3].Но при осущест­вленииэтой задачивозникаетмножествопроблем. Однаиз них состоитв том, что вразработкахавтоматизированныхсистемахдистанционногообучения (АСДО)нет никакойсистемы, никакогообъединяющегоначала, вследствиечего все АСДОявляются уникальными,разрозненными,не сопряженнымидруг с другомни по какимпараметрам.Отсюда следуетдублированиеразработокэлектронныхучебников, ихвысокая ценапри не всегдагарантированномкачестве, трудностиорганизациивнешнего контроля,а также неясностьвопросов, относящихсяк дидактическойэффективностикомпьютерногообучения вообще,слабая интеграциятрадиционныхучебников скомпьютернымии многие другие.Все эти трудности,с которымиприходитсясталкиватьсяразработчикамлюбых компьютерных обучающих систем, составляют «узкое» место в компьютеризацииобучения. Неустранив его,трудно надеятьсяна успешноевыполнениепрограммы,представленнойв проекте [4], гдезапланировано«создание иэффективноеиспользованиеединой образовательнойсреды на компьютернойоснове» и перечисленызадачи, являющиесяпервоочереднымив выполнениипрограммы.Например, однаиз задач сформулированаследующимобразом: «Создание,распространениеи внедрениев учебный процесссовременных электронных учебных материалов, их интеграция с традиционнымиучебными пособиями,а также разработкасредств поддержкии сопровождения.Обеспечениекачества,стандартизацияи сертификациясредств информационныхтехнологийучебного назначения»[4].Совершенноочевидно, чтоэффективностьвыполненияпрограммынепосредственнозависит оттого, насколькоуспешно будутпреодоленытрудности.

Оченьважной проблемойв области организациисамостоятельнойработы и, особенно,компьютерноговнешнего контроляявляется слабаязащищенностьобразовательногопрограммногообеспеченияот «взлома»с целью доступак правильнымответам и подделкирезультатовконтроля[5, 6, 7, 8, 9, 10, 11, 12].Эта проблемавытекает изтого, что в основномсовременныеконтролирующиесистемы строятсяна антропоморфномпринципе, сутькоторогоприменительнок автоматизацииобучения заключаетсяв использованиипамяти компьютерадля храненияэталонныхответов вместес заданиями.Как правило,они шифруются,но, как показываетпрактика, ихвсегда можнорасшифровать.Эта проблемаособенно островстала с появлениемв России дистанционныхтехнологийобучения, гдевнешний контрользнаний осуществляетсяв основномкомпьютеромв отсутствиепреподавателя.

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

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

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

Задачиисследования.

Длядостиженияпоставленнойцели в диссертационнойработе на примереАСДО сформулированыи решены следующиезадачи:

1)Выделены основныеключевые объекты,подлежащиезащите.

2)Разработаныметоды защитыАСДО вне довереннойвычислитель­нойсреды от массовыхпопыток модификациикода.

3)Разработаныметоды защитыданных длясистем обученияи контролязнаний внедовереннойвычислитель­нойсреды.

4)Проведен анализи предложенывозможныеспособы примененияразработанныхметодов.

5)На основе данныхметодов разработаннабор программныхмодулей защиты,предназначенныхдля интегрированияв системыдистанционногообучения.

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

Научнаяновизнаработы состоитв следующем:

1)Предложен методзащиты программпутем шифрованияисполняемыхфайлов, основанныйна использованиимножествауникальныхполиморфныхалгоритмов.

2)Предложен методорганизациизащиты информациии ее обмена сприменениемидеологииоткрытогоключа, основаннойна полиморфныхалгоритмах.

3)Отказ от использованияаппаратныхсредств.

4)Создание единогонабора интегрируемыхпрограммныхмодулей дляинтеграциив различныесистемы дистанционногообучения.

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

Практическаяценность:

1.Разработаныэффективныеметоды защитысистем дистанционногообучения внедовереннойвычислительнойсреды.

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

3.Разработанныеметоды не нуждаютсяв аппаратныхсредствах длясвоей реализации.

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

Внедрениеразработки:

Разработаннаясистема защитыбыла интегрированав программныйкомплекс AquariusEducation4.0, созданныйна кафедре АТМпод руководствомЮхименко Александраи представляющийсобой системуавтоматизированноготестирования.

Апробацияработы.

Всевопросы, относящиесяк теме диссертации,обсуждалисьнаразличныхкон­ференциях:

  1. Построениезащиты в системеконтроля ипередачи знаний.Печатный Сборникдокладовмеждународнойнаучной конференцииММТТ-Дон. РГХАСМ,Ростов-на-Дону,2002. 2 стр.

  2. Системаинтеграциизащиты информациидля пакетов автономногодистанционногообучения. ПечатныйСборник докладовмеждународнойнаучной конференцииММТТ-Дон. РГХАСМ,Ростов-на-Дону,2003. 2 стр.

Диссертациясостоитиз введения, четырех глав,заключенияи приложения.

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

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

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

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

Взаключенииподведены итогипроделаннойработы.

Вприложенииприведен исходныйтекст модулязащиты.


ГЛАВА1. СОЗДАНИЕЗАЩИТЫ ДЛЯПРОГРАММНЫХПАКЕТОВ, НАПРИМЕРЕ СИСТЕМЫДИСТАНЦИОННОГООБУЧЕНИЯ

1.1.Вопросызащиты информации,стоящие передавтоматизированнымисистемамидистанционногообучения

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

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

а)немалыефинансовыезатраты;

б)необходимость,чтобы каждыйстудент имелвозможностьнаходитьсяв сети;

в)низкаяпропускнаяспособность,если брать вовнимание качествоотечественныхтелефонныхлиний;

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


Отсюдавозникаетпотребностьсделать этусистему автономнойс возможностьюраспространенияее на носителях,таких, как CD-ROM.

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

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

1.Отсутствиевозможностидостоверноопределить,прошел ли студенттестированиесамостоятельно.Для этой задачион вполне могиспользоватьдругого человека(например, болееподготовленногостудента).

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

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

4.Существуетугроза созданияуниверсальнойпрограммыпросмотрафайлов с заданиямии ответами. Темсамым, студентимеет возможностьузнать верныеответы на вопросыв тестах.

5.Возможностьмодификациипрограммногокода системытестирования,с целью измененияалгоритмавыставленияоценок.

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


1.2.Обзор публикацийпо данной проблеме

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

Вкачестве подходак решению некоторыхпроблем, можнопривести примерсистемы, описаннойв еженедельнике"Закон. Финансы.Налоги." в статье"Компьютер-экзаменатор"[13]:

"УченыеСГУ разработалиновую тест-систему.Дляконтроля знанийстудентов вСовременномгуманитарномуниверситетеприменяетсяоригинальнаясистема тестирования,использующаяпечатные материалы.

Дляповышениякачества учебногопроцесса внедренасистема с применениемперсональногокомпьютерапреподавателяи индивидуальныхэлектронныхприборовтестирования.При ее использованииполностьюисключаетсярутинная ручнаяпроверка ипроставлениеоценок методистом.

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

Всостав системывходят личныеидентификаторыстудентов ипреподавателей,ПК, прибортестированияи устройствоввода-выводаинформации.

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

Работаэлектроннойсистемы происходитпо следующемусценарию. Системепредъявляетсяличный идентификатор(пластиковаякарточка скодом) методиста,который будетпроводитьтестирование.Далее системепредъявляетсяЛИ студента.Система производитпоиск в базеданных и выводна экран монитораданные о студенте(ФИО, номер контрактаи номер группы).Методист выбираеттест, на которыйбудет отвечатьстудент. Данныеможно ввестикак с клавиатуры,так и проведясканером поштрих-коду,нанесенномуна каждый варианттеста. Студентувыдаются прибортестированияи лист с вопросами.Время, выделенноедля ответа натест, контролируетсяв приборетестированияи в компьютере.Студент, нажавклавишу наприборе тестирования,видит оставшеесяу него время.За 5 мин. до концатестированияприбор предупреждаетстудента звуковыми текстовымсообщениями.По окончаниитестированиястудент возвращаетприбор методисту.Производитсяактивацияустройстваввода-выводаи прием собранныхданных из приборав компьютер.

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

Аналоговтакой системыв настоящеевремя не существует.СГУ готов всемзаинтересовавшимсяданной уникальнойсистемой оказатьвсестороннеесодействиеи консультации."

Применитьподобные методына практикезатруднительно.Причина очевидна– это слишкомвысокая ценапостроениясистемы сиспользованиемтаких аппаратныхсредств, да иэто не совсемто решенияпроблем дистанционноготестирования.

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

Внекоторыхдокладах вполнечестно отмечается,что существуетмасса нерешенныхпроблем. Примеромможет являтьсятезисы докладаО.С. Белокрыловав "Использованиекурса дистанционногообучения наэкономическомфакультетеРГУ" [14]. В нихотмечено,что проведеннаяработа даетразличныеположительныерезультатыпримененияинтернет-технологии.Но далее отмечается,что новационныйхарактер продуктаобусловливаетналичие некоторыхнедоработоки негативныхсторон программы.Одной из нихявляется: "слабаязащита (студентымогут использоватьчужой парольи выполнятьзадание подчужим именем);".

Отом же говоритС.В. Алешин, рассматривая принципы построения оболочкиинформационно-образовательной среды «Chopin»,имеющей структуру,показаннуюна рисунке 1[15].

Рисунок1. Структураоболочки «Chopin»

Онотмечает:

"Готовыетесты хранятсяв файловойсистеме данных(ФСД) в видетекстовыхфайлов Windowsс расширением“tst”.Подобный форматочень удобенпри практическойэксплуатациисистемы. Системаявляется прозрачной,логика ее работыможет бытьпроконтролированадо самого нижнегоуровня. Вместес тем, подобнаяоткрытостьсоздает рядпроблем в обеспеченииее безопасности.Система информационнойбезопасность основана наразграниченииправ пользователей."

Встатье "Проблемаобратной связипри дистанционномобучении." А.Г.Оганесян отмечает,что системадистанционногообразованиядолжна иметьдостаточныесредства защитыот несанкционированноговмешательстваи подмены реальныхстудентов ихдублерами [16].Далее говорится,что проблемаидентификациистудентов,кажется, вообщене имеет решения.Действительно,как уже отмечалось,пароли и иныеатрибуты личнойидентификациипроблемы нерешают, т.к. студентзаинтересованзаменить себядублером ирасполагаетнеограниченнымивозможностямитакой подмены.Техническоерешение дляее обнаруженияпридумать покане удалось. Авот организационные,похоже, есть.Выход можетбыть в созданиипостепенногоконтроля знанийс целью формированиятрудностейдля подменыпроходящеготестированиедублером. Найтидублера на одинэкзамен намногопроще, чем навесь периодобучения.

Внекоторыхработах отмечается,что примененныесистемы защитыможет иметьнегативныестороны. В тезисахдокладов ЗанимонецЮ.М. отмечает:"иногдачрезмерныемеры защитысоздавалипроблемы приинсталляциии эксплуатациипрограммногообеспечения"[17]. Следовательно,немаловажныммоментом являетсяхорошая продуманностьсистемы защиты.В противномслучае онаможет скореенавредить, чемпринести пользу.Из этого вновьможно сделатьвыводы, чтовопросы защиты(в областидистанционногообразования)плохо проработаны.

Некоторыеученые рассматриваютзащиту в оченьограниченномаспекте. Н.Н.Сенцов и В.С.Солдаткин,описывая программныйкомплекс
тестового контроля знаний «Тест», говорято следующем[18]:

"Каждаячасть программногокомплексафункционируетсамостоятельно.В клиентскойчасти нет возможностидоступа к базеданных для ееизменения –это возможноиз администраторскойчасти при знаниипароля доступак базе данных.Для работыклиентскойчасти необходимазаполненнаябаза данныхтестовымизаданиями. Этодолжно бытьзаведомо сделаноиз части администратора."

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

Внекоторыхстатьях этапроблема нерассматривается.Весьма интереснаясистема, описаннаяв статье"Автоматизированнаясистема разработкиэлектронныхучебников."А.А. Мицель, очевидновообще не защищена[19]. Все это говорито том, что этипроблемы весьмаважные, но вэтой областимало наработок.

Аналогично,Д.А. Жолобов,говоря о созданиигенераторамультимедийныхучебников,отмечает, чтопрограммадолжна обладатьвозможностьюзащитыданныхучебника отнесанкционированногодоступа [20]. Ноничего не говоритсяо том, как реализованазащита в этойсистеме.

Р.И.Вергазови П.А.Гудков,описывая системуавтоматизированногодистанционноготестирования,отмечают, чтов сетевом вариантеможно построитьвесьма надежнуюсистему [21]. Существуетвариант дляработы системыи в локальномрежиме. Но неупоминается,существуютли защита прииспользованииэтой системыв данном режиме.

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

1.Отсутствиевозможностиопределить,прошел ли студенттестированиесамостоятельно.Для этой задачион вполне могиспользоватьдругого человека(например, болееподготовленногостудента).

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

Проблематого, что студентможет пойтик товарищу, ане выполнятьлабораторнуюработу дома,практическиявляется проблемойустановкинесколькихкопий комплекса"виртуальнаялаборатория".А следовательно,эта проблемабудет обсужденав пункте № 2.

Вотчто пишет П.С.Ложников повопросу распознаваниепользователейв системахдистанционногообразования[22]:

"Сегодняостро стоитвопрос о качествезнаний, полученныхс использованиемтехнологиидистанционногообразования.При очной формеобучения большинствопреподавателейведут учетпосещаемостистудентов. Спереходом надистанционноеобразование(ДО) аудиторияобучаемыхувеличиласьв несколькораз, и учитыватьпосещаемостьстудентовпроблематично.ДО предъявляетопределенныетребованияк психологическимособенностямобучаемого.Во-первых, унего должнабыть высокаяустойчиваямотивация кполучениюобразования.Во-вторых, студентдостаточночетко долженпредставлятьжелаемый результатобучения. И,в-третьих, ондолжен понимать,что несетответственностьза знания, полученныес помощью СДО.Говорить о том,что сегодняидут на дистанционнуюформу обучениялюди с такимипсихологическимиданными нельзя.Большинстволюдей в Россииучится за самфакт получениядиплома. И умногих утверждениео том, что ДОобеспечиваетчеловеку свободныйграфик обучения,ассоциируетсясо свободнымпосещениемсервера СДО.В связи с этим,существуетвероятностьтого, что притестированиистудент можетпосадить закомпьютервместо себяболее осведомленногов предметечеловека.Навигационнаясистема ДОдолжна проверять,находится лиза удаленнымкомпьютеромименно тотобучаемый, закоторого онсебя выдает,то есть, произвестираспознаваниепользователя.

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

  • переченьстраниц, посещенныхпользователемза сеанс работы;

  • время,проведенноена каждой странице;

  • активированныегиперссылкина данной странице;

  • переченьфайлов, которыебыли скопированыпользователемс учебногосервера;

  • времятестирования;

  • идр.

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

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

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

Болееинтереснымявляется направление,обозначенноев статье какраспознаваниепользователейс использованиемдополнительногопрограммногообеспечения.Развитие исследованияданного вопросамы можем найтив пособии "Какзащитить информацию"(глава "Идентификацияпользователя:СВОЙ - ЧУЖОЙ?")[23].Вот основныеидеи, излагаемыев этом руководстве:

"Почеркуникален, этознают все. Нонемногиедогадываются,что в общениис компьютероминдивидуальностьпользователяпроявляетсятакже: скорость,привычка использоватьосновную илидополнительнуючасть клавиатуры,характер «сдвоенных»и «строенных»нажатий клавиш,излюбленныеприемы управлениякомпьютером...,с помощью которыхможно выделитьконкретногочеловека средивсех работавшихна данной машине. И ничего удивительного,- это сродниспособностимеломановразличать наслух пианистов,исполняющиходно произведение. Как же выявитьиндивидуальныеособенностиклавиатурногопочерка? Также,как и при графологическойэкспертизе:нужны эталонныйи исследуемыйобразцы текста.Лучше, если ихсодержаниебудет одинаковым(так называемая,парольная илиключевая фраза).Разумеется,по двум-трем,даже по десятинажатым клавишамотличить пользователяневозможно,нужна статистика.

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

Уникальныеособенностиклавиатурногопочерка выявляютсядвумя методами:по набору ключевойфразы или по«свободному»тексту. Каждыйобязательноимеет режимынастройки иидентификации.При настройкеопределяютсяи запоминаютсяэталонныехарактеристикиввода пользователемключевых фраз,например, время,затраченноена отдельныебуквы. А в режимеидентификации,после исключениягрубых ошибок,эталонное иполученноемножествасопоставляются(проверяетсягипотеза оравенстве ихцентров распределения)."

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

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

Применениеразличныхухищрений прихранении информациио проделаннойстудентомработе. Решитьэту проблемуне просто. Влюбом случаеневозможноузнать, чтостудент установилпакет программдистанционногообучения надвух компьютерах,а затем используетодин для тренировкии подбора правильныхответов, а второйуже для тестирования.При чем он можетпоступить прощеи воспользоватьсяпрограммойдля созданиямножествавиртуальныхмашин на однойфизической.Такой программой,например, являетсяWMware[24]. Или можетсоздать однувиртуальнуюмашину и установитьна ней программу,производящуютестирования.А затем, еслирезультатпрохождениятестированияего не будетустраивать,он сможетвосстановитьпредыдущеесостояние всейвиртуальнойсистемы, простосделав откат.Это, например,позволяетпроизвестиуже упомянутаяранее программаWMware.Т.е., фактически,используя такуюпрограмму,студент имеетвозможностьсоздавать"моментальныйслепок" всегокомпьютера.Что позволяетему необходимовернуться кпредыдущемусостоянию.

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

Ноэта технологияне являетсярешением проблемы.Посмотрим, что,например, говоритсяв электронномпособии поборьбе с хакерамио некоторыхтаких системах[23]:

"СистемаJAWS.

Ключеваяинформацияв системерасполагаетсяна дорожке 0инженерногоцилиндра сномером 42. Авторсистемы защитыот копированияJAWS утверждает,что созданныедискеты некопируютсяпрограммойCOPYWRIT. Это утверждениене соответствуетдействительности.Дискета копируетсяпрограммойCOPYWRIT, если указатьмаксимальныйномер копируемогоцилиндра, равным42.

СистемаНОТА.

Авторыэтой системытакже решилирасположитьинформациюо защите в областиинженерныхцилиндров. Вотличие отсистемы JAWS онирешили использоватьдорожку 0 цилиндра41. Однако программаCOPYWRIT также успешнокопируют этудискету.

СистемаSHIELD

Авторысистемы SHIELD непошли протореннымпутем использованияинженерногоцилиндра инарушения CHRN.Они использовалисвободноепространствона дорожке 0цилиндров 0, 1и 2 для размещенияключевой информации.Дискета некопируетсянапрямую программойCOPYWRIT. Однако послекопированияпрограммойCOPYWRIT достаточнообработатьданные программойDISK EXPLORER и Вы имеетеработоспособнуюкопию.

СистемаBOARD.

Надискете применяетсяметод форматированияс длиной 1. Такжеприменяетсяметод увеличениядлины последнегосектора, длязапутыванияпрограмм COPYIIPC иCOPYWRIT. Применяемыйформат имеетследующиехарактеристики.Формат одинаковдля цилиндров0 и 41. Выполняетсяформатированиена 11 секторовс N=1, GAP=255 и символомзаполнителемформата “X”.Первые 9 секторовимеют стандартныеR от 1 до 9 и N=2. ПредпоследнийCHRN имеет R=11 и N=6. Упоследнегосектора поляCHRN соответственноравны 123, 17, 249 и 7.Полученныйформат приработе с секторамиот 1 до 9 имеет“отрицательный”GAP3, так как форматированиевыполняетсяс кодом длины1, а операции ссекторамивыполняютсяс кодом длины2. При этом CRC секторазалезает наSYNC адресногомаркера идентификатораследующегосектора. В первомсекторе цилиндра41 записываетсяключевая информация,а сектора 2, 3, ... ,9 заполняютсясимволами F6h,что должномаскироватьих под обычныйформат. Вместес тем, авторыпроверяют извсего объемаключевой информациитолько информациюиз первогосектора нацилиндре 41. Поэтомупри копированиидостаточнозавести обычныйсектор с номером1 на 41 цилиндреи переписатьтуда ключевуюинформацию.Авторы неиспользовалидополнительныхвозможностейконтроля ключевойинформации.Анализ данныхпри чтениипредпоследнегосектора наключевых дорожкахпозволяетконтролироватьразмер GAP3 и символзаполнитель,использованныепри форматировании,а также CHRN последнегосектора надорожке и длинудорожки. "

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

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

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

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

Ноесть другойметод. Этоиспользованиешифрованияс открытымключом. Длякраткого ознакомленияс шифрованиемс использованияоткрытого ключаобратитьсяк книге БаpичеваСеpгея "Kpиптогpафиябез секретов"[25]:

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

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

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

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

криптографическиесистемы с открытымключом используюттак называемыенеобратимыеили односторонниефункции, которыеобладают следующимсвойством: призаданном значенииx относительнопросто вычислитьзначение f(x), однакоесли y=f(x), то нетпростого путидля вычислениязначения x.

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

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

Поэтомучтобы гарантироватьнадежную защитуинформации,к системам соткрытым ключом(СОК) предъявляютсядва важных иочевидныхтребования:

  1. преобразованиеисходноготекста должнобыть необратимыми исключатьего восстановлениена основе открытогоключа.

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

Алгоритмышифрованияс открытымключом получилиширокое распространениев современныхинформационныхсистемах. Так,алгоритм RSA сталмировым стандартомде-факто дляоткрытых систем.

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

  1. Разложениебольших чиселна простыемножители.

  2. Вычислениелогарифма вконечном поле.

  3. Вычислениекорней алгебраическихуравнений.

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

  1. Каксамостоятельныесредства защитыпередаваемыхи хранимыхданных.

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

  3. Средствааутентификациипользователей."

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

Подобнойпроблемы касаетсяБ.Н.Маутов в статье"Защита электронныхучебников наоснове программно-аппаратногокомплекса"Символ-КОМ"[26]. Но ее существеннымнедостаткомявляется наличиеаппаратнойчасти. Что весьмаограничиваетвозможностьиспользованиясистемы.

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

Побочнойпроблемойявляется возможностьвнесениязаинтересованнымлицом несанкционированногоизменения базданных обучающихсистем. Даннуюпроблему затрагиваетТыщенкоО.Б., говоря онеобходимостипримененияпаролей илисистемы паролей[27]. Хотя вопросрассматриваетсяв статье несколькос другого ракурса,он пересекаетсяс обсуждаемойпроблемой.Хранение данныхв обучающейсистеме подразумеваетвозможностьих просмотра,а, следовательно,наличие способадоступа к этимданных.

5.Возможностьмодификациипрограммногокода системытестированияс целью измененияалгоритмавыставленияоценок.

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

Вотчто, например,пишет ОганесянА. Г. в статье"Проблема«шпаргалок»или как обеспечитьобъективностькомпьютерноготестирования?"[28]:

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

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

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

Немаловажнымфактором являетсято, что существующиена данный моментразличныесистемы автоматизациипроцесса обучениянаписаны наразных языках.Это VisualC++, Delphi и Visual Basic и другиеязыки. Следовательно,для взаимодействияс ними нужноудобный и, главное,поддерживаемыйвсеми этимиязыками механизмвзаимодействия.Можно использоватьтакие средства,как именованныеканалы, сокеты.Но использованиетаких механизмовхотя и стандартнов ОС Windows, но ихиспользованиесовсем не простое.Надо иметьопределенныезнания по данномувопросу.

Впоследнее времяширокое применениенашла технологияCOM.Многие АСДО,разработанныес ее использованиемили с использованиемтаких ее разновидностей,как OLEи ActiveX.Для примераприведем словаРоманенко В.В.,описывающегосозданиеавтоматизированнойсистемы разработкиэлектронныхучебников [29]:

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

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

1.3.Задачи поставленныеперед системойзащиты

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

Ксожалению,первые двепроблемы лежатвне сферы возможностипрограммныхсредств безприменениядополнительногоаппаратногообеспечения.Напомним их.

1.Отсутствиевозможностидостоверноопределить,прошел ли студенттестированиесамостоятельно.Для этой задачион вполне могиспользоватьдругого человека(например, болееподготовленногостудента).

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

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

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

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

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

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

Решениеданной проблемыпредставляетсямне не в использованиистойких криптоалгоритмов,а в способехранения данных.Одно дело, есливсе данныебудут хранитьсяв текстовомвиде. Потомэтот текстовыйфайл будетпросто подвергнутшифрованию.В этом случае,расшифровавэти данные сиспользованиемнайденногоключа, злоумышленникполучит все,что ему надо.Совсем другоедело, если написатьмеханизмчтения/записиданных, использующийзаписи различныхтипов. Допустим,мы сохраняемсначала блокс названиемработы, потом,сохраняемидентификаторкартинки, затемданные самойкартинки, затемданные о правильномответе, и т.д.И теперь знаниеключа расшифровкимало что дает,т.к. для еще надознать форматсохраняемыхданных. А взломщикэто может узнатьтолько проведяглубокий анализвнутреннейработы ПО. Адаже если ктои проведет, ибудет знатьформат читаемых/сохраняемыхданных, он долженбудет создатьпрограмму,позволяющуюработать сними. В силутого, что хранимыеданные могутиметь весьмасложный формат,то это маловероятно.Иначе придетсяповторитьдовольно большуючасть неизвестногопрограммногокода.

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

5.Возможностьмодификациипрограммногокода системытестирования,с целью измененияалгоритмавыставленияоценок илидругого кода.

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

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

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

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

Этазадача полностьюлежит в сфереинформационныхтехнологийи имеет достаточнопростое решение.В ОС Windows существуетмеханизм, которыйпозволит легкоадаптироватьуже существующиесистемы дистанционногообучения итестирования,причем, созданныхна различныхязыках. Он обладаетширокой поддержкойсредств разработкии библиотек.ЭтоCOM (Component Object Model). COM- модель компонентныхобъектов Microsoft[31].

В частности,примером простотыработы с COM-модулямиможет служитьVisual Basic. В другихсредствахразработкипрограммногообеспеченияэтому механизмууделено многовнимания. ВVisual C++ существуетмощная библиотекаATL (Active Template Library) для разработкиCOM-модулей ивзаимодействияс ними. ATL - библиотекаактивных шаблонов,которая представляетсобой множествошаблонов языкаC++, предназначенныхдля построенияэффективныхСОМ-компонентов. Но главноепреимуществов том, что длятого чтобыподключитьмодуль защиты,кроме самойDLL, понадобитсятолько библиотекатипов (TLB файл).Библиотекатипов предназначенадля предоставлениядругим приложениями средам программированияинформациио составных объектах, которыев ней содержатся.

1.4.Выбор классатребованийк системе защиты

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

  • Оранжеваякнига (TCSEC)

  • Радужнаясерия

  • Гармонизированныекритерии Европейскихстран (ITSEC)

  • РекомендацииX.800

  • Концепциязащиты от НСДГостехкомиссиипри ПрезидентеРФ.

Остановимнаше вниманиена TCSEC.Оранжевая книгавыбрана, какдокумент ставшийсвоего родаклассическим.

TCSEC,называемыйчаще всего поцвету обложки"Оранжевойкнигой", былвпервые опубликованв августе 1983 года.Уже его названиезаслуживаеткомментария.Речь идет нео безопасных,а о надежныхсистемах, причемслово "надежный"трактуетсятак же, как всочетании"надежныйчеловек" —человек, которомуможно доверять."Оранжеваякнига" поясняетпонятие безопаснойсистемы, которая"управляет,посредствомсоответствующихсредств, доступомк информации,так что толькодолжным образомавторизованныелица или процессы,действующиеот их имени,получают правочитать, писать,создавать иудалять информацию".

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

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

Основныеэлементы политикибезопасности,согласно "Оранжевойкниге", включаютв себя по крайнеймере:

  • Произвольноеуправлениедоступом;.

  • Безопасностьповторногоиспользованияобъектов;

  • Меткибезопасности;

  • Принудительноеуправлениедоступом.

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

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

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

Согласно"Оранжевойкниге", меткибезопасностисостоят из двухчастей — уровнясекретностии списка категорий.Уровни секретности,поддерживаемыесистемой, образуютупорядоченноемножество,которое можетвыглядеть,например, так:

  • совершенносекретно;

  • секретно;

  • конфиденциально;

  • несекретно.

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

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

"Критерии"Министерстваобороны СШАоткрыли путьк ранжированиюинформационныхсистем по степенинадежности.В "Оранжевойкниге" определяетсячетыре уровнябезопасности(надежности)— D, C, B и A. УровеньD предназначендля систем,признанныхнеудовлетворительными.По мере переходаот уровня C к Aк надежностисистем предъявляютсявсе более жесткиетребования.Уровни C и B подразделяютсяна классы (C1, C2,B1, B2, B3) с постепеннымвозрастаниемнадежности.Таким образом,всего имеетсяшесть классовбезопасности— C1, C2, B1, B2, B3, A1.

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


1.5.Выводы

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


ГЛАВА2. ПРЕДЛАГАЕМЫЕМЕТОДЫ СОЗДАНИЯИНТЕГРИРУЕМОЙСИСТЕМЫ ЗАЩИТЫИНФОРМАЦИИ


2.1.Выбор объектовдля защиты

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

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

Рисунок2.

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

Рисунок3.

Втаком случаеуязвимым местомстановятсятакие объекты,как каналысвязи междуАРМ преподавателяи студента.Возможен вариантвзаимодействиямежду этимиАРМами в режимеoff-line.Под уязвимымиобъектамипонимаютсяразличные файлы(например срезультатамипромежуточноготестирования),с помощь которыхи организуетсяинформационноевзаимодействиемежду АРМ. Уязвимыбазы лекций,базы с задачамии ответами.Также самопрограммноеобеспечениеможет бытьподверженомодификации.На рисунке 4изображенаструктурнаясхема однойиз возможнойсистемы дистанционногообучения.

Рисунок4.


Теперьрассмотримболее подробнообъекты системыдистанционноголокальногообучения, требующиезащиты.

Данные,являющиесятекстом задачс ответами,могут бытьпросмотрены.Это не будетпростым деломв случае, еслиэти данныехранятся всложном бинарномформате, таккак без знанияустройствасоответствующегоформата, просмотртаких данныхвнешними программамивесьма сложен.Многие АСДОхранят этизадачи в простомтекстовом видеили в форматеWORDдокументов,и, следовательно,просмотр такихданных никакихсложностейне вызовет. И,соответственно,доступ к базезадач автоматическидискредитируютсистему тестирования.

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

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

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


2.2.Шифрованиеданных

2.2.1.Некоторые общиесведения

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

Бурноеразвитиекриптографическиесистемы получилив годы первойи второй мировыхвойн. Появлениевычислительныхсредств впослевоенныегоды ускорилоразработкуи совершенствованиекриптографическихметодов. Вообщеистория криптографиикрайне увлекательна,и достойнаотдельногорассмотрения.В качествехорошей книгипо теме криптографииможно рекомендовать"Основы современнойкриптографии"Баричев С. Г.[32].

Почемупроблемаиспользованиякриптографическихметодов винформационныхсистемах (ИС)стала в настоящиймомент особоактуальна?

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

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

Всеэто постоянноподталкиваетисследователейна созданиеновых криптосистеми тщательныйанализ ужесуществующих.

Проблемойзащиты информациипутем ее преобразованиязанимаетсякриптология.Криптологияразделяетсяна два направления– криптографиюикриптоанализ.Цели этих направленийпрямо противоположны.

Криптографиязанимаетсяпоиском иисследованиемметодов преобразованияинформациис целью скрытияее содержания.

Сфераинтересовкриптоанализа  исследованиевозможностирасшифровыванияинформациибез знанияключей.

Современнаякриптографияразделяет ихна четыре крупныхкласса.

  1. Симметричныекриптосистемы.

  2. Криптосистемыс открытымключом.

  3. Системыэлектроннойцифровой подписи(ЭЦП).

  4. Системыуправлениеключами.

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

Итак,криптографиядает возможностьпреобразоватьинформациютаким образом,что ее прочтение(восстановление)возможно толькопри знанииключа.

Приведемопределениянекоторыхосновных терминов,используемыхв криптографии.

Алфавит  конечноемножествоиспользуемыхдля кодированияинформациизнаков.

Текст  упорядоченныйнабор из элементовалфавита.

Вкачестве примеровалфавитов,используемыхв современныхИС можно привестиследующие:

  • алфавитZ33– 32 буквы русскогоалфавита (исключая"ё") и пробел;

  • алфавитZ256– символы, входящиев стандартныекоды ASCIIи КОИ-8;

  • двоичныйалфавит   Z2= {0,1};

  • восьмеричныйили шестнадцатеричныйалфавит.

Шифрование– процесспреобразованияисходноготекста, которыйносит такженазвание открытоготексташифрованныйтекст.

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

Криптографическаясистемапредставляетсобой семействоTпреобразованийоткрытоготекста. Членыэтого семействаиндексируются,или обозначаютсясимволом k;параметр kобычно называетсяключом.ПреобразованиеTkопределяетсясоответствующималгоритмоми значениемключа k.

Ключ– информация,необходимаядля беспрепятственногошифрованияи расшифрованиятекстов.

Пространствоключей K– это наборвозможныхзначений ключа.

Криптосистемыподразделяютсяна симметричныеи асимметричные(илисоткрытым ключом).

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

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

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

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

Кpиптостойкостьюназываетсяхарактеристикашифра, определяющаяего стойкостьк расшифрованиюбез знанияключа (т.е. криптоанализу).Имеется несколькопоказателейкриптостойкости,среди которых:

  • количествовсех возможныхключей;

  • среднеевремя, необходимоедля успешнойкриптоаналитическойатаки того илииного вида.

Эффективностьшифрованияс целью защитыинформациизависит отсохранениятайны ключаи криптостойкостишифра.


2.2.2.Асимметричныекриптосистемы

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

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

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

Криптосистемас открытымключом определяетсятремя алгоритмами:генерацииключей, шифрованияи расшифрования.Алгоритм генерацииключей открыт,всякий можетподать ему навход случайнуюстроку rнадлежащейдлины и получитьпару ключей(k1,k2).Один из ключей(например, k1)публикуется,он называетсяоткрытым, авторой, называемыйсекретным,хранится втайне. Алгоритмышифрования

и расшифрования
таковы,что для любогооткрытоготекста m
.

Рассмотримтеперь гипотетическуюатаку злоумышленникана эту систему.Противникуизвестен открытыйключ k1,но неизвестенсоответствующийсе­кретныйключ k2.Противникперехватилкриптограммуdи пытаетсянайти сообщениеm,где

.Посколькуалгоритм шифрованияоткрыт, противникможет простопоследовательноперебрать всевозможныесообщения длиныn,вычислить длякаждого такогосооб­щенияmiкриптограмму
и сравнить diс d.То сообщение,для которогоdi= dи будет искомымоткрытым текстом.Если пове­зет,то открытыйтекст будетнайден достаточнобыстро. В худшемже случае переборбудет выполненза время порядка2nT(n),где T(n)– время, требуемоедля шифрованиясообщения длинып.Еслисообщения имеютдлину порядка1000 битов, то такойперебор неосуществимна практикени на какихсамых мощныхкомпьютерах.

Мырассмотрелилишь один извозможныхспособов атакина кри­птосистемуи простейшийалгоритм поискаоткрытоготекста, назы­ваемыйобычно алгоритмомполного перебора.Используетсятакже и другоеназвание: «методгрубой силы».Другой простейшийалгоритм поискаоткрытоготекста – угадывание.Этот очевидныйалгоритм требуетнебольшихвычислений,но срабатываетс пренебрежимомалой вероятностью(при большихдлинах текстов).На самом делепротивник можетпытаться атаковатькриптосистемуразличнымиспособами ииспользоватьразличные,более изощренныеалгоритмыпоиска откры­тоготекста.

Дляпримера краткорасскажем онесколькихклассическихасимметричныхсистемах шифровани.

2.2.2.1.КриптосистемаЭль-Гамаля

СистемаЭль-Гамаля –это криптосистемас открытымключом, основаннаяна проблемелогарифма.Система включаеткак алгоритмшифрования,так и алгоритмцифровой подписи.

Множествопараметровсистемы включаетпростое числоpи целое числоg,степени которогопо модулю pпорождаютбольшое числоэлементов Zp.У пользователяAесть секретныйключ aи открытый ключy,где y=ga(modp).Предположим,что пользовательBжелает послатьсообщение mпользователюA.Сначала Bвыбирает случайноечисло k,меньшее p.Затем он вычисляет

y1= gk(modpy2= mЕ(yk(modp)),

гдеЕобозначаетпобитовое"исключающееИЛИ". Bпосылает Aпару (y1,y2).

Послеполученияшифрованноготекста пользовательAвычисляет

m= (y1amodp)Еy2.

Известенвариант этойсхемы, когдаоперация Езаменяетсяна умножениепо модулю p.Это удобнеев том смысле,что в первомслучае текст(или значениехэш-функции)необходиморазбивать наблоки той жедлины, что ичисло yk(modp).Во втором случаеэтого не требуетсяи можно обрабатыватьблоки текстазаранее заданнойфиксированнойдлины (меньшей,чем длина числаp).

2.2.2.2.КриптосистемаРивеста-Шамира-Эйделмана

СистемаРивеста-Шамира-Эйделмана(Rivest,Shamir,AdlеmanRSA)представляетсобой криптосистему,стойкостькоторой основанана сложностирешения задачиразложениячисла на простыесомножители.Кратко алгоритмможно описатьследующимобразом:

ПользовательAвыбирает паруразличныхпростых чиселpAи qA, вычисляет nA= pAqAи выбираетчисло dA,такое что НОД(dA,j(nA))= 1, где j(n)– функция Эйлера(количествочисел, меньшихnи взаимно простыхс n.Если pq,где pи q– простые числа,то j(n) = (p   1)(q   1)).Затем он вычисляетвеличину eA,такую, что dAЧeA= 1 (modj(nA)),и размещаетв общедоступнойсправочнойтаблице пару(eA,nA),являющуюсяоткрытым ключомпользователяA.

ТеперьпользовательB,желая передатьсообщениепользователюA,представляетисходный текст

x= (x0,x1,..., xn–1),xОZn, 0 Јin,

пооснованию nA:

N= c0+c1nA+....

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

:

,

получаязашифрованноесообщение N'.В силу выборачисел dAи eA,отображение

являетсявзаимно однозначным,и обратным кнему будетотображение

ПользовательА производитрасшифрованиеполученногосообщения N',применяя

.

Длятого чтобынайти отображение

,обратное поотношению к
,требуетсязнание множителейnA= pAqA.Время выполнениянаилучших изизвестныхалгоритмовразложенияпри n> 10145на сегодняшнийдень выходитза пределысовременныхтехнологическихвозможностей.

2.2.2.3.Криптосистема,основаннаяна эллиптическихкривых

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


2.2.3.Адаптированныйметод асимметричногошифрования

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

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

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

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

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


2.3.Преимуществапримененияполиморфныхалгоритмовшифрования

Кпреимуществампримененияполиморфныхалгоритмовшифрованиядля систем, пофункциональностисхожим с АСДО,можно отнестиследующиепункты:

  • слабаяочевидностьпринципа построениясистемы защиты;

  • сложностьсозданияуниверсальныхсредств дляобхода системызащиты;

  • легкаяреализациясистемы асимметрическогошифрования;

  • возможностьлегкой, быстройадаптации иусложнениятакой системы;

  • возможностьрасширениявиртуальноймашины с цельюсокрытия частикода.

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

1)Слабая очевидностьпринципа построениясистемы защиты,является следствиемвыбора достаточносвоеобразныхмеханизмов.Во-первых, этосамо выполнениекода шифрования/расшифрованияв виртуальноймашине. Во-вторых,наборы полиморфныхалгоритмов,уникальныхдля каждогопакета защищаемогопрограммногокомплекса. Этодолжно повлечьсерьезныезатрудненияпри попыткеанализа работытакой системыс целью поискаслабых местдля атаки. Еслисистема сразусоздаст видимостьсложности ималой очевидностиработы своихвнутреннихмеханизмов,то скорее всегоэто остановитчеловека отдальнейшихисследований.Правильнопостроеннаяпрограмма сиспользованиемразрабатываемойсистемой защитыможет не толькооказатьсясложной на вид,но и быть такойв действительности.Выбранные жеметоды сделаютустройстводанной системынестандартным,и, можно сказать,неожиданным.

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

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

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

5)Посколькупрограммистуотдаются исходныекоды системазащиты, то онлегко можетвоспользоватьсясуществующейвиртуальноймашиной и расширитьее для собственныхнужд. То же самоекасается игенератораполиморфныхалгоритмов.Например, онможет встроитьв полиморфныйкод ряд специфическойдля его системыфункций. Сейчасимеется возможностьограничитьвозможностьиспользованияалгоритмовпо времени. Агде-то, возможно,понадобитсяограничениепо количествузапусков. Можнорасширитьтолько виртуальнуюмашину с цельювыполненияв ней критическихдействий. Например,проверку результатовответа. Выполнениевиртуальногокода намногосложнее дляанализа, а,следовательно,расширяя механизмвиртуальноймашины, можнодобитьсясущественногоповышениязащищенностиАСДО.


2.4.Функциональностьсистемы защиты

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

  1. Генераторполиморфныхалгоритмовшифрованиеи расшифрования.

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

  3. Асимметричнаясистема шифрованияданных.

  4. Ограничениеиспользованияполиморфныхалгоритмовпо времени.

  5. Защитаисполняемыхфайлов отмодификации.

  6. Контрольза временемвозможностизапуска исполняемыхфайлов.

  7. Поддержкатаблиц соответствиймежду именамизашифрованныхфайлов и соответствующихим алгоритмамшифрования/расшифрования.

  8. Упаковкашифруемыхданных.


ГЛАВА3. РЕАЛИЗАЦИЯСИСТЕМЫ ЗАЩИТЫ


3.1.Выбор средствразработкии организациисистемы

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

Естественнымвыбором будетиспользованиеVisualC++.Он отвечаетвсем необходимымтребованиям.Также понадобитсябиблиотекадля сжатияданных. Наиболееподходящимкандидатомявляется библиотекаZLIB.Теперь рассмотримпо отдельностикаждый из этихкомпонентов,с целью показатьпочему былсделан именнотакой выбор.В рассмотрениевойдут: языкС++, среда VisualC++,библиотекаактивных шаблонов(ATL), библиотекаZLIB.


3.1.1.Краткая характеристикаязыка программированияС++

Объектно-ориентированныйязык С++ создавалсякак расширениеязыка Си. РазработанныйБьярном Страуструпом(BjarneStroustroup)из AT&TBellLabsв начале 80-х, С++получил широкоераспространениесреди программистовпо четыремважным причинам.

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

  • КомпиляторыС++ широко доступны,а язык соответствуетстандартамANSI.

  • Большинствопрограмм наС++ широко доступны,а язык соответствуетстандартамANSI.

  • Большинствопрограмм наСи без всякихизменений,либо с незначительнымиизменениями, можно компилироватьс помощьюкомпилятораС++. Кроме того,многие программисты,владеющиеязыком Си, могутсразу начатьработать скомпиляторомС++, постепенноосваивая егоновые возможности.При этом ненужно осваиватьновый сложныйобъектно-ориентированныйязык с нуля.

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

ХотябольшинствоэкспертоврассматриваютС++ как самостоятельныйязык, фактическиС++ представляетсобой развитоеобъектно-ориентированноерасширениеСи, или объектно-ориентированный«гибрид». Языкдопускаетсмешанноепрограммированиес использованиемконцепциипрограммированияСи и объектно-ориентированнойконцепции, иэто можноохарактеризоватькак недостаток.

Объектно-ориентированноепрограммирование(ООП) основная методологияпрограммирования90-х годов. Онаявляется результатомтридцатилетнегоопыта и практики,которые берутначало в языкеSimula67 и продолжаютсяв языках Smalltalk,LISP,Cluи в более позднихActor,Eiffel,ObjectiveC,Javaи С++. ООП это стильпрограммирования,который фиксируетповедениереального миратак, что деталиразработкискрыты, а этопозволяет тому,кто решаетзадачу, мыслитьв терминах,присущих этойзадаче, а непрограммирования.ООП это программирование,сфокусированноена данных, причемданные и поведениенеразрывносвязаны. Онивместе составляюткласс, а объектыявляются экземплярамикласса.

С++ относительномолодой иразвивающийсяязык, тольков 1998 году былутвержденстандарт ANSI,и еще не всекомпиляторыполностьюсоответствуютэтому стандарту.Тем не менееязык оченьпопулярен ираспространенне меньше, чемСи.

Выборбыл остановленна языке С++ последующимпричинам. Посколькубудет использоватьсясреда VisualC++,то нет смыслаотказыватьсяот преимуществязыка С++, темболее, что программадостаточносложная. Например,механизмыисключениймогут бытьвесьма полезны.Еще однимпреимуществомявляется возможностьиспользоватьумные указателина COMинтерфейсы,что часто бываеточень удобно.ИспользованиебиблиотекиATLтоже подразумеваетнеобходимостьязыка С++, таккак она написанаименно на нем.


3.1.2.Краткая характеристикасреды VisualC++

Всвязи с тем,что сегодняуровень сложностипрограммногообеспеченияочень высок,разработкаприложенийWindows с использованиемтолько какого-либоязыка программирования(например, языкаC) значительнозатрудняется.Программистдолжен затратитьмассу временина решениестандартныхзадач по созданиюмногооконногоинтерфейса.РеализациятехнологииCOMпотребует отпрограммистаеще более сложнойработы.

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

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

Подобныесредстваавтоматизированногосоздания приложенийвключены вкомпиляторMicrosoft Visual C++ и называютсяMFC AppWizard. Заполнивнесколькодиалоговыхпанелей, можноуказать характеристикиприложенияи получить еготексты, снабженныеобширнымикомментариями.MFC AppWizard позволяетсоздаватьоднооконныеи многооконныеприложения,а также приложения,не имеющиеглавного окна,-вместо негоиспользуетсядиалоговаяпанель. Можнотакже включитьподдержкутехнологииCOM,баз данных,справочнойсистемы.

СредаVisualC++6.0 была выбранакак одно излучших средствразработкина языке С++ дляОС MicrosoftWindows.Немаловажнымфактором являетсяее поддержкатакими утилитами,как VisualAssist,BoundsChecker,которые в своюочередь позволяютсоздаватьпрограммы болеебыстро и качественно.КомпиляторVisualC++генерируетдостаточнооптимизированныйкод, что весьмаважно дляразрабатываемогоприложения.


3.1.3.Краткая характеристикабиблиотекиATL

Библиотекаактивных шаблонов(ATL) представляетсобой основудля созданиянебольших СОМ- компонентов.В ATL использованыновые возможностишаблонов, добавленныев C++. Исходныетексты этойбиблиотекипоставляютсяв составе системыразработкиVisual C++. Кроме того,в эту системуразработкивведено множествомастеров Visual C++,что облегчаетначальный этапсозданияATL-проектов.

БиблиотекаATL обеспечиваетреализациюключевых возможностейСОМ компонентов.Выполнениямногих рутинныхпроцедур, скоторыми мыстолкнулисьпри разработкепоследнегопримера, можноизбежать засчет использованияклассов шаблоновATL. Приведем далеконе полный списокфункций ATL. Некоторыеиз них будутрассмотреныв этой главе.

  • УтилитаAppWizard, предназначеннаядля созданияпервичногоATL-проекта.

  • Мастеробъектов,используемыйдля добавленияв проект компонентовразличныхтипов.

  • Поддержкапо умолчаниюосновных интерфейсовCOM, таких какIUnknown и IClassFactory.

  • Поддержкамеханизматранспортировкипользовательскогоинтерфейса.

  • Поддержкабазового механизмадиспетчеризации(автоматизации)и двунаправленногоинтерфейса.

  • СущественнаяподдержкаразработкинебольшихэлементовуправленияActiveX.

Основнойзадачей ATL являетсяоблегчениесоздания небольшихСОМ-компонентов.Задача MFC — ускорениеразработкибольших Windows-приложений.Функции MFC и ATLнесколькоперекрываются,в первую очередьв области поддержкиOLE и ActiveX.

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


3.1.4.Краткая характеристикабиблиотеки ZLIB

БиблиотекаZLIBпредставляетсобой небольшуюи удобную библиотекуна языке С. Ееназначение– упаковка ираспаковкаданных. Посколькуона распространяетсяв исходныхкодах, то еебудет легкои удобно использоватьв разрабатываемоммодуле. Такжеотметим, чтоэта библиотекаявляется свободнораспространяемой,что не влечетза собой нарушенияавторских прав.


3.2.Полиморфныйгенераторалгоритмовшифрования

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


3.2.1.Общие принципыработы полиморфныхалгоритмовшифрованияи расшифрования

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

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

Рисунок5.Алгоритмшифрования/расшифрованияв общем виде.

Блок1 заносит ввиртуальныйрегистр илипеременную(обозначим еекак A1)адрес шифруемого/расшифруемогоблока данных.Для виртуальноймашины этотадрес на самомделе всегдаявляется нулем.Дело в том, чтокогда происходитвыполнениевиртуальнойинструкциимодификацииданных, товиртуальнаямашина добавляетк этому адресунастоящий адресв памяти и ужес ним производитоперации. МожнопредставитьA1как индекс вмассивешифруемых/расшифруемыхданных, адресуемыхс нуля.

Блок2 заносит ввиртуальныйрегистр илипеременную(обозначим еекак A2)размер блокаданных. А2 выполняетроль счетчикав цикле преобразованияданных. Заметим,что ее значениевсегда в 4 разаменьше, чемнастоящийразмер шифруемых/расшифруемыхданных. Этосвязано с тем,что полиморфныеалгоритмывсегда работаютс блоками данных,кратных поразмеру 4 байтам.Причем, операциипреобразованиявыполняютсянад блоками,кратными 4 байтам.О выравниванииданных по 4 байтазаботятся болеевысокоуровневыемеханизмы,использующиевиртуальнуюмашину и полиморфныеалгоритмы дляшифрованияи расшифрованияданных. Возникаетвопрос, откудаалгоритму"знать", какогоразмера блокему необходимозашифровать,ведь при егогенерации такойинформациипросто нет.Необходимоезначение онпросто беретиз ячейки памяти.Виртуальнаямашина памятизнает именнооб этой ячейкепамяти и передначалом выполненияполиморфногоалгоритмазаносит туданеобходимоезначение.

Блок3 помещает ввиртуальныйрегистр илипеременную(обозначим еекак A3)константу,участвующуюв преобразовании.Эта константа,возможно, затеми не будетиспользованадля преобразованияданных, всезависит оттого, какой кодбудет сгенерирован.Блок 3 можетбыть повтореннесколько раз.Над даннымиосуществляетсяцелый наборразличныхпреобразований,и в каждом изних участвуютразличныерегистры/переменные,инициализированныев блоке 3.

Блок4 можно назватьосновным. Именноон, а, точнеесказать, наборэтих блоковпроизводитшифрование/расшифрованиеданных. Количествоэтих блоковслучайно иравно количествублоков номер3. При преобразованияхне обязательнобудет использованозначение изA3.Например, вместоA3может использоватьсяконстанта илизначение изсчетчика. Наданный моментполиморфныйгенераторподдерживает3 вида преобразований:побитовое"исключающееили" (XOR),сложение ивычитание.Набор этихпреобразованиеможно легкорасширить,главное, чтобытакое преобразованиеимело обратнуюоперацию.

Блок5 служит дляувеличенияA1на единицу. Каки во всех другихблоках этаоперация можетбыть выполненапо-разному, тоесть с использованиемразличныхэлементарныхинструкцийвиртуальноймашины.

Блок6 организуетцикл. Он уменьшаетзначение A2на единицу, иесли результатне равен 0, товиртуальнаямашина переходитк выполнениючетвертогоблока. На самомделе управлениеможет бытьпередано наодин из холостыхблоков междублоком 3 и 4, нос функциональнойточки зренияэто значенияне имеет.

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

Блок8 завершаетработу алгоритма.


3.2.2.Виртуальнаямашина длявыполненияполиморфныхалгоритмов

Дляначала приведемсписок инструкций,поддерживаемыхна данный моментвиртуальноймашиной. Кодыэтих инструкцийимеют тип E_OPERATIONи определеныв файле p_enums.hследующимобразом:

enumE_OPERATION // Инструкции

{

EO_ERROR = -1, // Недопустимаяинструкция

EO_EXIT_0,EO_EXIT_1, EO_EXIT_2, // Конецработы

EO_NOP_0,EO_NOP_1, EO_NOP_2, EO_NOP_3, // Пустыекоманды

EO_TEST_TIME_0,EO_TEST_TIME_1, // Контрольвремени

EO_MOV,EO_XCHG, // Пересылкаданных

EO_PUSH, EO_POP, // Работа состеком

EO_XOR, EO_AND,EO_OR, EO_NOT, // Логическиеоперации

EO_ADD, EO_SUB,EO_MUL, EO_DIV, EO_NEG, // Арифметическиеоперации

EO_INC,EO_DEC,

EO_TEST,EO_CMP, // Операциисравнения

//(влияют на флаги)

EO_JMP, EO_CALL,EO_RET, // Операторыбезусловногоперехода

EO_JZ, EO_JNZ,EO_JA, EO_JNA, // Условныепереходы

};

Втаблице 1 приведенаинформацияпо этим инструкциями перечисленыих аргументы.

Таблица1. Описаниеинструкцийвиртуальноймашины.

Название

Действие

EO_EXIT_0

EO_EXIT_1

EO_EXIT_2

Командызавершенияработы. Послеее выполнениявиртуальнаямашина остановится,и управлениебудет передановыше. Данныеинструкцииаргументовне имеют.

EO_TEST_TIME_0EO_TEST_TIME_1

Командыконтроля времени.Имеют одинаргумент -последнийдоступныйдень использования.

EO_MOV

Командапересылкиданных. Имеетдва аргумента– источник иполучатель.

EO_XCHG

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

EO_PUSH

Сохраняетпереданныйаргумент встеке.

EO_POP

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

EO_XOR

Логическаяоперация XOR.Имеет двааргумента.Результатпомещаетсяв ячейку памятиили регистр,переданныйв качествепервого аргумента.


Продолжениетаблицы 1. Описаниеинструкцийвиртуальноймашины.

Название

Действие

EO_AND

Логическаяоперация AND.Имеет двааргумента.Результатпомещаетсяв ячейку памятиили регистр,переданныйв качествепервого аргумента.

EO_OR

Логическаяоперация OR.Имеет двааргумента.Результатпомещаетсяв ячейку памятиили регистр,переданныйв качествепервого аргумента.

EO_NOT

Логическаяоперация NOT.Имеет одинаргумент.Результатпомещаетсяв ячейку памятиили регистр,переданныйв качествеаргумента.

EO_ADD

Арифметическаяоперация сложения.Имеет двааргумента.Результатпомещаетсяв ячейку памятиили регистр,переданныйв качествепервого аргумента.

EO_SUB

Арифметическаяоперациявычитания.Имеет двааргумента.Результатпомещаетсяв ячейку памятиили регистр,переданныйв качествепервого аргумента.

EO_MUL

Арифметическаяоперацияумножения.Имеет двааргумента.Результатпомещаетсяв ячейку памятиили регистр,переданныйв качествепервого аргумента.

EO_DIV

Арифметическаяоперация деления.Имеет двааргумента.Результатпомещаетсяв ячейку памятиили регистр,переданныйв качествепервого аргумента.

EO_NEG

Арифметическаяоперация изменениязнака. Имеетодин аргумент.Результатпомещаетсяв ячейку памятиили регистр,переданныйв качествеаргумента.

EO_INC

Увеличиваетзначение ячейкипамяти илирегистра наединицу, передаваемойв единственномаргументе.

EO_DEC

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

EO_TEST

Операциясравнениядвух аргументовна равенство.Если аргументыравны, то флагZERO выставляетсяв true,в противномслучае в false.

EO_CMP

Операциясравнениядвух аргументов.Если аргументыравны, то флагZERO выставляетсяв true,в противномслучае в false.Если первыйаргумент меньшевторого, тофлаг ABOVE выставляетсяв true,в противномслучае в false.

Продолжениетаблицы 1. Описаниеинструкцийвиртуальноймашины.

Название

Действие

EO_JMP

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

EO_CALL

Даннаяинструкцияосуществляетвызов функциипо адресу,указанномув качествеаргумента.

EO_RET

Даннаяинструкциявозвращаетуправлениепредыдущейфункции. Аргументовнет.

EO_JZ

Условныйпереход поадресу, указанномув качествеаргумента.Условием являетсяZERO == true.

EO_JNZ

Условныйпереход поадресу, указанномув качествеаргумента.Условием являетсяZERO == false.

EO_JA

Условныйпереход поадресу, указанномув качествеаргумента.Условием являетсяABOVE == true.

EO_JNA

Условиемявляется ABOVE ==false.

Отметим,что аргументымогут бытьследующихтипов:

EOP_REG– Регистр

EOP_REF_REG– Память поадресу в регистре.

EOP_VAR– Переменная.

EOP_REF_VAR– Память поадресу в переменной.

EOP_CONST– Константноезначение.

EOP_RAND– Случайноечисло.

Перечисленныетипы объявленыв файле p_enums.h.

Дляпримера, приведемкак будет выгладитькод сложениярегистра N1 с константой0x12345:

DWORD AddRegAndConst[] = { EO_ADD, EOP_REG , 1, EOP_CONST, 0x12345 };

Длянагляднойдемонстрации,как происходитвыполнениекода в виртуальноймашине пришифровании/расшифрованииданных, приведемотрывок изотладочногоотчета. Каждоедействие вотладочномрежиме протоколируетсяв файле uniprot.log. Благодаряэтому, былолегко отлаживатьмеханизм генерацииполиморфныхалгоритмови саму работуалгоритмов.Дополнительнымрезультатомсоздания механизмапротоколированиястала возможностьпоказать, какпроисходитвыполнениеалгоритмашифрованиярасшифрования.Ниже приведенотрывок изфайла uniprot.log, относящийсяк процессушифрованияданных. С цельюсокращенияобъема текста,убраны дублирующийсявывод внутрицикла. Такжепри генерацииэтого алгоритмабыли выставленавложенностьшифрованияравная единицыи почти убраныхолостые блоки.


=== StartTranslateOperations ===

mov RAND ==>REG_2

xchg REG_2 VAR_16 REG_2 VAR_16

mov CONST ==>VAR_11

dec VAR_11 ==>VAR_11

cmp VAR_11 CONST

jnzCONST


mov RAND ==>REG_6

xchg VAR_14 VAR_12 VAR_14 VAR_12

mov CONST ==>VAR_15

add VAR_15 VAR_18 ==> VAR_15

mov RAND ==>REG_4

mov CONST ==>VAR_19

add VAR_19 VAR_9 ==> VAR_19

add REG_8 REG_7 ==>REG_8

xchg REG_2 VAR_13 REG_2 VAR_13


Этачасть повторяетсямного раз:

mov RAND ==>REG_6

xor REF_VAR_11VAR_14 ==> REF_VAR_11

mov RAND ==>REG_4

mov RAND ==>REG_9

xor REF_VAR_11VAR_15 ==> REF_VAR_11

sub VAR_11 CONST ==> VAR_11

mov RAND ==>REG_7

dec VAR_14 ==>VAR_14

cmpVAR_14 CONST

jnz CONST

…………..


mov RAND ==>REG_1

add REG_9 REG_6 ==>REG_9

test_time1 VAR_10

OK TIME (continue)

exit


3.2.3.Генераторполиморфногокода

3.2.3.1.Блочная структураполиморфногокода

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

//--------------------------------------------------------------

//Блок N5. (x1)

// Служитдля организациицикла.

// ES_VARIABLE_0 –ячейка, котораяможет бытьзанята подсчетчик.

// ES_REG_0 -регистр, которыйможет бытьзанят под счетчик.

// ES_ADDRESS_0 -куда осуществитьпереход дляповтора цикла.


BLOCK_START(05_00)

EO_DEC,EOP_VAR, ES_VARIABLE_0,

EO_CMP, EOP_VAR,ES_VARIABLE_0, EOP_CONST, 0,

EO_JNZ, EOP_CONST,ES_ADDRESS_0

BLOCK_END(05_00)


BLOCK_START(05_01)

EO_DEC, EOP_REG,ES_REG_0,

EO_CMP, EOP_REG,ES_REG_0, EOP_CONST, 0,

EO_JNZ, EOP_CONST,ES_ADDRESS_0

BLOCK_END(05_01)


BLOCKS_START(05)

BLOCK(05_00)

BLOCK(05_01)

BLOCKS_END(05)


BLOCKS_SIZE_START(05)

BLOCK_SIZE(05_00)

BLOCK_SIZE(05_01)

BLOCKS_SIZE_END(05)

//--------------------------------------------------------------

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

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

Вернемсяк распределениюблоков в памяти.Помимо того,что каждыйалгоритм состоитиз произвольногонабора функциональныхблоков, этиблоки не имеютфиксированногоместа расположения.Скажем, что подвесь алгоритмвыделено 200 байт,а размер всехблоков в суммесоставляет100 байт. В результатеположение этихблоков как бы"плавает" отодного сгенерированногоалгоритма кдругому. Должновыполнятьсялишь одно условие:соблюдениечеткой последовательностирасположенияблоков. То есть,адрес расположенияблока с большимномером неможет бытьменьше, чемадрес блокас меньшим номером.Для большейнаглядностиприведем рисунок6.


Рисунок6.Расположениефункциональныхблоков в памяти.

Белымцветом показанывсе функциональныеблоки. Серымцветом отмеченыпустые места,которые будутзаполненыпроизвольнымихолостымиблоками.

Можетполучиться,например, итакая картинараспределенияблоков, когдамежду некоторыминет промежутказаполняемогохолостымиблоками. Такаяситуация показанана рисунке 7.


Рисунок7.Плотное расположениефункциональныхблоков в памяти.

Какфункциональныеблоки, так ихолостые, могутиметь различнуюдлину. Послеслучайногорасположенияфункциональныхблоков происходитзаполнениепустых пространствмежду нимихолостымиблоками. Причем,существуютхолостые блокидлиной 1, длятого чтобыможно былозаполнитьпустые местав любом случае.Размер памяти,выделенныйпод создаваемыйкод алгоритма,выбираетсяпроизвольно.В данной версиион лежит в пределахот 160 до 200 байт.Это с запасомпокрываетмаксимальнонеобходимыйразмер памяти,необходимыйдля размещения8 самых большихфункциональныхблоков из всехвозможных, иоставляет местопод холостыеблоки. Болеебольшой полиморфныйкод хоть и будетсложнее дляанализа, но этоможет существеннозамедлитьпроцесс шифрованияи расшифрования.По этому лучшевсего придерживатьсяразумногобаланса.


3.2.3.2.Алгоритм генерацииполиморфногокода

Опишемтеперь пошаговокак работаетгенераторполиморфногокода.

  1. Напервом этапевыбираютсяхарактеристикибудущих алгоритмов.К ним относятся:
    a)размер памяти,выделеннойпод код;
    б) вкаких регистрахили ячейкахбудут располагатьсяуказатели намодифицируемыйкод;
    г) сколько раз будутповторятьсяфункциональныеблоки 3 и 4;
    д) вкаких регистрахили ячейкахбудут располагатьсясчетчики циклов;
    Приэтом количествоповторенийблоков 3 и 4 должнобыть одинаковыми для алгоритмашифрованияи для алгоритмарасшифрования,так как каждойкоманде преобразованияданных пришифрованиидолжна бытьсопоставленаобратная командав алгоритмерасшифрования.

  2. Виртуальнаяпамять, используемаяв алгоритме,заполняетсяслучайнымизначения.

  3. Создается1-ый функциональныйблок и помещаетсяв промежуточноехранилище.
    а)Случайнымобразом ищетсяподходящийпервый блок.Критерий поиска– блок должениспользоватьрегистр илиячейку памятипод указатель,в зависимостиот того какиехарактеристикибыли выбранына первом шаге(пункт б).
    б) Вкод блокаподставляетсясоответствующийномер регистраили адресвиртуальнойячейки памяти.

  4. Создается2-ой функциональныйблок и помещаетсяв промежуточноехранилище.Алгоритм созданияподобен алгоритму,описанномув шаге 3. Но толькотеперь подставляетсяне только номеррегистра илиячейки памяти,куда помещаетсязначение, нои адрес памятис источником.В эту ячейкупамяти в дальнейшемвиртуальнаямашина будетпомещать размершифруемой/расшифруемойобласти.

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

  6. Подсчитываетсяразмер ужесгенерированныхблоков. Эточисло затембудет использоватьсядля случайнойгенерацииадреса началаблоков в цикле.

  7. Рассчитываетсяразмер памяти,который будетвыделен подуже сгенерированныеблоки (расположенныедо цикла) срезервированиемместа под холостыеблоки. Такжеподсчитываетсяадрес первогоблока в цикле.

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

  9. Создается5-ый функциональныйблок и помещаетсяв промежуточноехранилище.

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

  11. Создается7-ой функциональныйблок и помещаетсяв промежуточноехранилище.

  12. Создается8-ой функциональныйблок и помещаетсяв промежуточноехранилище.

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

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

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


3.2.3.3.Таблицы блоковдля генерацииполиморфногокода

Вышенеоднократноупоминалисьтаблицы блоков,среди которыхпроисходитвыбор. Приведемдля примерачасть таблицыс блоками N1 и опишем ееустройство.

//--------------------------------------------------------------

// БлокN0. (x1)

// Служитдля инициализацииуказателянулем.

// ES_VARIABLE_0 -ячейка котораяможет бытьзанята подуказатель.

// ES_REG_0 -регистр которыйможет бытьзанят под указатель.

BLOCK_START(00_00)

EO_MOV, EOP_VAR,ES_VARIABLE_0, EOP_CONST, 0

BLOCK_END(00_00)


BLOCK_START(00_01)

EO_MOV, EOP_REG,ES_REG_0, EOP_CONST, 0

BLOCK_END(00_01)


BLOCK_START(00_02)

EO_PUSH,EOP_CONST, 0,

ES_RANDOM_NOP,

ES_RANDOM_NOP,

EO_POP, EOP_REG,ES_REG_0

BLOCK_END(00_02)


.. .. . . .


BLOCKS_START(00)

BLOCK(00_00)

BLOCK(00_01)

BLOCK(00_02)

BLOCK(00_03)

.. .. .

BLOCKS_END(00)


BLOCKS_SIZE_START(00)

BLOCK_SIZE(00_00)

BLOCK_SIZE(00_01)

BLOCK_SIZE(00_02)

BLOCK_SIZE(00_03)

.. .. .

BLOCKS_SIZE_END(00)

//--------------------------------------------------------------

Рассмотримстроку "BLOCK_START(00_00)". BLOCK_STARTпредставляетсобой макроскоторый делаеткод более понятными раскрываетсятак:

#defineBLOCK_START(num) const static int block_##num [] = {

BLOCKS_ENDраскрываетсяв:

#defineBLOCK_END(num) }; const size_tsizeBlock_##num =\

CALC_ARRAY_SIZE(block_##num);

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

EO_MOV,EOP_VAR, ES_VARIABLE_0, EOP_CONST, 0

Онапредставляетсобой один извариантовреализациипервого блока.EO_MOVозначает, чтобудет выполненакоманда пересылкиданных. EOP_VARозначает, чтозапись будетпроизводитьсяв ячейку памяти.Этот блок никогдане станет выбранным,если при выборехарактеристикалгоритма будетрешено, что подуказательнеобходимоиспользоватьрегистр. Еслиже будет приняторешение использоватьячейку памяти,то этот блокпопадет в списокиз которогозатем случайнымобразом будетпроизведенвыбор. ES_VARIABLE_0это идентификаторна место которогобудет подставленномер переменной,используемойдля храненияуказателя. Этотномер такжегенерируетсяна этапе выборахарактеристик.EOP_CONSTозначает, чтопеременнойбудет присвоенозначение константы.Этим значениемявляется 0.

Аналогичнымобразом интерпретируетсястрока: EO_MOV,EOP_REG,ES_REG_0,EOP_CONST,0. Но теперь вместовиртуальнойячейки памятивыступаетвиртуальныйрегистр. Болееинтереснымявляется следующийблок:

EO_PUSH,EOP_CONST, 0,

ES_RANDOM_NOP,

ES_RANDOM_NOP,

EO_POP, EOP_REG, ES_REG_0

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

МакросыBLOCKS_STARTи BLOCKS_SIZE_STARTносят вспомогательныйхарактер и непредставляютбольшого интереса.Они простостроят таблицыадресов различныхблоков и ихразмеров.


3.2.4.Уникальностьгенерируемогополиморфногоалгоритма исложность егоанализа

Важнаяидея в разрабатываемоммодуле защитызаключена впостроениисложного дляанализа полиморфногокода, что должнопрепятствоватьпостроениюобратногоалгоритма, таккак в защищаемыхсистемах частопросто невозможнохранить ключиотдельно отданных. Еслиесть доступк ключам, то иувеличиваетсявероятностькаким-либообразом произвестинесанкционированныедействия. Изэтого следуетнеобходимостьсоздания сложныхдля анализаалгоритмовшифрования/расшифрования.Одним из этихсредств являетсявиртуальнаямашина. Другим– использованиеполиморфныхалгоритмов.Это затрудняетвозможностипо анализумеханизмовшифрованияданных, так какполный анализодного алгоритмаочень малопомогает ванализе другого.Чем большевозможно вариантовпостроенияполиморфногокода, тем болеетрудоемкойстановитсяпроцедураанализа. Следовательно,можно сказать,что критерийнадежностиповышаетсяс ростом количествавозможныхвариантовполиморфногокода. Подсчитаемколичествовозможныхвариантов,который можетсгенерироватьразработанныйгенераторполиморфногокода.

Вероятностьгенерации двуходинаковыхпар составляет:(2^32*3)^5 3.5*10^50. Где 2^32 – случайноиспользуемаяконстанта дляшифрования.3 – количествовозможныхопераций надчислом. 5 – максимальноеколичествопроходов дляшифрования.Фактическиэто означаетчто два одинаковыхалгоритма небудут никогдасгенерированыэтой системой.Но это не являетсяцелью. Ведь точто не генерируются2 одинаковыхалгоритма, нетак важно. Важночто анализтаких разнородныхмеханизмовшифрования/расшифрованиябудет оченьплохо поддаватьсяанализу.

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

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

Впервом случаеможет понадобитьсяразрабатыватьдостаточносложную системус целью эмуляциигенератораотчета. Этоочень труднореализуемо.В каком-то смыслепридется повторитьбольшую частьфункциональностиАРМ студента.Так, если в отчетебудут хранитьсявопросы, которыебыли заданыстуденту, то,фактически,придется работатьс этой базойвопросов ислучайно выбиратьиз них. В противномслучае, еслииспользоватьстрого определенныйнабор, то у всех,кто воспользуетсятакой системойвзлома, будутсовпадатьотчеты. Этоможет привестик подозрениюсо стороныпреподавателя.Таким образом,в грамотно исложно организованнойАСДО этот подходпрактическине применим.

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

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

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


3.3.Особенностиреализациимодуля защиты

Разрабатываемыймодуль защитыUniprotбудет представлятьсобой файл типаdynamiclinklibrary(DLL)с именем Uniprot.dll.

Дляорганизациивзаимодействиямодуль защитыпредоставляетнабор интерфейсовс использованиемтехнологииCOM.Для описанияинтерфейсовиспользуетсяспециальныйязык - IDL, по своейструктуре оченьпохожий на С++.В определенииинтерфейсаописываютсязаголовкивходящих в негофункций с указаниемих имен, возвращаемыхтипов, входныхи выходныхпараметров,а также их типов.Подробно спредоставляемымиинтерфейсамиможно будетознакомитьсяв разделе 4.2. Интерфейсы,описанные вIDLфайле,преобразуютсяIDL-компилятором(MIDL.EXE) в двоичныйформат и записываютсяв файл с расширениемTLB, который называетсябиблиотекойтипов. Этотфайл будетнеобходим,например, дляиспользованиямодуля Uniprot.dllиз среды VisualBasic.С процессомподключения TLBфайлов в VisualBasicможно ознакомитьсяв разделе 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. Наборпримеров написанныхна VisualBasic,демонстрирующихработу с библиотекой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.В этот интерфейссобраны функцииобщего планаи генерациифайлов с полиморфнымиалгоритмамишифрованиеи расшифрования.


interfaceIProtect: IDispatch

{

[id(1),helpstring("method GetInfo")]

HRESULTGetInfo(

[out] short*version, [out] BSTR *info);

[id(2),helpstring("method Generate UPT files")]

HRESULTGenerateUPTfiles(

[in]BSTR algorithmCryptFileName,

[in] BSTRalgorithmDecryptFileName);

[id(3),helpstring("method Generate Time Limit UPT files")]

HRESULTGenerateTimeLimitUPTfiles(

[in] BSTRalgorithmCryptFileName,

[in] BSTRalgorithmDecryptFileName,

[in] longLimitDays);

[id(4),helpstring("method Generate Time Limit UPT files")]

HRESULTGenerateTimeLimitUPTfiles2(

[in] BSTRalgorithmCryptFileName,

[in] BSTRalgorithmDecryptFileName,

[in] longLimitDaysCrypt,

[in] longLimitDaysDecrypt);

};


Теперьопишем каждуюиз функцийинтерфейсаIProtect.


HRESULTGetInfo([out]short *version, [out] BSTR *info);


ФункцияGetInfoвозвращаетстроку с краткойинформациио данном модулеи его версии.Может бытьиспользованадля получениярядя сведенийо модуле. Например,имя автора игод создания.Версия хранитсяв виде числаследующимобразом: 0x0100– версия 1.00, 0x0101– версия 1.01, 0x0234– версия 2.34 и такдалее.

Описаниеиспользуемыхпараметров:

version– сюда будетзанесена версиямодуля.

info– сюда будетзанесена строкас краткой информациейо модуле.

HRESULTGenerateUPTfiles(

[in]BSTR algorithmCryptFileName,

[in]BSTR algorithmDecryptFileName);


ФункцияGenerateUPTfilesгенерируетдва файла-ключа.Они представляютсобой сгенерированныеполиморфнымгенераторомалгоритмышифрованияи расшифрования.При этом расшифроватьзашифрованныйфайл можнотолько соответствующималгоритмомрасшифрования.Генерируемаяпара ключейна практикеуникальна.Вероятностьгенерации двуходинаковыхпар составляет:(2^32*3)^5 3.5*10^50. Где 2^32 – случайноиспользуемаяконстанта дляшифрования.3 – количествовозможныхопераций надчислом. 5 – максимальноеколичествопроходов дляшифрования.

Описаниеиспользуемыхпараметров:

algorithmCryptFileName– имя выходногофайла с алгоритмомшифрования.

algorithmDecryptFileName– имя выходногофайла с алгоритмомрасшифрования.


HRESULTGenerateTimeLimitUPTfiles(

[in]BSTR algorithmCryptFileName,

[in]BSTR algorithmDecryptFileName,

[in]long LimitDays);


ФункцияGenerateTimeLimitUPTfilesгенерируетдва файла-ключа,ограниченныхв использованиипо времени. Вцелом функцияэквивалентнаGenerateUPTfiles,но генерируемыеею алгоритмыимеют дополнительноесвойство. Ихиспользованиеограниченоопределеннымвременем. Количестводней, в течениикоторых онибудут работать,указываетсяв третьем параметре LimitDays.Отсчет начинаетсяс текущего дня.Это может бытьполезно, например,для ограничениясрока использованияпроектов. Естественназащита самапо себе ненадежна,так как невозможнозащититьсяот переводачасов на компьютереили модификациикода модулязащиты с цельюудалениясоответствующихпроверок. Нотем не менееэто может датьдополнительныесвойствазащищенности,по крайней мереот рядовыхпользователей.

Описаниеиспользуемыхпараметров:

algorithmCryptFileName– имя выходногофайла с алгоритмомшифрования.

algorithmDecryptFileName– имя выходногофайла с алгоритмомрасшифрования.

LimitDays– количестводней, в течениикоторых будутфункционироватьсгенерированныеалгоритмы.


HRESULTGenerateTimeLimitUPTfiles2(

[in]BSTR algorithmCryptFileName,

[in]BSTR algorithmDecryptFileName,

[in]long LimitDaysCrypt,

[in]long LimitDaysDecrypt);


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

Описаниеиспользуемыхпараметров:

algorithmCryptFileName– имя выходногофайла с алгоритмомшифрования.

algorithmDecryptFileName– имя выходногофайла с алгоритмомрасшифрования.

LimitDaysCrypt– количестводней, в течениикоторых будутфункционироватьсгенерированныйалгоритм шифрования.

LimitDaysDecrypt– количестводней, в течениикоторых будутфункционироватьсгенерированныйалгоритмрасшифрования.


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


interfaceIProtectFile: IDispatch

{

[id(1),helpstring("method Create New File")]

HRESULTCreate(

[in] BSTR name,

[in] CreateModemode,

[in] BSTRuptFileNameForWrite,

[out, retval] short*handle);

[id(2),helpstring("method Open File")]

HRESULTOpen(

[in] BSTR name,

[in] BSTRuptFileNameForRead,

[in] BSTRuptFileNameForWrite,

[out, retval] short*handle);

[id(3),helpstring("method Close File")]

HRESULTClose(

[in] short handle);

[id(4),helpstring("method Write To File")]

HRESULTWrite(

[in] short handle,

[in] VARIANT buffer,

[out, retval] long*written);

[id(5),helpstring("method Read From File")]

HRESULTRead(

[in] short handle,

[out] VARIANT*buffer,

[out, retval] long*read);

[id(6),helpstring("method Write String To File")]

HRESULTWriteString(

[in] short handle,

[in] BSTR buffer,

[out, retval] long*written);

[id(7),helpstring("method Read String From File")]

HRESULTReadString(

[in] short handle,

[out] BSTR *buffer,

[out, retval] long*read);

[id(8),helpstring("method From File")]

HRESULTFromFile(

[in] short handle,

[in]BSTR FileName,

[out, retval] long*read);

[id(9),helpstring("method To File")]

HRESULTToFile(

[in] short handle,

[in] BSTR FileName,

[out, retval] long*written);

};


Опишемфункции в данноминтерфейсе.


HRESULTCreate(

[in]BSTR name,

[in]CreateMode mode,

[in]BSTR uptFileNameForWrite,

[out,retval] short *handle);


ФункцияCreateслужит длясоздания новыхзашифрованныхфайлов. Посколькуво вновь созданныйфайл можнотолько писать,то функциинеобходим дляработы толькофайл с алгоритмомшифрования.Имя файла сэтим алгоритмомпередаетсятретьим параметроми являетсяобязательным.Параметр modeимеет тип CreateMode,для чего онслужит, былосказано ранее.При успешномсоздании файл,в handleвозвращаетсяего дескриптор.По окончанииработы с файлом,его обязательнонужно закрыть,используяфункцию Close.

Описаниеиспользуемыхпараметров:

name– имя создаваемогофайла.

mode– тип создаваемогофайла (см. ранееописание типаCreateMode)

uptFileNameForWrite– имяфайласалгоритмомшифрования.

handle– возвращаемыйдескрипторсозданногофайла.


HRESULTOpen(

[in]BSTR name,

[in]BSTR uptFileNameForRead,

[in]BSTR uptFileNameForWrite,

[out,retval] short *handle);


ФункцияOpenоткрывает ужеранее созданныйзашифрованныйфайл. Файл можетбыть открыткак для чтениятак и для записи.После чегопроизводитьс ним можнотолько однуиз двух операций- чтение илизапись данных.Это обусловленотем, что записив файле представляютсобой блокиразличногоразмера. Даннаяособенностьявляется следствиемнеобходимостихранения такоготипа данных,как VARIANT.Таким образом,запись к даннымв файле можетбыть толькопоследовательная.И если послеоткрытия файлапроизвестив него запись,то прочитатьстарые данныеиз него будетуже невозможно.Можно сказать,что открытиефайла для записиэквивалентноего созданию,за парой исключений.Первое исключениесостоит в том,что при открытиифайла не указываетсяего тип. То естьнет необходимостиуказывать,следует паковатьданные передшифрованиемили нет. Информацияо типе беретсяиз уже существующегофайла. Второесостоит в том,что для открытияфайла, в отличииот создания,обязательнонеобходим файлс алгоритмомрасшифрования.Режим открытияфайла зависитот того, указанли файл с алгоритмомшифрования.Имя файла салгоритмомрасшифрованияявляется обязательнымпараметром.Файл с алгоритмомрасшифрования– нет. Если онне будет указан,то из такогофайла возможнобудет толькочтение. Еслиуказан, то будетвозможно какчтение, так изапись. Приуспешном открытиифайла в handleвозвращаетсядескрипторэтого файла.По окончанииработы с файломего обязательнонужно закрыть,используяфункцию Close.

Описаниеиспользуемыхпараметров:

name– имя открываемогофайла.

uptFileNameForRead– имя файла салгоритмомрасшифрования.

uptFileNameForWrite– имя файла салгоритмомшифрования.

handle– возвращаемыйдескриптороткрытогофайла.


HRESULTClose(

[in]short handle);


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

Описаниеиспользуемыхпараметров:

handle– дескрипторзакрываемогофайла.


HRESULTWrite(

[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– возвращаетразмер записанныхданных в байтах.


HRESULTRead(

[in]short handle,

[out]VARIANT *buffer,

[out,retval] long *read);


ФункцияReadчитает из файладанные и возвращаетих в виде переменнойтипа VARIANT.Чтение производитсяиз файла связанногос дескриптором,передаваемогов параметреhandle.В возвращаемомзначении readпосле завершенияработы функциибудет указаноколичествопрочитанныхиз файла байт.

Описаниеиспользуемыхпараметров:

handle– дескрипторфайла для чтения.

buffer– возвращаемыеданные.

read– возвращаетразмер прочитанныхданных в байтах.


HRESULTWriteString(

[in]short handle,

[in]BSTR buffer,

[out,retval] long *written);


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

Описаниеиспользуемыхпараметров:

handle– дескрипторфайла для записи.

buffer– записываемаястрока.

written– возвращаетразмер записанныхданных в байтах.


HRESULTReadString(

[in]short handle,

[out]BSTR *buffer,

[out,retval] long *read);

ФункцияReadStringслужит длячтения строкииз зашифрованногофайла.

Описаниеиспользуемыхпараметров:

handle– дескрипторфайла для чтения.

buffer– возвращаемаястрока.

read– возвращаетразмер прочитанныхданных в байтах.


HRESULTFromFile(

[in]short handle,

[in]BSTR FileName,

[out,retval] long *read);


ФункцияFromFileпозволяетзаписать взашифрованныйфайл данные,прочитанныеиз другогофайла. Иначеговоря, даннаяфункция сохраняетцеликом произвольныйфайл в зашифрованномфайле. Это можетбыть удобно,если, например,следует сохранитьи зашифроватьнабор картинокв формате jpg.Если бы даннаяфункция отсутствовала,то пришлосьбы вначалепрограммносчитывать этифайлы в память,а уже затемзаписыватьв зашифрованныйфайл. Чтобыоблегчитьзадачу программистуи была созданаэта функция.Обратным действием– извлечениемфайла из зашифрованногохранилища –занимаетсяфункция ToFile.В результатеполучаетсяискомый файлв незашифрованномвиде. Это можетпоказатьсяслабым местомв организациизащиты. Но вэтом есть смыслс точки зренияудобства адаптацииуже существующихпрограммныйкомплексовобучения итестирования.Сразу хочетсязаметить, чтоесли есть желаниеобойтись безвременныхфайлов в незашифрованномвиде, то никакихсложностейнет. Рассмотримна примере jpgфайла. Достаточнозаписать такойфайл в зашифрованномвиде, используяфункцию Write.Это достаточнопросто, так кактип VARIANTможет хранитьмассивы байт.В дальнейшемэтот массивбайт будетвозможнонепосредственносчитать в памятьи отобразитьна экране, неприбегая квременным фаламне диске. Нодело в том, чточасто это требуетсущественнойдоработки ужесуществующегопрограммногообеспечения.И проще, по крайней,мере на начальномэтапе внедрениясистемы защиты,за счет некоторогопонижениястепени надежности,быстро модифицироватьуже имеющуюсяпрограмму. Этаможет бытьвесьма важныммоментом. Кактолько файлбудет отображенна экране, этотвременный файлможно тут жестереть.

Описаниеиспользуемыхпараметров:

handle– дескрипторфайла для чтения.

FileName– имя файладобавляемогов зашифрованноехранилище.

read– возвращаетразмер прочитанныхданных в байтах.


HRESULTToFile(

[in]short handle,

[in]BSTR FileName,

[out,retval] long *written);


ФункцияToFileпроизводитобратное действиеотносительноFromFile.Она извлекаетфайл из хранилища.

Описаниеиспользуемыхпараметров:

handle– дескрипторфайла для чтения.

FileName– имя извлекаемогофайла.

written– возвращаетразмер записанныхданных в байтах.


ИнтерфейсIProtectConformityобъединяетнабор вспомогательныхфункций, призванныхоблегчитьиспользованиесистемы с большимколичествомфайлов, с алгоритмамии зашифрованнымиданными. Например,возьмем АРМпреподавателя.В этой системеможет бытьбольшое количестворазличныхданных, связанныхс определеннымистудентами.Если эти данныезашифрованы,то необходимознать, какимименно файломс алгоритмомэто сделано.Все эти взаимосвязинеобходимохранить. В случае,если такаясистема написанас использованиемСУБД, сложностейвозникнутьне должно. Еслиже нет, то придетсявносить некоторуюдополнительнуюфункциональность,которая являетсяподмножествомвозможностиСУБД. Чтобыоблегчитьадаптацию такихпроектов, неиспользующихБД, предназначеныфункции описываемогоинтерфейса.Фактически,они позволяютстроить и работатьс таблицамисоответствий.Такая таблицапредставляетсобой наборпар, содержащийимя зашифрованногофайла и имясоответствующегофайла алгоритмадля шифрованияили расшифрования.В такой таблицевозможен поиск,как по именизашифрованногофайла, так и поимени файлас алгоритмом.В дальнейшемфайлы, хранящиеинформациюо соответствиифайлов с даннымии соответствующимифайлами салгоритмами,будем называтьфайлами соответствий.Отметим также,что файлысоответствийтоже подвергаютсяшифрованию.


interfaceIProtectConformity: IDispatch

{

[id(1),helpstring("method Create Conformity File")]

HRESULTCreateConformityFile(

[in] BSTR name,

[in] BSTRuptFileNameForRead,

[in] BSTRuptFileNameForWrite,

[in] BSTRArrayOfStrings);

[id(2),helpstring("method Easy Create Conformity File")]

HRESULTEasyCreateConformityFile(

[in] BSTR name,

[in] BSTRuptFileNameForCreate,

[in] BSTRArrayOfStrings);

[id(3),helpstring("method Read Conformity File")]

HRESULTReadConformityFile(

[in] BSTR name,

[in] BSTRuptFileNameForRead,

[out, retval] BSTR*ArrayOfStrings);

[id(4),helpstring("method Get UptAlgName by FileName")]

HRESULTGetAlgName(

[in] BSTR Strings,

[in] BSTRSearchName,

[out, retval] BSTR*ResultStr);

[id(5),helpstring("method Get FileName by UptAlgName")]

HRESULTGetDataName(

[in] BSTR Strings,

[in] BSTRSearchName,

[out, retval] BSTR*ResultStr);

[id(6),helpstring("method Get UptAlgName by FileName From File")]

HRESULTGetAlgFromFile(

[in] BSTR FileName,

[in] BSTRuptFileNameForRead,

[in] BSTRSearchName,

[out, retval] BSTR*ResultStr);

[id(7),helpstring("method Get FileName by UptAlgName From File")]

HRESULTGetDataFromFile(

[in] BSTR FileName,

[in] BSTRuptFileNameForRead,

[in] BSTRSearchName,

[out, retval] BSTR*ResultStr);

};


Теперьопишем каждуюиз функцийинтерфейсаIProtect.


HRESULTCreateConformityFile(

[in]BSTR name,

[in]BSTR uptFileNameForRead,

[in]BSTR uptFileNameForWrite,

[in]BSTR ArrayOfStrings);


ФункцияCreateConformityFileсоздает новыйфайл соответствийи записываетв него соответствующуютаблицу. Таблицапредается ввиде однойстроки, в которойпоследовательнозаписаны именафайлов. Всенечетные –имена файловс данными, всечетные – соответствующиеалгоритмышифрованияили расшифрования.Имена должныбыть заключеныв двойные кавычки.Это связанос тем, что иначеневозможноработать сименами файлов,содержащимипробелы. Междукавычкой вконце имениодного файлаи кавычкойперед именемвторого можетстоять произвольноеколичествопробелов исимволов табуляцииили возвратакаретки и переносастроки. Поддержкаодновременногохранения информациикак о файлахдля шифрования,так и для расшифрованияне осуществлена.Это сделанопо двум причинам.Во-первых, совсемне сложно завестидва файла, аинтерфейсфункций и ихколичествосущественносокращается.Во-вторых, даннаяфункциональностьсоответствиядвух файловможет бытьприменена идля другихцелей. Хочетсясделать ееболее абстрактной.Следует датьследующий советесли для шифрованиябольшого количествафайлов однималгоритмом:удобно создатьсоответствующийкаталог, в которыйпомещаютсяшифруемыефайлы, записатьв файл соответствийимя этого каталогаи соответствующийалгоритмшифрования/расшифрованиядля работы сфайлами в этомкаталоге.

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

Описаниеиспользуемыхпараметров:

name– имя создаваемогофайла, для храненияинформациио соответствии.

uptFileNameForRead– имя создаваемогофайла с алгоритмомрасшифрования.

uptFileNameForWrite– имя создаваемогофайла с алгоритмомшифрования.

ArrayOfStrings– строка синформациейо соответствиях.


HRESULTEasyCreateConformityFile(

[in]BSTR name,

[in]BSTR uptFileNameForCreate,

[in]BSTR ArrayOfStrings);


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

name– имя создаваемогофайла, для храненияинформациио соответствии.

uptFileNameForCreate– имя файла салгоритмомшифрования.

ArrayOfStrings– строка синформациейо соответствиях.


HRESULTReadConformityFile(

[in]BSTR name,

[in]BSTR uptFileNameForRead,

[out,retval] BSTR *ArrayOfStrings);


ФункцияReadConformityFileчитает содержимоефайла соответствийи возвращаетего в виде строки.Строка имееттот же формат,что и передаваемаянапример вфункциюCreateConformityFile.

Описаниеиспользуемыхпараметров:

name– имя зашифрованногофайла cинформациейо соответствиях.

uptFileNameForRead– имя файла салгоритмомрасшифрования.

ArrayOfStrings– возвращаемаястрока с информациейо соответствиях.


HRESULTGetAlgName(

[in]BSTR Strings,

[in]BSTR SearchName,

[out,retval] BSTR *ResultStr);


ФункцияGetAlgName,используя имяфайла с данными,возвращаетсоответствующийалгоритм шифрованияили расшифрования.Поиск производитсяв переданнойстроке. Форматстроки эквивалентенформату, с которымработают идругие функции.Например,EasyCreateConformityFile илиReadConformityFile.

Описаниеиспользуемыхпараметров:

Strings– строка синформациейо соответствиях.

SearchName– имя файла сданными, длякоторого будетпроизведенпоиск соответствующегоалгоритма.

ResultStr– возвращаемоеимя файла салгоритмом.


HRESULTGetDataName(

[in]BSTR Strings,

[in]BSTR SearchName,

[out,retval] BSTR *ResultStr);


ФункцияGetDataName,используя имяфайла с алгоритмом,возвращаетимя соответствующегофайла с данными.Поиск производитсяв переданнойстроке. Форматстроки эквивалентенформату, с которымработаю и другиефункции. НапримерEasyCreateConformityFile илиReadConformityFile.

Описаниеиспользуемыхпараметров:

Strings– строка синформациейо соответствиях.

SearchName– имя файла салгоритмом,для которогобудет произведенпоиск соответствующегофайла с данными.

ResultStr– возвращаемоеимя файла сданными.


HRESULTGetAlgFromFile(

[in]BSTR FileName,

[in]BSTR uptFileNameForRead,

[in]BSTR SearchName,

[out,retval] BSTR *ResultStr);


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

Описаниеиспользуемыхпараметров:

FileName– имя файла сзашифрованнойинформациейо соответствиях.

uptFileNameForRead– файл с алгоритмомрасшифрования.

SearchName– имя файла сданными, длякоторого будетпроизведенпоиск соответствующегоалгоритма.

ResultStr– возвращаемоеимя файла салгоритмом.


HRESULTGetDataFromFile(

[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(PortableExecutables).Защита исполняемыхмодулей основанана их шифровании.Особенностьюутилиты ProtectEXEявляется то,что она шифруеткаждый исполняемыйфайл уникальнымполиморфнымалгоритмом.Это затрудняетвозможностьиспользованияпрограммноговзломщика,основанногона модификацииопределенныхкодов в программе.Посколькукаждый исполняемыйфайл зашифровансвоим методом,то и модифицироватьих единым методомневозможно.Утилита ProtectEXE.EXEне позволяетзащититьсяот динамическогомодифицированияв памяти. Этослишком сложнои не может бытьдостигнутобез существеннойпеределкиисходноготекста самойзащищаемойпрограммы. Нов рамках защитыдистанционныхсредств обучениятакая защитадолжна бытьдостаточноэффективна,так как созданиевзламывающейпрограммыэкономическимало целесообразно,а следовательнои скорее всегоне будет осуществлено.

МодульProtectEXE.EXEимеет два возможныхрежима запуска.Первый режимпредназначендля генерациизашифрованногофайла из указанногоисполняемогомодуля. Второйрежим служитнепосредственнодля запусказащищенногомодуля.

Опишемэтап созданиязашифрованногофайла. Для созданиязашифрованногофайла необходимозапуститьProtectEXE.EXE,указав в качествепараметра имяшифруемогоисполняемогофайла. Можноуказать нетолько имя, нои путь. В результатебуду сгенерированыдва файла. Еслибыло указанотолько имя, тофайлы будутрасполагатьсяв текущем каталоге.Если был указанпуть к файлу,то сгенерированныефайлы будутсозданы в томже каталоге,где расположени шифруемыйфайл. Первыйфайл будетиметь расширениеupb. Он представляетсобой непосредственнозашифрованныйисполняемыйфайл. Второйфайл будетиметь расширениеupu. Он представляетсобой ключ,необходимыйдля расшифровкиисполняемогофайла. При разработкеProtectEXEбыло приняторешение хранитьзашифрованныйфайл и ключ дляего расшифровкене в единомфайле, а раздельно.Это было сделанос целью большейгибкости. Еслихранить всев одном файле,это будет означать,что его всегдабудет возможнозапустить.Раздельноехранение ключапозволяетсоздаватьсистему, гдезапуск определенныхпрограмм будетзапрещен. Например,программадистанционногообучения можетпозволятьзапускать наборопределенныхпрограмм толькотогда, когдабудет выполненряд условий.Допустим, послесдачи определенногонабора работ.Когда определенныеработы будетсданы и защищены,АРМ преподавателявыдает студентунеобходимыедля дальнейшейработы ключевыефайлы. Можнобыло бы, конечно,выдавать сразурасшифрованныйбинарный файл,но программаможет бытьдостаточнобольшой, и этопросто нерационально.И, тем более,тогда нет никакихсложностейскопироватьее другомустуденту, которомуона еще не должнабыть выдана.

Теперьопишем второйрежим работы.Это непосредственнозапуск зашифрованногомодуля. Для егозапуска необходимозапуститьProtectEXE, указав вкачестве параметрапуть и имя зашифрованногофайла с расширениемupb.Если будетнайден ключевойфайл с тем жеименем, но срасширениемupu,то программабудет запущена.При этом будетсоздан временныйфайл с расширениемexe.Он будет располагатьсяв том же каталоге,где нахолодятсяфалы с расширениемupbи upu.Этот файл являетсявременным ибудет удаленпосле завершенияработы программы.Данный файл,хоть и носитрасширениеexe,не являетсяисполняемымфайлом. В чемможно убедиться,попытавшисьзапустить его.Результатомбудет его зависание.Поэтому неследует бояться,что это расшифрованныйфайл, и студентсможет скопироватьего, когда онбудет создан.


4.4.Описаниеиспользованиясистемы защитына примерах

4.4.1.Подключениемодуля защитык программена языке VisualC++

Распишемшаги, которыенаобходимопроделать,чтобы подключитьCOMмодуль Uniprotк программе,написаннойна VisualC++.

  1. Создайтеновый или откройтеуже существующийпроект.

  2. Создайтеновую папкув каталоге спроекта иливыберете ужесуществующуюи скопируйтев нее необходимыедля подключениябиблиотекифайлы. Это файлы:export.h,export.cpp,Uniprot.tlb.

  3. ОткройтеMFC ClassWizard. Дляэтого выбиретев меню пункт
    View->ClassWizard.

  4. Нажмитена кнопку AddClassи выберетепункт "From atypelibrary…".

  5. Укажитепуть к файлуUniprot.tlb и откройтеего.

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

  7. Закройтедиалог MFCClassWizard.

  8. Включитев проект файлыexport.h,export.cpp.

  9. Добавитьinclude"export.h"в те модуле,где вы планируетеиспользоватьбиблиотекуUniprot.

  10. Проверьте,что у вас инициализируетсяработа с COM.То есть вызываетсяфункция CoInitialize.

  11. Теперьвы можете работатьс библиотекойCOMнапример так.

IProtect ProtectObj;

IProtectFileProtectFileObj;

ProtectObj.CreateDispatch(UniprotLibID);

ProtectFileObj.CreateDispatch(UniprotLibID);

LPDISPATCHpDisp = ProtectFileObj.m_lpDispatch;

HRESULT hr = pDisp->QueryInterface(

IProtectFileIntarfaceID,

(void**)&ProtectFileObj.m_lpDispatch);

VERIFY(hr == S_OK);


4.4.2.Подключениемодуля защитык программена языке VisualBasic

Распишемшаги, которыенаобходимопроделать,чтобы подключитьCOMмодуль Uniprotк программе,написаннойна VisualBasic.

  1. Создайтеновый или откройтеуже существующийпроект.

  2. Создайтеновую папкув каталоге спроекта иливыберете ужесуществующуюи скопируйтев нее необходимыйдля подключениябиблиотекифайл. Это файл:Uniprot.tlb.

  3. Откройтедиалог References.Для этого выбиретев меню пункт
    Project->References.

  4. Нажмитекнопку Browse.

  5. Укажитефайл Uniprot.tlbи откройтеего.

  6. Поставьтев списке галочкунапротив появившейсястроки Uniprot1.0 TypeLibraryи нажмите Ok.

  7. Теперьвы можете работатьс библиотекойCOMнапример так.

Dim handle AsInteger

Dim obj As Newprotect


Dim ver As Integer

Dim strInfo AsString

obj.GetInfo ver,strInfo

Dim s As String

s= "Version:" + Str(ver / 256) + "." +

Str((ver Mod256) / 16) + Str(ver Mod 16)

s = s + Chr(13) +"Info:" + strInfo

MsgBox s


Dim file AsIProtectFile

Set file = obj

handle =file.Create(FileName, Default, cryptUPT)


4.4.3.Пример использованиямодуля защитыв программена языке VisualBasic


Рассмотримнесколькодемонстрационныхпрограммах.Представим,что у нас существуеткомплекс, состоящийиз двух частей.Первая из которыхпредназначенадля преподавателя,а другая – длястудента. Вдальнейшембудем называтьих соответственно"АРМ преподавателя"и "АРМ студента".АРМ преподавателяпредназначенадля составлениявопросов ипросмотрарезультатовтестирования.А АРМ студентапредназначенадля контролязнаний. Естественно,примеры данныхпрограмм будуточень упрощены.

Дляначала приведемтекст программыАРМ преподавателябез использованиязащиты. На рисунке8 показан еепользовательскийинтерфейс.

Private SubEdit_Click()

orm1.ole_doc.DoVerb

End Sub


Private SubForm_Load()

Form1.ole_doc.Format= "Rich Text Format"

End Sub


PrivateSub Load_Click()

Open"c:\temp\temp.rtf" For Input As #1

Dim str, tmp

Do While NotEOF(1)

Input #1, tmp

str = str +tmp

Loop

Close #1

Form1.ole_doc.DoVerbvbOLEDiscardUndoState

Form1.ole_doc.DataText= str

Form1.ole_doc.Update

End Sub


Private SubSave_Click()

Dim msg

Form1.ole_doc.DoVerbvbOLEDiscardUndoState

msg =Form1.ole_doc.DataText

Open"c:\temp\temp.rtf" For Output As #1

Print #1, msg

Close #1

End Sub


Private SubViewResult_Click()

Open"c:\temp\result.txt" For Input As #1

Dimn As Integer

Input #1, n

Close #1

result = n

End Sub

Рисунок8. ИнтерфейсАРМ преподавателя


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

Private SubSaveResult(a)

Open"c:\temp\result.txt" For Output As #1

Print #1, a

Close #1

End


End Sub

Private SubCommand1_Click(Index As Integer)

SaveResult (2)

End Sub


Private SubCommand2_Click()

SaveResult(2)

End Sub


Private SubCommand3_Click()

SaveResult (5)

End Sub


Private SubCommand4_Click()

SaveResult (2)

End Sub


Private SubForm_Load()

Form1.ole_doc.Format= "Rich Text Format"

Open"c:\temp\temp.rtf" For Input As #1

Dim str, tmp

Do While NotEOF(1)

Input #1, tmp

str = str +tmp

Loop

Close #1

Form1.ole_doc.DoVerbvbOLEDiscardUndoState

Form1.ole_doc.DataText= str

Form1.ole_doc.Update

End Sub


Рисунок9. ИнтерфейсАРМ студента


Каквидно эта программаочень проста.Она простовыводит текствопроса и ждетответ. Послечего записываетоценку в файл.На рисунке 10показано, каквыглядит файлс результатом.

Рисунок10. Файл с незашифрованнымрезультатом


Естественно,такая системане выдерживаетникакой критикис точки зрениязащиты. Во-первых,файл с вопросомпредставляетиз себя простойRTF-файл. Конечно,если эти файлыбудут хранитьсяв защищеннойбазе, то проблемне возникнет.Мы же предполагаем,что пока онихранятся открыто.Предположим,что таких файловмного, и недопустимо,чтобы студентимел к ним доступ.Соответственно,это одно измест, где потребуетсямодуль защиты.Второе, пожалуй,еще более важноеместо – этофайл с результатом.На данный моментэто простотекстовый файл,с числом, обозначающийоценку. Хранениерезультатав таком видекак просто, таки недопустимо.

Теперь,используямодуль зашиты,мы исправимперечисленныенедостатки.Для началапокажем новыйинтерфейспользователяи объяснимизменения.Кнопки "Загрузитьтекст", "Сохранитьтекст" остались,но теперь программабудет работатьс зашифрованнымиданными. Кнопка"Импорт старыхданных" предназначенадля чтениянезашифрованногофайл с вопросом.

Кнопка"Сгенерироватьпакет" генерирует4 алгоритма.Первая параалгоритмовшифрования/расшифрованияиспользуетсядля записи/чтенияфайла с вопросом.При этом студентудостаточноотдать толькофайл с алгоритмомрасшифрования.Вторая параиспользуетсяпри работе сфайлом, содержащимрезультаттестирования.Алгоритм шифрованияпредназначендля АРМ студента.Алгоритмрасшифрованияотносится кАРМ преподавателяи служи длярасшифрованияэтого файла.Передача студентутолько некоторыхалгоритмовповышает надежностьзащиты.

Новыйинтерфейс АРМпреподавателяизображен нарисунке 11.


Рисунок11. Новый интерфейсАРМ преподавателя


Рассмотрим,какие измененияпонадобилосьвнести в программу.Их совсем немного. Добавиласьглобальнаяперемереннаяobj. Она предназначенадля взаимодействияс COM-модулем.Глобальнойона быть совсемне обязана,просто это былосделано длякраткостипрограммы.Типом этойпеременныйявляется указательна интерфейсIProtect. Но использоватьэтот интерфейсдля шифрования/расшифрованияне представляетсявозможным.Поэтому, в дальнейшемobj будем преобразовыватьэтот указательк указателюна интерфейс IProtectFile.

Dim obj As Newprotect

Private SubEdit_Click()

Form1.ole_doc.DoVerb

End Sub

Private SubForm_Load()

Form1.ole_doc.Format= "Rich Text Format"

End Sub

Даннаяподпрограммапредназначенадля генерации4 алгоритмовшифрования/расшифрования.Для простотыона записываютсяво временнуюпапку. Причем,генерируемыеалгоритмы будутограниченыв использованиипо времени.Файл "c:\temp\crypt.upt" и"c:\temp\decrypt.upt" предназначеныдля работы сфайлом содержащимвопрос. Файл"c:\temp\cryptres.upt" и "c:\temp\decryptres.upt"предназначеныдля работы сфалом результата.Следовательнодля работыАРМ-преподавателянеобходимыфайлы "c:\temp\crypt.upt" ,"c:\temp\decrypt.upt" и "c:\temp\decryptres.upt".А для АРМ-студентанеобходимыфайлы "c:\temp\decrypt.upt","c:\temp\cryptres.upt".

Private SubGenerate_Click()

Dim days As Integer

days = DaysLimit

obj.GenerateTimeLimitUPTfiles"c:\temp\crypt.upt", "c:\temp\decrypt.upt", days

obj.GenerateTimeLimitUPTfiles"c:\temp\cryptres.upt", "c:\temp\decryptres.upt",days

End Sub

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

Private SubImport_Click()

Open"c:\temp\temp.rtf" For Input As #1

Dim str, tmp

Do While Not EOF(1)

Input #1, tmp

str = str + tmp

Loop

Close #1

Form1.ole_doc.DoVerbvbOLEDiscardUndoState

Form1.ole_doc.DataText= str

Form1.ole_doc.Update

End Sub

Вотновая подпрограммачтения текставопроса изфайла. Дадимкомментариик некоторымстрочкам.

Dimfile As IProtectFile– объявляетуказатель наинтерфейсIProtectFile, которыйпозволяетшифровать/расшифровыватьфайлы.

handle= file.Open("c:\temp\temp.dat", "c:\temp\decrypt.upt","c:\temp\crypt.upt")– открываемфайл с вопросоми сохраняемдескриптороткрытогофайла.

readSize= file.Read(handle, v)– читаем переменнуютипа Variant, котораяна самом делебудет представлятьиз себя строку.

file.Close(handle)– закрываетфайл.

Private SubLoad_Click()

Dim handle AsInteger

Dim file AsIProtectFile

Set file = obj

handle =file.Open("c:\temp\temp.dat", "c:\temp\decrypt.upt","c:\temp\crypt.upt")

Dim readSize As Long

Dim v As Variant

readSize= file.Read(handle, v)

Dim str As String

str = v

Form1.ole_doc.DoVerbvbOLEDiscardUndoState

Form1.ole_doc.DataText= str

Form1.ole_doc.Update

file.Close (handle)

End Sub


Воткак теперьвыглядит новаяподпрограммасохранениявопроса в файл.

PrivateSub Save_Click()

Dim handle AsInteger

Dim file AsIProtectFile

Set file = obj

handle =file.Create("c:\temp\temp.dat", Default,"c:\temp\crypt.upt")

Dim writeSize AsLong

Dim v As Variant

Dim str As String

str =Form1.ole_doc.DataText

v = str

writeSize =file.Write(handle, v)

file.Close (handle)

End Sub


Ипоследнее, этоновая подпрограммачтения файловс результатомтестирования.

Private SubViewResult_Click()

Dim handle AsInteger

Dim file AsIProtectFile

Set file = obj

handle= file.Open("c:\temp\result.dat", "c:\temp\decryptres.upt","c:\temp\cryptres.upt")

Dim readSize As Long

Dim v As Variant

readSize =file.Read(handle, v)

Dim str As String

result = v

file.Close (handle)

End Sub


Внешнийвид АРМ студентане изменился.Приведем толькотекст программы.

Dim obj As Newprotect

Private SubSaveResult(a)

Dimhandle As Integer

Dim file AsIProtectFile

Set file = obj

handle =file.Create("c:\temp\result.dat", Default,"c:\temp\cryptres.upt")

Dim writeSize AsLong

Dim v As Variant

Dim str As String

str =Form1.ole_doc.DataText

v = a

writeSize =file.Write(handle, v)

file.Close (handle)

End

End Sub


Private SubCommand1_Click(Index As Integer)

SaveResult (2)

End Sub


Private SubCommand2_Click()

SaveResult (2)

End Sub


Private SubCommand3_Click()

SaveResult (5)

End Sub


Private SubCommand4_Click()

SaveResult (2)

End Sub


Private SubForm_Load()

Form1.ole_doc.Format= "Rich Text Format"

Dim handle AsInteger

Dim file AsIProtectFile

Set file = obj


handle =file.Open("c:\temp\temp.dat", "c:\temp\decrypt.upt","c:\temp\crypt.upt")

Dim readSize As Long

Dim v As Variant

readSize =file.Read(handle, v)

Dim str As String

str = v


Form1.ole_doc.DoVerbvbOLEDiscardUndoState

Form1.ole_doc.DataText= str

Form1.ole_doc.Update


file.Close (handle)

End Sub


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

Рисунок12. Файлс зашифрованнымрезультатом


4.4.4.Пример использованияпрограммыProtectEXE.exe

Вкачестве примераприведем кодна VisualС++, которыйпроизводитшифрованиеисполняемогофайла, а затемкод, производящийзапуск зашифрованногофайла. Обе функциипринимают навходе имя файлас расширениеexe.Для большейясности рекомендуетсяознакомитьсяс приведеннымранее описаниемпрограммы ProtectEXE.

voidCreateEncryptedModule(const CString &FileName)

{

CStringLine(_T("ProtectExe.exe"));

Line += FileName;

STARTUPINFOStartupInfo;

memset(&StartupInfo,0, sizeof(StartupInfo));

StartupInfo.cb= sizeof(StartupInfo);

PROCESS_INFORMATIONProcessInformation;

if(!CreateProcess(Line,NULL, NULL, NULL, FALSE, 0,

FALSE,NULL, &StartupInfo,

&ProcessInformation))

throw _T("Errorrun ProtectExe.exe");

WaitForInputIdle(ProcessInformation.hProcess,

INFINITE);

WaitForSingleObject(ProcessInformation.hProcess,

INFINITE);

CloseHandle(ProcessInformation.hProcess);

DeleteFile(FileName);

}


voidRunEncryptedModule(constCString &FileName)

{

CStringEncryptedFileName(FileName);

EncryptedFileName= EncryptedFileName.Mid(0,FileName.GetLength()- 3);

EncryptedFileName+=_T("upb");

CStringLine(_T("ProtectExe.exe"));

Line+= EncryptedFileName;

STARTUPINFOStartupInfo;

memset(&StartupInfo,0, sizeof(StartupInfo));

StartupInfo.cb =sizeof(StartupInfo);

PROCESS_INFORMATIONProcessInformation;

if(!CreateProcess(Line,NULL, NULL, NULL, FALSE, 0,

FALSE,NULL, &StartupInfo, &ProcessInformation))

throw _T("Errorrun ProtectExe.exe");

WaitForInputIdle(ProcessInformation.hProcess,INFINITE);

WaitForSingleObject(ProcessInformation.hProcess,INFINITE);

CloseHandle(ProcessInformation.hProcess);

}

4.5.Общие рекомендациипо интеграциисистемы защиты


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

1.Перед началомработ по модификациисуществующегопрограммногообеспеченияс целью интеграциисистемы защитырекомендуетсятщательноознакомитьсяс приведеннойдокументациейи с примерамипо использованиюразличныхфункций. Такженеобходимымтребованиемперед началомработ, являетсябазовые навыкиработы с технологиейCOM.Если вы не знакомыс технологиейCOM,то здесь можнопорекомендоватьв качествелитературыпо данной темеследующиекниги: МодельCOMи применениеATL3.0 [31], СущностьтехнологииCOM.[33],ProgrammingDistributed Applications with COM and Microsoft Visual Basic 6.0[34].

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

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

4.Еще одной изрекомендацийбудет созданиесистемногожурнала. Поэтому поводурекомендуетсяознакомитьсясо статьейОганесяна А.Г. " Проблема«шпаргалок»или как обеспечитьобъективностькомпьютерноготестирования?"[28].

5.Создавая АСДО,позаботьтесьо дублированииинформации.В противномслучае, уничтожение,например, базыс данными осданных работахможет иметьвесьма тяжелыепоследствия.Это – совет неотносится кзащите информации,но может помочьвесьма повыситьнадежностьсистемы в целом.

ОСНОВНЫЕВЫВОДЫ И РЕЗУЛЬТАТЫ


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

2.На основе анализа,предложен рядмер, позволяющийповысить защищенностьАСДО.Разработаныпрограммныесредства,предназначенныедля интеграциив уже существующиеобучающиесистемы, с цельюих защиты прииспользованиивнедовереннойвычислительнойсреды.

3.В разработанномпрограммномобеспечениибыли использованыновые технологиишифрованияданных. Полностьюисключенанеобходимостьиспользованияаппаратныхсредств.

4.Разработанасистема защиты,руководстводля программиста,набор тестовыхпримеров ирекомендациипо ее применению.Созданнаясистема былаинтегрированав уже существующийкомплекс AquariusEducation4.0, разработанныйна кафедре АТМ.


СПИСОКИСПОЛЬЗОВАННЫХИСТОЧНИКОВ


1.Аунапу Т.Ф.,Веронская М.В.Автоматизацияобучения спозиций системногоанализа//Управлениекачествомвысшего образованияв условияхмногоуровневойподготовкиспециалистови внедренияобразовательныхстандартов:Тез. докладовреспубликанскойнаучно-методическойконферен­ции.—Барнаул: Алт.гос. техн. ун-т,1996. —С.5 — 6. д

2.Брусенцов Н.П.,Маслов С.П., РамильАльваресX.Микроко­мпьютернаясистема «Наставник».—М.: Наука,1990. — 224с.

3.КондратоваО.А. Психологическиетребованияк проектированиюкомпьютерныхучебных средстви систем обучения// Проблемыгуманизациии новые методыобучения всистеме инженерногообразования:Тез. докл. межвузовскойнаучно-практическойконференции.— Новокузнецк:Сиб. Гос. горно-металлургическаяакадемия,1995. — С.78 — 80.

4.Федеральнаяцелевая программа«Развитиеединой образовательнойинформационнойсреды на2002 — 2006годы» (проект).—М.: Миноб­разования,2001. — 35с.

5.Кручинин В.В.,Ситникова Е.А.Проблема защитыкомпьютерныхэкзаменационныхпрограмм в ТМЦДО// Современноеобразование:массовостьи качество.Тез. докл. региональнойнаучно-методическойконференции.— Томск:ТУСУР,2001. — С.144.

6.Махутов Б.Н.,Шевелев М.Ю.Защита электронныхучебников вдистанционномобучении//ОбразованиеXXIвека: инновационныетехнологии,диагностикаи управлениев условияхинформатизациии гуманизации:МатериалыIIIВсероссийскойнаучно-методическойконференциис международнымучастием.—Красноярск:КГПУ,2001. —С.106 — 108.

7.Раводин О.М.Проблемы созданиясистемы дистанционногообразованияв ТУСУРе//Дистанционноеобразование.Состояние,проблемы,перспективы.Тез. докл. научно-методическойконференции,Томск,19ноября Э1997г.—Томск: ТУ СУР,1997. —С.19 — 25.

8.Шевелев М.Ю.Автоматизированныйвнешний контрольсамосто­ятельнойработы студентовв системедистанционногообразования/У Дистанционнообразование.Состояние,проблемы,перспективы.Тез. докл.научно-методическойконференции.—Томск: ТУСУР,1997. —С.49.

9.Шевелев М.Ю.Прибор длядихотомическойоценки семантическихсообщений вавтоматизированныхобучающихсистемах//Современныетехника и технологии.Сб. статеймеждународнойнаучно-практическойконференции.—Томск: ТПУ,2000. —С.152.

10.Шевелев М.Ю.Программно-аппаратнаясистема контроляи защиты информации//Современноеобразование:массовостьи качество.Тез. докл.научно-методическойконференции1-2февраля2001г.—Томск: ТУСУР,2001.—С.99—100.

11.Шелупанов А.А.,Пряхин А.В. Анализпроблемы информациив системедистанционногообразования// Современноеобразование:массовостьи качество.Тез. докл. региональнойнаучно-методическойконференции.— Томск:ТУ СУР,2001. — С.159 — 161.

12. КацманЮ.Я. Применениекомпьютерныхтехнологийпри дистанционномобучении студентов// Тез. докладоврегиональнойнаучно методическойконференции"Современноеобразование:массовостьи качество".– Томск: ТУСУР,2001. – С.170 – 171.

13.Пресс-группаСГУ. Компьютер-экзаменатор.// Электронныйеженедельник"Закон. Финансы.Налоги." – 2000. –№ 11 (77).

14.БелокрыловаО.С. Использованиекурса дистанционногообучения наэкономическомфакультетеРГУ // Cовременныеинформационныетехнологиив учебном процессе:Тез. докл.Учебно-методическаяконференция.– Апрель 2000.

15.АлешинС.В. Принципыпостроенияоболочкиинформационно– образовательнойсреды CHOPIN// Новые информационныетехнологии: Тез. докл. Восьмаямеждународнаястуденческаяшкола семинар.– Крым: Алтайскийгосударственныйтехническийуниверситет,Май 2000.

16.ОганесянА.Г. Проблемаобратной связипри дистанционномобучении // Открытоеобразование.– 2002. – март.

17.ЗанимонецЮ.М., ЗиньковаЖ.Г. Проведениевсероссийскогокомпьютерноготестирования"Телетестинг-2000"в Ростовскомгосуниверсите// Современныеинформационныетехнологиив учебном процессе: Тез. докл.Учебно-методическаяконференция.– 2000. – апрель.

18.Сенцов,В.С. Программныйкомплекс тестовогоконтроля знаний«Тест» // Новыеинформационныетехнологии:Тез. докл. Восьмаямеждународнаястуденческаяшкола семинар.– Крым: Алтайскийгосударственныйтехническийуниверситет,Май 2000.

19.Мицель.А.А. Автоматизированнаясистема разработкиэлектронныхучебников //Открытое образование.– 2001. – май.

20.ЖолобовД.А. Генератормультимедиаучебников //Новые информационныетехнологии:Тез. докл. Восьмаямеждународнаястуденческаяшкола семинар.– Крым: Астраханскийгосударственныйтехническийуниверситет,Май 2000.

21.ВергазовР. И., Гудков П.А. Системаавтоматизированногодистанционноготестирования// Новые информационныетехнологии:Тез. докл. Восьмаямеждународнаястуденческаяшкола семинар.– Крым: Пензенскийгосударственныйуниверситет,Май 2000.

22.ЛожниковП. С. Распознаваниепользователейв системахдистанционногообразования:обзор //Educational Technology & Society. – 2001.–№4, http://ifets.ieee.org/russian/depository/v4_i2/html/4.html

23.РасторгуевС.П., Долгин А.Е.,Потанин М.Ю.Как защититьинформацию// Электронноепособие поборьбе с хакерами.http://kiev-security.org.ua

24.ЕрижоковА.А.ИспользованиеVMWare 2.0 // Публикацияв  сети ИНТЕРНЕТна сервере http://www.citforum.ru/operating_systems/vmware/index.shtml.

25.БаpичевС. Kpиптогpафиябез секретов.– М.: Наука, 1998. –105 с.

26.МаутовБ.Н. Защитаэлектронныхучебников наоснове программно-аппаратногокомплекса"Символ-КОМ"// Открытоеобразование.– 2001. – апрель.

27.Тыщенко О.Б.Новое средствокомпьютерногообучения -электронныйучебник // Компьютерыв учебном процессе.– 1999. – № 10. – С. 89-92.

28.Оганесян А. Г.,Ермакова Н. А.,Чабан К. О. Проблема«шпаргалок»или как обеспечитьобъективностькомпьютерноготестирования?// «Львіськаполітехніка».–2001. – №6. Публикацияв  сети ИНТЕРНЕТна сервереhttp://www.mesi.ru/joe/N6_00/oga.html.

29.Романенко В.В.Автоматизированнаясистема разработкиэлектронныхучебников. //Новые информационныетехнологиив университетскомобразовании:Тез. докл. Материалыседьмой МеждународнойНаучно-Методическойконференции.– Томск: ТомскийГосударственныйУниверситетСистем Управленияи Радиоэлектроники,Март 2000.

30.КасперскийЕ.В. Компьютерныевирусы: что этотакое и как сними бороться.– М.: СК Пресс,1998. – 288 с., ил.

31.ТрельсонЭ. Модель COMи применениеATL3.0: Пер. с англ. –СПб.БХВ-Петербург,2001. – 928 с.ил.

32.БаричевС. Г. и др. «Основысовременнойкриптографии».– М.: «Горячаялиния –Телеком»,2001 – 120 с.

33.Бокс.Д. СущностьтехнологииCOM.Библиотекапрограммиста.– СПб.: Питер,2001. – 400 с.: ил.

34.TedPattison. Programming Distributed Applications with COM and MicrosoftVisual Basic 6.0. – MicrosoftPress,1998. – 260 c. ISBN 1-57231-961-5




ТУЛЬСКИЙГОСУДАРСТВЕННЫЙУНИВЕРСИТЕТ


Направах рукописи


КарповАндрей Николаевич


ЗАЩИТАИНФОРМАЦИИВ СИСТЕМАХДИСТАНЦИОННОГООБУЧЕНИЯ СМОНОПОЛЬНЫМДОСТУПОМ


Направление553000- Системныйанализ и управление

Программнаяподготовка553005 –Системный

анализданных и моделейпринятия решений


АВТОРЕФЕРАТ

диссертациина соисканиестепени

магистратехники и технологии


Тула2004


Работавыполнена накафедре автоматикии телемеханики

Тульскогогосударственногоуниверситета


Научныйруководитель

д.т.н.БогатыревМ.Ю._____________


Консультатнт

к.т.н.проф. ТеличкоГ.Н._____________


Защитадиссертациисостоится 16июня 2004 г. в 10 ч. 00мин.


СекретарьГАК

кандидаттехническихнаук, доцентСпицын А.В.

ОБЩАЯХАРАКТЕРИСТИКАРАБОТЫ


Актуальностьтемы. Впоследнее времямного проблемразработчиками пользователямпрограммногообеспечениядоставляютпроблемыинформационнойбезопасности. Вопросызащиты информациивесьма обширны,поэтому в даннойработе будетрассмотреназащита автоматизированныхсистем дистанционногообучения (АСДО).Они являютсяудачным образцомсистем, функционирующихв режиме монопольногодоступа внедоверительнойсреды. Подмонопольнымдоступом понимаетсявозможностьпользователясовершать спрограммойлюбые действиябез внешнегоконтроля. Длясистем, функционирующихвне доверительнойсреды, характерныследующиезадачи информационнойбезопасности:защита отнесанкционированногокопирования,защита от модификациипрограммногокода, сокрытиеот пользователячасти информациии ряд другихзадач. Это отмечаютАлешинС. В., БелокрыловаО.С., ЖолобовД.А.,Мицель А.А., ОганесянА.Г.,Шевелев М.Юи другие авторыв работах,посвященныхзащите информациив АСДО.

Объектисследования– автоматизированнаясистема дистанционногообучения.

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

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

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

Задачиисследования.Длядостиженияпоставленнойцели в диссертационнойработе на примереАСДО сформулированыи решены следующиезадачи:

1.Выделены основныеключевые объекты,подлежащиезащите.

2.Разработаныметоды защитыАСДО вне довереннойвычислитель­нойсреды от массовыхпопыток модификациикода.

3.Разработаныметоды защитыданных длясистем обученияи контролязнаний внедовереннойвычислитель­нойсреды.

4.Проведен анализи предложенывозможныеспособы примененияразработанныхметодов.

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

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

Практическаяценность.

1.Разработаныэффективныеметоды защитысистем дистанционногообучения внедовереннойвычислительнойсреды.

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

3.Разработанныеметоды не нуждаютсяв аппаратныхсредствах длясвоей реализации.

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

Реализация– системазащиты былаинтегрированав программныйкомплекс AquariusEducation4.0, созданныйна кафедре АТМпод руководствомЮхименко Александраи представляющийсобой системуавтоматизированноготестирования.

Областьприменения– сфера образования

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

Структураи объем работы.Диссертациясостоит извведения, четырехглав, заключения,списка литературыи приложения.Материал изложенна 168 страницах,содержит 12 рисунков,одну таблицуи список литературыиз 34 наименований.


ОСНОВНОЕСОДЕРЖАНИЕРАБОТЫ


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

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

Всебольшее вниманиеуделяетсяновому направлениюв образовании– дистанционномуобучению. Однойиз задач припостроенииАСДО являетсяих защита. Примеромможет служитьустановлениедостоверностирезультатовкомпьютерноготестирования.Сюда же относитсяпроблема построениясистемы разграничениядоступа в различныхпрограммныхкомплексах,предназначенныхдля автоматизациипроцесса обучения.Рассмотримчасто встречающуюсяна данный моментситуацию. Накафедре созданасистема, включающаявиртуальноголектора и подсистемутестирования.В случае использованияданной системыв аудиторияхкафедры никакихсложностейне возникает,так как студентынаходятся подконтролемпреподавательскогосостава. Ноориентацияобразованияв сторонудистанционногообучения вноситсвои коррективы.Возникаетпотребностьв возможностииспользованияданного программногообеспечениястудентом насвоей локальноймашине. Такаязадача можетбыть решена(и решаетсядостаточнохорошо) с использованиемсетевых технологий.В такой системестудент заходитна сайт, где онможет заниматьсяобучением илипроходитьразличные видытестирования. Но такая системанеудобна тем,что требуетпостоянногоподключенияк сети, влечетнемалые финансовыезатраты, вынужденаограничиватьучебный материал. Например, придетсяограничитьсякартинкой там,где совсем быне помешалопоказать видеоролик.Отсюда возникаетпотребностьсделать этусистему автономной,с возможностьюраспространенияее на такихносителях, какCD-ROM.

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

1.Отсутствиевозможностидостоверноопределить,прошел ли студенттестированиесамостоятельно.Для этой задачион вполне могиспользоватьдругого человека(например, болееподготовленногостудента).

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

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

4.Существуетвозможностьсозданияуниверсальнойпрограммыпросмотрафайлов с заданиямии ответами. Темсамым, студентимеет возможностьузнать верныеответы на вопросыв тестах.

5.Возможностьмодификациипрограммногокода системытестирования,с целью измененияалгоритмавыставленияоценок.

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

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

Встатье "Проблемаобратной связипри дистанционномобучении." А.Г.Оганесян отмечает,что системадистанционногообразованиядолжна иметьдостаточныесредства защитыот несанкционированноговмешательстваи подмены реальныхстудентов ихдублерами.Далее говорится,что проблемаидентификациистудентов –дистанщиков,кажется вообщене имеет решения.Действительно,пароли и иныеатрибуты личнойидентификациипроблемы нерешают, т.к. студентзаинтересованзаменить себядублером ирасполагаетнеограниченнымивозможностямитакой подмены.Техническоерешение дляее обнаруженияпридумать покане удалось. Авот организационные,похоже, есть.Выход можетбыть в созданиипостепенногоконтроля знаний,с целью формированиятрудностейдля подменыпроходящеготестированиедублером. Ведьнайти дублерана один экзаменнамного проще,чем на весьпериод обучения.

Внекоторыхработах отмечается,что примененниесистемы защитыможет иметьнегативныестороны. В тезисахдокладов ЗанимонецЮ.М. отмечает:"иногда чрезмерныемеры защитысоздавалипроблемы приинсталляциии эксплуатациипрограммногообеспечения".Следовательно,немаловажныммоментом являетсяхорошая продуманностьсистемы защиты.В противномслучае онаможет скореенавредить, чемпринести пользу.Из этого вновьможно сделатьвыводы, чтовопросы защиты(в областидистанционногообразования)плохо проработаны.

Некоторыеученые рассматриваютзащиту в оченьограниченномаспекте. Н.Н.Сенцов и В.С.Солдаткин,описывая программныйкомплекс
тестового контроля знаний «Тест», говорято следующем:

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

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

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

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

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

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

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

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

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

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

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

Задачалегкой адаптацииуже существующихАСДО полностьюлежит в сфереинформационныхтехнологийи имеет достаточнопростое решение.В ОС Windows имеетсямеханизм, которыйпозволит легкоадаптироватьуже существующиесистемы дистанционногообучения итестирования,причем разработанныена различныхязыках. Он обладаетширокой поддержкойсредств разработкии библиотек.ЭтоCOM (Component Object Model). COM- модель компонентныхобъектов Microsoft(стандартныймеханизм, включающийинтерфейсы,с помощью которыходни объектыпредоставляютсвои сервисыдругим, - являетсяосновой многихобъектныхтехнологий,в том числе OLEи ActiveX) [15].

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

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

Рассмотримболее подробнообъекты системыдистанционноголокальногообучения, требующиезащиты.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Естественнымвыбором будетиспользованиеVisualC++.Данное средстворазработкиотвечает всемнеобходимымтребованиям.Также понадобитсябиблиотекадля сжатияданных. Наиболееподходящимкандидатомявляется библиотекаZLIB.

Рассмотримобщие принципыработы полиморфныхалгоритмовшифрованияи расшифрования.Алгоритмысостоят из 8функциональныхблоков, некоторыеиз которыхмогут повторяться.На рисунке 1приведенаабстрактнаясхема работыалгоритмашифрования/расшифрования.

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


Рисунок1. Алгоритмшифрования/расшифрованияв общем виде.

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

Блок1 заносит ввиртуальныйрегистр илипеременную(обозначим еекак A1)адрес шифруемого/расшифруемогоблока данных.Для виртуальноймашины этотадрес на самомделе всегдаявляется нулем.Дело в том, чтокогда происходитвыполнениевиртуальнойинструкциимодификацииданных, товиртуальнаямашина добавляетк этому адресунастоящий адресв памяти и ужес ним производитоперации. МожнопредставитьA1как индекс вмассивешифруемых/расшифруемыхданных, адресуемыхс нуля.

Блок2 заносит ввиртуальныйрегистр илипеременную(обозначим еекак A2)размер блокаданных. А2 выполняетроль счетчикав цикле преобразованияданных. Заметим,что ее значениевсегда в 4 разаменьше, чемнастоящийразмер шифруемых/расшифруемыхданных. Этосвязано с тем,что полиморфныеалгоритмывсегда работаютс блоками данныхкратных поразмеру 4 байтам.Причем, операциипреобразованиявыполняютсянад блокамикратными 4 байтам.О выравниванииданных по 4 байтазаботятся болеевысокоуровневыемеханизмы,использующиевиртуальнуюмашину и полиморфныеалгоритмы дляшифрованияи расшифрованияданных. Возникаетвопрос, откудаалгоритмузнать, какогоразмера блокему необходимозашифровать,ведь при егогенерации такойинформациипросто нет.Необходимоезначение онпросто беретиз ячейки памяти.Дело в том, чтовиртуальнаямашина памяти"знает" именнооб этой виртуальнойячейке памятии перед началомвыполненияполиморфногоалгоритмазаносит туданеобходимоезначение.

Блок3 помещает ввиртуальныйрегистр илипеременную(обозначим еекак A3)константу,участвующуюв преобразовании.Эта константа,возможно, затеми не будетиспользованадля преобразованияданных, всезависит оттого, какой кодбудет сгенерирован.Блок 3 можетбыть повтореннесколько раз.Над даннымиосуществляетсяцелый наборразличныхпреобразованийи в каждом изних участвуютразличныерегистры/переменныеинициализированныев блоке 3.

Блок4 можно назватьосновным. Именноон, а, точнеесказать, наборэтих блоковпроизводитшифрование/расшифрованиеданных. Количествоэтих блоковслучайно, иравно количествублоков номер3. Но при преобразованияхне обязательнобудет использованозначение изA3.Например, вместоA3может использоватьсяконстанта илизначение изсчетчика. Наданный моментполиморфныйгенераторподдерживает3 вида преобразований:побитовое"исключающееили" (XOR),сложение ивычитание.Набор этихпреобразованиеможно легкорасширить,главное, чтобытакое преобразованиеимело обратнуюоперацию.

Блок5 служит дляувеличенияA1на единицу. Каки во всех другихблоках этаоперация можетбыть выполненапо-разному, тоесть с использованиемразличныхэлементарныхинструкцийвиртуальноймашины.

Блок6 организуетцикл. Он уменьшаетзначение A2на единицу, иесли результатне равен 0, товиртуальнаямашина переходитк выполнениючетвертогоблока. На самомделе управлениеможет бытьпередано наодин из холостыхблоков междублоком 3 и 4, нос функциональнойточки зренияэто значенияне имеет.

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

Блок8 завершаетработу алгоритма.


Опишемтеперь по шагам,как работаетгенераторполиморфногокода.

1. На первом этапевыбираютсяхарактеристикибудущих алгоритмов.К ним относятся:
a)размер памяти,выделеннойпод код;

б)в каких регистрахили ячейкахбудут располагатьсяуказатели намодифицируемыйкод;
г) сколько раз будутповторятьсяфункциональныеблоки 3 и 4;

д)в каких регистрахили ячейкахбудут располагатьсясчетчики циклов;

Приэтом количествоповторенийблоков 3 и 4 должнобыть одинаковыми для алгоритмашифрованияи для алгоритмарасшифрования,так как каждойкоманде преобразованияданных пришифрованиидолжна бытьсопоставленаобратная командав алгоритмерасшифрования.

2. Виртуальнаяпамять, используемаяв алгоритме,заполняетсяслучайнымизначения.

3.Создается 1-ыйфункциональныйблок и помещаетсяв промежуточноехранилище.
а)Случайнымобразом ищетсяподходящийпервый блок.Критерий поиска– блок должениспользоватьрегистр илиячейку памятипод указатель,в зависимостиот того какиехарактеристикибыли выбранына первом шаге(пункт б).
б) Вкод блокаподставляетсясоответствующийномер регистраили адрес виртуальнойячейки памяти.

4. Создается 2-ойфункциональныйблок и помещаетсяв промежуточноехранилище.Алгоритм созданияподобен алгоритму,описанномув шаге 3. Но теперьподставляетсяне только номеррегистра илиячейки памяти,куда помещаетсязначение, нои адрес памятис источником.В эту ячейкупамяти в дальнейшемвиртуальнаямашина будетпомещать размершифруемой/расшифруемойобласти.

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

6. Подсчитываетсяразмер ужесгенерированныхблоков. Эточисло затембудет использоватьсядля случайнойгенерацииадреса началаблоков в цикле.

7.Рассчитываетсяразмер памяти,который будетвыделен подуже сгенерированныеблоки (расположенныедо цикла) срезервированиемместа под холостыеблоки. Такжеподсчитываетсяадрес первогоблока в цикле.

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

9.Создается 5-ойфункциональныйблок и помещаетсяв промежуточноехранилище.

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

11.Создается 7-ойфункциональныйблок и помещаетсяв промежуточноехранилище.

12.Создается 8-ойфункциональныйблок и помещаетсяв промежуточноехранилище.

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

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

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

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

Вначале главыприведен списоккомпонентов,входящих вразработаннуюбиблиотекузащиты Uniprot.Затем подробноописаны интерфейсы,предоставляемыепрограммистумодулем Uniprot.dll.Модуль экспортируеттри интерфейса:IProtect,IProtectFile,IProtectConformity.

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

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

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

Главасодержит такжеруководствопрограммистапо использованиюпрограммыProtectEXE.exe.ПрограммаProtectEXE.EXEпредназначенадля защитыисполняемыхфайлов отмодификации.Под исполняемымимодулями понимаютсяEXEфайлы в форматеPE(PortableExecutables).Защита исполняемыхмодулей основанана их шифровании.Особенностьюутилиты ProtectEXEявляется то,что она шифруеткаждый исполняемыйфайл уникальнымполиморфнымалгоритмом.Это затрудняетвозможностьиспользованияпрограммноговзломщика,основанногона модификацииопределенныхкодов в программе.Посколькукаждый исполняемыйфайл зашифровансвоим методом,то и модифицироватьих единым методомневозможно.Утилита ProtectEXE.EXEне позволяетзащититьсяот динамическогомодифицированияв памяти. Этослишком сложнои не может бытьдостигнуто,без существеннойпеределкиисходноготекста самойзащищаемойпрограммы. Нов рамках защитыдистанционныхсредств обучениятакая защитадолжна бытьдостаточноэффективнаи достаточна.Ведь созданиевзламывающейпрограммыэкономическимало целесообразно,а, следовательно,и, скорее всего,не будет осуществлено.

Далеев главе описаноиспользованиясистемы защитына примерах.Так напримеррассмотреноподключениемодуля защитык программена языке VisualC++и VisualBasic.Приведен примериспользованиямодуля защитыв программена языке VisualBasiс,Пример использованияпрограммыProtectEXE.exe.

Вконце главыдан ряд общихрекомендацийпо интеграциисистемы защиты.

Взаключенииподведены итогипроделаннойработы.

Вприложенияхприведен исходныйтекст модулязащиты.


ОСНОВНЫЕРЕЗУЛЬТАТЫРАБОТЫ


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

2.На основе анализапредложен рядмер, позволяющийповысить защищенностьАСДО.Разработаныпрограммныесредства,предназначенныедля интеграциив уже существующиеобучающиесистемы с цельюих защиты прииспользованиивнедовереннойвычислительнойсреды.

3.В разработанномпрограммномобеспечениибыли использованыновые технологиишифрованияданных. Полностьюисключенанеобходимостьиспользованияаппаратныхсредств.

4.Разработанасистема защиты,руководстводля программиста,набор тестовыхпримеров ирекомендациипо ее применению.Созданнаясистема былаинтегрированав уже существующийкомплекс AquariusEducation4.0, разработанныйна кафедре АТМ.


СПИСОКОСНОВНЫХ ПУБЛИКАЦИЙПО ТЕМЕ ДИССЕРТАЦИИ


  1. Построениезащиты в системеконтроля ипередачи знаний.Печатный Сборникдокладовмеждународнойнаучной конференцииММТТ-Дон. РГХАСМ,Ростов-на-Дону,2002. 2 стр.


  1. Системаинтеграциизащиты информациидля пакетов автономногодистанционногообучения. ПечатныйСборник докладовмеждународнойнаучной конференцииММТТ-Дон. РГХАСМ,Ростов-на-Дону,2003. 2 стр.


ђ §¤Ґ«: Їа®Ја ¬¬Ёа®ў ­ЁҐ
”€Ћ: Љ аЇ®ў Ђ­¤аҐ© ЌЁЄ®« ҐўЁз
forsp@list.ru
‡ йЁв  Ё­д®а¬ жЁЁ ў бЁб⥬ е ¤Ёбв ­жЁ®­­®Ј® ®Ўг祭Ёп б ¬®­®Ї®«м­л¬ ¤®бвгЇ®¬
„ЁЇ«®¬

168



Частьисходных текстоввспомогательногохарактераопущена. В качествепримера можнопривести классcom_ptr, представляющийвспомогательныйкласс для болееудобной работыс COMинтерфейсом.Также полностьюопущены исходныетектсыт свободнораспрострняемойбиблиотекиZLIB1.1.2.


Файлblocks.h.


#ifndef__BLOCKS_H__

#define__BLOCKS_H__


#ifndefCALC_ARRAY_SIZE

#defineCALC_ARRAY_SIZE(arr) ((int) (sizeof arr / sizeof arr[0]))

#endif


#defineBLOCK_START(num) const static int block_##num [] = {

#defineBLOCK_END(num) }; const size_t sizeBlock_##num =CALC_ARRAY_SIZE(block_##num);


#defineBLOCKS_START(num) const static int * const blocks_##num [] = {

#defineBLOCKS_END(num) }; const size_t sizeBlocksArray_##num =CALC_ARRAY_SIZE(blocks_##num);

#defineBLOCK(num) static_cast(block_##num),


#defineBLOCKS_SIZE_START(num) const static unsigned sizeBlocks_##num [] = {

#defineBLOCK_SIZE(num) sizeBlock_##num,

#defineBLOCKS_SIZE_END(num) };


//Абстрактныйалгоритм

//[ADDR(REG|VAR)

//[COUNT(REG|VAR)

//{[R(REG|VAR)

//label:

//{

// TEMP

// TEMP = TEMP opearation R[i]

// [ADDR]

// ADDR++

// COUNT--

//} * i(1; n)

//if (COUNT!=0)

// GOTO label

//TrstDate

//EXIT


//-----------------------------------------------------------------------------

//БлокN0. (x1)

// Служитдля инициализацииуказателянулем.

// ES_VARIABLE_0 -ячейка котораяможет бытьзанята подуказатель.

// ES_REG_0 -регистр которыйможет бытьзанят под указатель.

BLOCK_START(00_00)

EO_MOV, EOP_VAR,ES_VARIABLE_0, EOP_CONST, 0

BLOCK_END(00_00)


BLOCK_START(00_01)

EO_MOV, EOP_REG,ES_REG_0, EOP_CONST, 0

BLOCK_END(00_01)


BLOCK_START(00_02)

EO_PUSH,EOP_CONST, 0,

ES_RANDOM_NOP,

ES_RANDOM_NOP,

EO_POP, EOP_REG,ES_REG_0

BLOCK_END(00_02)


BLOCK_START(00_03)

EO_PUSH, EOP_CONST,ES_RANDOM_CONST,

ES_RANDOM_NOP,

EO_POP, EOP_REG,ES_REG_0,

EO_SUB, EOP_REG,ES_REG_0, EOP_REG, ES_REG_0

BLOCK_END(00_03)


BLOCK_START(00_04)

EO_MOV, EOP_VAR,ES_VARIABLE_0, EOP_CONST, 1,

EO_DEC, EOP_VAR,ES_VARIABLE_0,

EO_CMP, EOP_VAR,ES_VARIABLE_0, EOP_CONST, 0,

EO_JNZ, EOP_CONST,ES_RANDOM_CONST

BLOCK_END(00_04)


BLOCK_START(00_05)

EO_XOR, EOP_REG,ES_REG_0, EOP_REG, ES_REG_0

BLOCK_END(00_05)


BLOCK_START(00_06)

EO_XOR, EOP_VAR,ES_VARIABLE_0, EOP_VAR, ES_VARIABLE_0

BLOCK_END(00_06)


BLOCKS_START(00)

BLOCK(00_00)

BLOCK(00_01)

BLOCK(00_02)

BLOCK(00_03)

BLOCK(00_04)

BLOCK(00_05)

BLOCK(00_06)

BLOCKS_END(00)


BLOCKS_SIZE_START(00)

BLOCK_SIZE(00_00)

BLOCK_SIZE(00_01)

BLOCK_SIZE(00_02)

BLOCK_SIZE(00_03)

BLOCK_SIZE(00_04)

BLOCK_SIZE(00_05)

BLOCK_SIZE(00_06)

BLOCKS_SIZE_END(00)

//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------

// БлокN1. (x1)

// Служитдля инициализациисчетчика нужнымзначением.

// ES_VARIABLE_0 -ячейка котораяможет бытьзанята подзначение.

// ES_REG_0 -регистр которыйможет бытьзанят под значение.

// ES_VARIABLE_1 -Отсюда необхлдимовзять размер

BLOCK_START(01_00)

EO_MOV, EOP_VAR,ES_VARIABLE_0, EOP_VAR, ES_VARIABLE_1

BLOCK_END(01_00)


BLOCK_START(01_01)

EO_MOV,EOP_REG, ES_REG_0, EOP_VAR, ES_VARIABLE_1

BLOCK_END(01_01)


BLOCK_START(01_02)

EO_PUSH, EOP_VAR,ES_VARIABLE_1,

ES_RANDOM_NOP,

ES_RANDOM_NOP,

EO_POP, EOP_REG,ES_REG_0

BLOCK_END(01_02)


BLOCK_START(01_03)

EO_PUSH, EOP_VAR,ES_VARIABLE_1,

EO_MOV, EOP_REG,ES_REG_0, EOP_RAND,

EO_POP, EOP_REG,ES_REG_0

BLOCK_END(01_03)


BLOCK_START(01_04)

EO_XCHG, EOP_VAR,ES_VARIABLE_0, EOP_VAR, ES_VARIABLE_1

BLOCK_END(01_04)


BLOCK_START(01_05)

EO_XCHG, EOP_REG,ES_REG_0, EOP_VAR, ES_VARIABLE_1

BLOCK_END(01_05)


BLOCKS_START(01)

BLOCK(01_00)

BLOCK(01_01)

BLOCK(01_02)

BLOCK(01_03)

BLOCK(01_04)

BLOCK(01_05)

BLOCKS_END(01)


BLOCKS_SIZE_START(01)

BLOCK_SIZE(01_00)

BLOCK_SIZE(01_01)

BLOCK_SIZE(01_02)

BLOCK_SIZE(01_03)

BLOCK_SIZE(01_04)

BLOCK_SIZE(01_05)

BLOCKS_SIZE_END(01)

//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------

// БлокN2. (xN)

// Служитдля инициализациимодификаторанужным значением.

// ES_VARIABLE_0 -ячейка котораяможет бытьзанята подзначение.

// ES_REG_0 -регистр которыйможет бытьзанят под значение.

// ES_VARIABLE_1 -ячейка, гдеможет хранитьсямодификатор

// ES_COSNT_0 -здесь можетхранитьсямодификатор

BLOCK_START(02_00)

EO_MOV, EOP_VAR,ES_VARIABLE_0, EOP_VAR, ES_VARIABLE_1

BLOCK_END(02_00)


BLOCK_START(02_01)

EO_MOV, EOP_REG,ES_REG_0, EOP_VAR, ES_VARIABLE_1

BLOCK_END(02_01)


BLOCK_START(02_02)

EO_MOV, EOP_VAR,ES_VARIABLE_0, EOP_CONST, ES_CONST_0

BLOCK_END(02_02)


BLOCK_START(02_03)

EO_MOV, EOP_REG,ES_REG_0, EOP_CONST, ES_CONST_0

BLOCK_END(02_03)


BLOCK_START(02_04)

EO_XCHG, EOP_VAR,ES_VARIABLE_0, EOP_VAR, ES_VARIABLE_1

BLOCK_END(02_04)


BLOCK_START(02_05)

EO_XCHG, EOP_REG,ES_REG_0, EOP_VAR, ES_VARIABLE_1

BLOCK_END(02_05)


BLOCK_START(02_06)

EO_PUSH, EOP_CONST,ES_CONST_0,

ES_RANDOM_NOP,

ES_RANDOM_NOP,

EO_POP, EOP_REG,ES_REG_0

BLOCK_END(02_06)


BLOCK_START(02_07)

EO_MOV, EOP_VAR,ES_VARIABLE_0, EOP_CONST, 0,

EO_ADD, EOP_VAR,ES_VARIABLE_0, EOP_VAR, ES_VARIABLE_1

BLOCK_END(02_07)


BLOCKS_START(02)

BLOCK(02_00)

BLOCK(02_01)

BLOCK(02_02)

BLOCK(02_03)

BLOCK(02_04)

BLOCK(02_05)

BLOCK(02_06)

BLOCK(02_07)

BLOCKS_END(02)


BLOCKS_SIZE_START(02)

BLOCK_SIZE(02_00)

BLOCK_SIZE(02_01)

BLOCK_SIZE(02_02)

BLOCK_SIZE(02_03)

BLOCK_SIZE(02_04)

BLOCK_SIZE(02_05)

BLOCK_SIZE(02_06)

BLOCK_SIZE(02_07)

BLOCKS_SIZE_END(02)

//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------

// БлокN3. (xN)

// Служитдля преобразованияодной ячейкипамяти.

// ES_VARIABLE_0 - \указатель наячейку памяти

//ES_REG_0 - /

//ES_VARIABLE_1 - \ модификатор

//ES_REG_1 - /

//ES_VARIABLE_2 - \ счетчик

// ES_REG_2 - /

// ES_SPECIFIC_0 -сюда подставитьоперацию

//.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . .


conststatic int block_03_operation_AB[] =

{

EO_XOR, EO_ADD,EO_SUB

};


conststatic int block_03_operation_BA[] =

{

EO_XOR, EO_SUB,EO_ADD

};


BLOCK_START(03_00)

ES_SPECIFIC_0,EOP_REF_REG, ES_REG_0, EOP_REG, ES_REG_1

BLOCK_END(03_00)


BLOCK_START(03_01)

ES_SPECIFIC_0,EOP_REF_VAR, ES_VARIABLE_0, EOP_REG, ES_REG_1

BLOCK_END(03_01)


BLOCK_START(03_02)

ES_SPECIFIC_0,EOP_REF_REG, ES_REG_0, EOP_REG, ES_REG_2

BLOCK_END(03_02)


BLOCK_START(03_03)

ES_SPECIFIC_0,EOP_REF_VAR, ES_VARIABLE_0, EOP_REG, ES_REG_2

BLOCK_END(03_03)


BLOCK_START(03_04)

ES_SPECIFIC_0,EOP_REF_REG, ES_REG_0, EOP_VAR, ES_VARIABLE_1

BLOCK_END(03_04)


BLOCK_START(03_05)

ES_SPECIFIC_0,EOP_REF_VAR, ES_VARIABLE_0, EOP_VAR, ES_VARIABLE_1

BLOCK_END(03_05)


BLOCK_START(03_06)

ES_SPECIFIC_0,EOP_REF_REG, ES_REG_0, EOP_VAR, ES_VARIABLE_2

BLOCK_END(03_06)


BLOCK_START(03_07)

ES_SPECIFIC_0,EOP_REF_VAR, ES_VARIABLE_0, EOP_VAR, ES_VARIABLE_2

BLOCK_END(03_07)


BLOCKS_START(03)

BLOCK(03_00)

BLOCK(03_01)

BLOCK(03_02)

BLOCK(03_03)

BLOCK(03_04)

BLOCK(03_05)

BLOCK(03_06)

BLOCK(03_07)

BLOCKS_END(03)


BLOCKS_SIZE_START(03)

BLOCK_SIZE(03_00)

BLOCK_SIZE(03_01)

BLOCK_SIZE(03_02)

BLOCK_SIZE(03_03)

BLOCK_SIZE(03_04)

BLOCK_SIZE(03_05)

BLOCK_SIZE(03_06)

BLOCK_SIZE(03_07)

BLOCKS_SIZE_END(03)

//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------

// БлокN4. (x1)

// Служитдля увеличениязначения указателя.

// ES_VARIABLE_0 -ячейка котораяможет бытьзанята подуказатель.

// ES_REG_0 -регистр которыйможет бытьзанят под указатель.

BLOCK_START(04_00)

EO_ADD,EOP_VAR, ES_VARIABLE_0, EOP_CONST, 1

BLOCK_END(04_00)


BLOCK_START(04_01)

EO_INC, EOP_VAR,ES_VARIABLE_0

BLOCK_END(04_01)


BLOCK_START(04_02)

EO_INC, EOP_REG,ES_REG_0

BLOCK_END(04_02)


BLOCK_START(04_03)

EO_SUB, EOP_VAR,ES_VARIABLE_0, EOP_CONST, -1

BLOCK_END(04_03)


BLOCK_START(04_04)

EO_SUB, EOP_REG,ES_REG_0, EOP_CONST, -1

BLOCK_END(04_04)


BLOCK_START(04_05)

EO_NEG, EOP_REG,ES_REG_0,

ES_RANDOM_NOP,

ES_RANDOM_NOP,

EO_DEC, EOP_REG,ES_REG_0,

EO_NEG, EOP_REG,ES_REG_0

BLOCK_END(04_05)


BLOCKS_START(04)

BLOCK(04_00)

BLOCK(04_01)

BLOCK(04_02)

BLOCK(04_03)

BLOCK(04_04)

BLOCK(04_05)

BLOCKS_END(04)


BLOCKS_SIZE_START(04)

BLOCK_SIZE(04_00)

BLOCK_SIZE(04_01)

BLOCK_SIZE(04_02)

BLOCK_SIZE(04_03)

BLOCK_SIZE(04_04)

BLOCK_SIZE(04_05)

BLOCKS_SIZE_END(04)

//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------

// БлокN5. (x1)

// Служитдля организациицикла.

// ES_VARIABLE_0 -ячейка котораяможет бытьзанята подсчетчик.

// ES_REG_0 -регистр которыйможет бытьзанят под счетчик.

// ES_ADDRESS_0 -куда осуществитьпереход дляповтора цикла.


BLOCK_START(05_00)

EO_DEC, EOP_VAR,ES_VARIABLE_0,

EO_CMP, EOP_VAR,ES_VARIABLE_0, EOP_CONST, 0,

EO_JNZ, EOP_CONST,ES_ADDRESS_0

BLOCK_END(05_00)


BLOCK_START(05_01)

EO_DEC, EOP_REG,ES_REG_0,

EO_CMP, EOP_REG,ES_REG_0, EOP_CONST, 0,

EO_JNZ, EOP_CONST,ES_ADDRESS_0

BLOCK_END(05_01)


BLOCKS_START(05)

BLOCK(05_00)

BLOCK(05_01)

BLOCKS_END(05)


BLOCKS_SIZE_START(05)

BLOCK_SIZE(05_00)

BLOCK_SIZE(05_01)

BLOCKS_SIZE_END(05)

//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------

// БлокN6. (x1)

// Служитдля проверкивременныхограничений.(может отсутсвовать)

// ES_CONST_0 -константакоторая можетсодержать датудля контроля.

// ES_VARIABLE_0 -ячейка котораяможет содержатьдату для контроля.


BLOCK_START(06_00)

EO_TEST_TIME_0,EOP_CONST, ES_CONST_0

BLOCK_END(06_00)


BLOCK_START(06_01)

EO_TEST_TIME_1,EOP_CONST, ES_CONST_0

BLOCK_END(06_01)


BLOCK_START(06_02)

EO_TEST_TIME_0,EOP_VAR, ES_VARIABLE_0

BLOCK_END(06_02)


BLOCK_START(06_03)

EO_TEST_TIME_1,EOP_VAR, ES_VARIABLE_0

BLOCK_END(06_03)


BLOCKS_START(06)

BLOCK(06_00)

BLOCK(06_01)

BLOCK(06_02)

BLOCK(06_03)

BLOCKS_END(06)


BLOCKS_SIZE_START(06)

BLOCK_SIZE(06_00)

BLOCK_SIZE(06_01)

BLOCK_SIZE(06_02)

BLOCK_SIZE(06_03)

BLOCKS_SIZE_END(06)


//-----------------------------------------------------------------------------

// БлокN7. (x1)

// Служитдля завершения.


BLOCK_START(07_00)

EO_EXIT_0

BLOCK_END(07_00)


BLOCK_START(07_01)

EO_EXIT_1

BLOCK_END(07_01)


BLOCK_START(07_02)

EO_EXIT_2,

EO_NOP_0,

EO_JMP, EOP_CONST, 0

BLOCK_END(07_02)


BLOCKS_START(07)

BLOCK(07_00)

BLOCK(07_01)

BLOCK(07_02)

BLOCKS_END(07)


BLOCKS_SIZE_START(07)

BLOCK_SIZE(07_00)

BLOCK_SIZE(07_01)

BLOCK_SIZE(07_02)

BLOCKS_SIZE_END(07)


//-----------------------------------------------------------------------------

//БлокNOP.

BLOCK_START(nop_00)

EO_XCHG, EOP_REG,ES_RANDOM_REG, EOP_VAR, ES_RANDOM_VAR,

BLOCK_END(nop_00)


BLOCK_START(nop_01)

EO_ADD, EOP_REG,ES_RANDOM_REG, EOP_REG, ES_RANDOM_USE_REG,

BLOCK_END(nop_01)


BLOCK_START(nop_02)

EO_NOP_0

BLOCK_END(nop_02)


BLOCK_START(nop_03)

EO_NOP_1

BLOCK_END(nop_03)


BLOCK_START(nop_04)

EO_NOP_2

BLOCK_END(nop_04)


BLOCK_START(nop_05)

EO_NOP_3

BLOCK_END(nop_05)


BLOCK_START(nop_06)

EO_MOV, EOP_REG,ES_RANDOM_REG, EOP_RAND

BLOCK_END(nop_06)


BLOCKS_START(Nops)

BLOCK(nop_00)

BLOCK(nop_01)

BLOCK(nop_02)

BLOCK(nop_03)

BLOCK(nop_04)

BLOCK(nop_05)

BLOCK(nop_06)

BLOCKS_END(Nops)


BLOCKS_SIZE_START(Nops)

BLOCK_SIZE(nop_00)

BLOCK_SIZE(nop_01)

BLOCK_SIZE(nop_02)

BLOCK_SIZE(nop_03)

BLOCK_SIZE(nop_04)

BLOCK_SIZE(nop_05)

BLOCK_SIZE(nop_06)

BLOCKS_SIZE_END(Nops)

//-----------------------------------------------------------------------------


#endif// __BLOCKS_H__


Файлp_enums.h.


#ifndef__P_ENUMS_H__

#define__P_ENUMS_H__


#ifndefCALC_ARRAY_SIZE

#defineCALC_ARRAY_SIZE(arr) ((int) (sizeof arr / sizeof arr[0]))

#endif


enumE_OPERATION // Инструкции

{

EO_ERROR= -1, // Недопустимаяинструкция

EO_EXIT_0,EO_EXIT_1,EO_EXIT_2, // Конец рабоботы

EO_NOP_0,EO_NOP_1,EO_NOP_2,EO_NOP_3,// Пустые команды

EO_TEST_TIME_0,EO_TEST_TIME_1, // Контрольвремени

EO_MOV,EO_XCHG, // Пересылкаданных

EO_PUSH,EO_POP, // Работасо стеком

EO_XOR,EO_AND,EO_OR,EO_NOT, // Логическиеоперации

EO_ADD,EO_SUB,EO_MUL,EO_DIV,EO_NEG,// Арифметическиеоперации

EO_INC,EO_DEC,

EO_TEST,EO_CMP, // Операциисравнения

//(влияют на флаги)

EO_JMP,EO_CALL,EO_RET, // Операторыбезусловногоперехода

EO_JZ,EO_JNZ,EO_JA,EO_JNA, // Условныепереходы

};


#defineLAST_DEFINED_NOP EO_NOP_3

#defineLAST_OPERATION EO_JNA


enumE_FLAGS // Флаги

{

EF_ZERO = 1, // Ноль

EF_ABOVE = 2, // Больше

};


enumE_OPERAND

{ // Операндомявляется:

EOP_REG= 0, // Регистр

EOP_REF_REG, // Память поадресу в регистре

EOP_VAR, // Переменная

EOP_REF_VAR, // Память поадресу в переменная

EOP_CONST, // Константноезначение

EOP_RAND // Случайноечисло

};


enumE_SUBSTITUTION // Подстановки

{

//НЕ зАБЫВАТЬподправитьArraySubstitution

ES_RANDOM_NOP = 0x0A0FF00,// Сюда можноподставитьлюбой NOP-блок

ES_RANDOM_CONST= 0x0A0FF01,// Сюда можноподставит любоечисло

ES_RANDOM_REG = 0x0A0FF02,// Сюда можноподставитьлюбой незанятый

//регистр

ES_RANDOM_VAR = 0x0A0FF03,// Сюда можноподставитьлюбую незанятую

//переменную

ES_RANDOM_USE_REG= 0x0A0FF04,// Сюда можноподставитьлюбой незанятый

//или занятыйрегистр

ES_RANDOM_USE_VAR= 0x0A0FF05,// Сюда можноподставитьлюбую незанятую

//или занятуюпеременную

ES_VARIABLE_0= 0x0B0FF02,// Сюда подставляютсяданные, актуальные

ES_VARIABLE_1= 0x0B0FF03,// для данногоблока

ES_VARIABLE_2= 0x0B0FF04,

ES_REG_0 =0x0C0FF05,

ES_REG_1 =0x0C0FF06,

ES_REG_2 =0x0C0FF07,

ES_ADDRESS_0 =0x0D0AA08,

ES_ADDRESS_1 =0x0D0AA09,

ES_CONST_0 = 0x0E0AA0A,

ES_CONST_1 =0x0E0AA0B,

ES_SPECIFIC_0 =0x0E0BB0C,

ES_SPECIFIC_1 =0x0E0BB0D

};


staticconst E_SUBSTITUTION AllSubstitution[] =

{ES_RANDOM_NOP, ES_RANDOM_CONST, ES_RANDOM_REG, ES_RANDOM_VAR,

ES_RANDOM_USE_REG, ES_RANDOM_USE_VAR,

ES_VARIABLE_0, ES_VARIABLE_1, ES_VARIABLE_2,

ES_REG_0, ES_REG_1, ES_REG_2,

ES_ADDRESS_0, ES_ADDRESS_1,

ES_CONST_0, ES_CONST_1,

ES_SPECIFIC_0, ES_SPECIFIC_1

};

unsignedAllSubstitutionSize = CALC_ARRAY_SIZE(AllSubstitution);


#endif// __P_ENUMS_H__


Файлpdebug.h.


#ifndef__PDEBUG_H__

#define__PDEBUG_H__


#ifdef_DEBUG

#defineWRITE_LOG

#endif


#ifdefWRITE_LOG

voidWriteToLog(LPCTSTR str, bool newLine = true);

voidWriteToLog(int num, bool newLine = true);

#else

inline voidWriteToLog(LPCTSTR, bool = true) { }

inline voidWriteToLog(int, bool = true) { }

#endif


#endif//__PDEBUG_H__


Файлpdebug.cpp.


#include"stdafx.h"

#include

#include"pdebug.h"

#include"ckg_str.h"


#ifdefWRITE_LOG

staticFILE *logFile = NULL;

voidWriteToLog(LPCTSTR str, bool newLine)

{

if (!logFile)

{

logFile =_tfopen(_T("uniprot.log"), _T("wb"));

_ASSERT(logFile);

}

fwrite(str,sizeof(TCHAR), _tcslen(str), logFile);

if (newLine)

{

static LPCTSTRendStr = _T("\r\n");

fwrite(endStr,sizeof(TCHAR), _tcslen(endStr), logFile);

}

fflush(logFile);

}

void WriteToLog(intnum, bool newLine)

{

CkgString str;

str.Format(_T("%d"), num);

WriteToLog(str,newLine);

}

#endif


Файлpolymorphism.h.


#ifndef__POLYMORPHISM_H__

#define__POLYMORPHISM_H__


// Чемудолжны бытькранты размерыданных.

#defineROUND_SATA_SIZE 64


// Минимальнодопустимыйгод.

//(Вычитется вGetCurrentDayNum)

#defineMIN_YEAR 1970 // бездумноне трогать.

//(подумать надDataToDay())


voidCryptData (BYTE &dataArray, size_t size, BYTE&algorithmDataArray,

size_talgorithmDataSize);


voidDecryptData(BYTE &dataArray, size_t size, BYTE&algorithmDataArray,

size_talgorithmDataSize);


voidCryptData (BYTE &dataArray, size_t size, const TCHAR &fileName);


voidDecryptData(BYTE &dataArray, size_t size, const TCHAR &fileName);


unsignedGetCurrentDayNum();


voidGenerateAlgorithm(pure_c_ptr &algorithmCrypt, size_t &sizeCrypt,

pure_c_ptr&algorithmDecrypt, size_t &sizeDecrypt,

unsigneddeltaTimeCrypt = 0,

unsigneddeltaTimeDecrypt = 0);


voidGenerateAlgorithm(const TCHAR &algorithmCryptFileName,

constTCHAR &algorithmDecryptFileName,

unsigneddeltaTimeCrypt = 0,

unsigneddeltaTimeDecrypt = 0);


int CoolRand();

int CoolRand(unsigned limit);


#endif// __POLYMORPHISM_H__


Файлpolymorphism.cpp.


#include"stdafx.h"

#include

#include

#include

#include"resource.h"

#include"cpp_ptr.h"

#include"c_ptr.h"

#include"ckg_str.h"

#include"ckg_error.h"

#include"ckg_alloc.h"

#include"ckg_array.h"

#include"polymorphism.h"

#include"p_enums.h"

#include"blocks.h"

#include"pdebug.h"


// Количествопеременныхдля виртуальноймашины.

// В отличииот виртуальныхрегистров,переменные

// явдяютсяинициализированнымидо начала работы.

constunsigned variablesNum= 20;


// Количествовиртуальныхрегистров

constunsignedregistersNum= 10;


constBYTEidSupportAlgorithm= 1; // Идентификаторблока с алгоритмом

constBYTEidCryptAlgorithm = 0; // Алгоритмдля шифрования

constBYTEidDecryptAlgorithm= 1; // Алгоритм длярасшифрования


constunsignedmaxUseTime = INT_MAX;// Ограничениепо максимальному

//времени использования(дней).


typedefCkgSimpleContainerArray Block;


structAlgorithmDataStruct

{

BYTEidSupportAlgorithm;

BYTE idType;

size_t sizeAll;

intvariables[variablesNum];

unsignednumVarForSetSize; // В переменнуюс этим номеромзанести

//размер данных

};


constunsignedminSizeAlgorithm= 160; // Придельныеразмеры алгоритма.

constunsigned maxSizeAlgorithm = 200; //

constunsigned minNumTransformation = 2; // Придельноеколичество

constunsigned maxNumTransformation = 5; // трансформаций.

constunsigned numBlocks = 8; // Количествоблоков.

constunsigned numBlocksBeforeLoop = 3; // Количествоблоков до метки

//Loop.

constunsigned dataSizeSmoothing = ROUND_SATA_SIZE;

//Чему должныбыть кранты

//размеры данных


structAlgorithmParameters

{

unsignedsizeAlgorithm; // Размералгоритма

unsignednumTransformation;// Количествоблоков дляпреобразования

bool addressIsReg; // Адрес в регистреили переменной

unsignedaddressNumber; // Номер переменнойили регистрагде

//будет хранитьсяадрес.

bool modificatoryIsReg[maxNumTransformation];

//Модификаторрегистр / переменная.

unsignedmodificatorsNumbers[maxNumTransformation];

//Номера регистров/переменныхдля

//модификаторов.

unsignedcounterIsReg; // Счетчик врегистре илипеременной.

unsignedcounterNumber; // Номер переменнойили регистрагде

//будет хранитьсясчетчик.

unsignedinitCounterNumber;// Какую переменнуюиспользоватьдля

//инициализациисчетчика

unsignedtotalNumTrueBlocks;// Сколько всегоблоков должнополучиться

//(без учета nops)


bool usedRegisters[registersNum]; // Занятыерегистры.

bool usedVariables[variablesNum]; // Занятыеперемненные.

};


//-----------------------------------------------------------------------------

#ifdef_DEBUG

voidDebugTestBlock(int a)

{

unsignedsizeArrayAllSubstitution = CALC_ARRAY_SIZE(AllSubstitution);


_ASSERT(a !=EO_ERROR);

for (unsigned i =0; i

_ASSERT(AllSubstitution[i]!= a);


}

#defineDEBUG_TEST_BLOCK(a) DebugTestBlock(a)

#else

#defineDEBUG_TEST_BLOCK(a)

#endif// _DEBUG

//-----------------------------------------------------------------------------

intTestRegNum(int reg)

{

if (reg = registersNum)

CkgExcept(_T("errorregister number"));

return reg;

}

//-----------------------------------------------------------------------------

intTestVarNum(int var)

{

if (var = variablesNum)

CkgExcept(_T("errorvariables number"));

return var;

}

//-----------------------------------------------------------------------------

voidSkepValue(const int *&p)

{

E_OPERAND operand =static_cast(*p++);

switch (operand)

{

case EOP_REG:

case EOP_REF_REG:

case EOP_VAR:

case EOP_REF_VAR:

case EOP_CONST: *p++; return;

case EOP_RAND: return;

default:CkgExcept(_T("error operand type"));

}

}

//-----------------------------------------------------------------------------

intGetValue(const int *&p, int &variables, int &registers,const int &data)

{

E_OPERAND operand =static_cast(*p++);

int reg, var;

switch (operand)

{

case EOP_REG: reg = TestRegNum(*p++);

WriteToLog(_T("REG_"),false);

WriteToLog(reg,false);

return(&registers)[reg];

case EOP_REF_REG: {

reg= TestRegNum(*p++);

intn = (&registers)[reg];

WriteToLog(_T("REF_REG_"),false);

WriteToLog(reg,false);

return(&data)[n];

}

case EOP_VAR: var = TestVarNum(*p++);

WriteToLog(_T("VAR_"),false);

WriteToLog(var,false);

return(&variables)[var];

case EOP_REF_VAR: {

var= TestVarNum(*p++);

intn = (&variables)[var];

WriteToLog(_T("REF_VAR_"),false);

WriteToLog(var,false);

return(&data)[n];

}

case EOP_CONST: WriteToLog(_T("CONST "), false);

return*p++;

case EOP_RAND: WriteToLog(_T("RAND "), false);

returnCoolRand();

default:CkgExcept(_T("error operand type"));

}

return 0; // antiwarning

}

//-----------------------------------------------------------------------------

voidSetValue(const int *&p, int &variables, int &registers,int &data,

intvalue)

{

E_OPERAND operand =static_cast(*p++);

int reg, var;

switch (operand)

{

case EOP_REG: reg = TestRegNum(*p++);

(&registers)[reg]= value;

WriteToLog(_T("REG_"),false);

WriteToLog(reg,false);

break;

case EOP_REF_REG: {

reg= TestRegNum(*p++);

intn = (&registers)[reg];

(&data)[n]= value;

WriteToLog(_T("REF_REG_"),false);

WriteToLog(reg,false);

break;

}

case EOP_VAR: var = TestVarNum(*p++);

(&variables)[var]= value;

WriteToLog(_T("VAR_"),false);

WriteToLog(var,false);

break;

case EOP_REF_VAR: {

var= TestVarNum(*p++);

intn = (&variables)[var];

(&data)[n]= value;

WriteToLog(_T("REF_VAR_"),false);

WriteToLog(var,false);

break;

}

default:CkgExcept(_T("error operand type"));

}

}

//-----------------------------------------------------------------------------

voidTranslateOperations(const int &operations, const int &variables,

BYTE&memory)

{

const int *p =&operations;

cpp_arr_ptrvars(new int[variablesNum]);

TestPtr(vars);

cpp_arr_ptrregs(new int[registersNum]);

TestPtr(regs);

memcpy(vars.ptr(),&variables, variablesNum * sizeof(int));

memset(regs.ptr(),0, registersNum * sizeof(int));

int *data =reinterpret_cast(&memory);

CkgSimpleContainerArraystack;

unsigned flags = 0;


WriteToLog(_T("\r\n===Start TranslateOperations ===\r\n"));


E_OPERATIONoperation;

for (;;)

{

if (*p == EO_ERROR)

CkgExcept(IDS_PL_ERROR_INSTRUCTION_IN_ALG_0);

if (*p LAST_OPERATION)

CkgExcept(IDS_PL_ERROR_INSTRUCTION_IN_ALG);

operation =static_cast(*p++);

switch (operation)

{

case EO_EXIT_0:WriteToLog(_T("exit")); return;

case EO_EXIT_1:WriteToLog(_T("exit")); return;

case EO_EXIT_2:WriteToLog(_T("exit")); return;

case EO_NOP_0: break;

case EO_NOP_1: break;

case EO_NOP_2: break;

case EO_NOP_3: break;

case EO_MOV: {

WriteToLog(_T("mov"), false);

constint *oldP = p;

SkepValue(p);

intvalue = GetValue(p, *vars, *regs, *data);

WriteToLog(_T("==> "), false);

SetValue(oldP,*vars, *regs, *data, value);

WriteToLog(_T(""));

break;

}

case EO_XCHG: {

constint *oldP = p;

WriteToLog(_T("xchg"), false);

intvalue1 = GetValue(p, *vars, *regs, *data);

intvalue2 = GetValue(p, *vars, *regs, *data);

p= oldP;

WriteToLog(_T(" "), false);

SetValue(p,*vars, *regs, *data, value2);

SetValue(p,*vars, *regs, *data, value1);

WriteToLog(_T(""));

break;

}

case EO_PUSH: {

WriteToLog(_T("push"), false);

intvalue = GetValue(p, *vars, *regs, *data);

WriteToLog(_T(""));

stack.Add(value);

break;

}

case EO_POP: {

WriteToLog(_T("pop"), false);

intvalue = stack.Remove(stack.GetSize() - 1);

SetValue(p,*vars, *regs, *data, value);

WriteToLog(_T(""));

break;

}

case EO_XOR:

case EO_AND:

case EO_OR:

case EO_ADD:

case EO_SUB:

case EO_MUL:

case EO_DIV:

{

constint *oldP = p;

#ifdefWRITE_LOG

if (operation == EO_XOR)

WriteToLog(_T("xor"), false);

elseif (operation == EO_AND)

WriteToLog(_T("and"), false);

elseif (operation == EO_OR)

WriteToLog(_T("or"), false);

elseif (operation == EO_ADD)

WriteToLog(_T("add"), false);

elseif (operation == EO_SUB)

WriteToLog(_T("sub"), false);

elseif (operation == EO_MUL)

WriteToLog(_T("mul"), false);

elseif (operation == EO_DIV)

WriteToLog(_T("div"), false);

#endif

intvalue1 = GetValue(p, *vars, *regs, *data);

intvalue2 = GetValue(p, *vars, *regs, *data);

WriteToLog(_T("==> "), false);

intresult = 0; // anti warning

if (operation == EO_XOR)

result= value1 ^ value2;

elseif (operation == EO_AND)

result= value1 & value2;

elseif (operation == EO_OR)

result= value1 | value2;

elseif (operation == EO_ADD)

result= value1 + value2;

elseif (operation == EO_SUB)

result= value1 - value2;

elseif (operation == EO_MUL)

result= value1 * value2;

elseif (operation == EO_DIV)

result= value1 / value2;

else

CkgExcept();

SetValue(oldP,*vars, *regs, *data, result);

WriteToLog(_T(""));

break;

}

case EO_NOT:

case EO_NEG:

case EO_INC:

case EO_DEC:

{

constint *oldP = p;

#ifdefWRITE_LOG

if (operation == EO_NOT)

WriteToLog(_T("not"), false);

elseif (operation == EO_NEG)

WriteToLog(_T("neg"), false);

elseif (operation == EO_INC)

WriteToLog(_T("inc"), false);

elseif (operation == EO_DEC)

WriteToLog(_T("dec"), false);

#endif

intvalue = GetValue(p, *vars, *regs, *data);

if (operation == EO_NOT)

value= 0 ^ value;

elseif (operation == EO_NEG)

value= -value;

elseif (operation == EO_INC)

value++;

elseif (operation == EO_DEC)

value--;

else

CkgExcept();

WriteToLog("==> ", false);

SetValue(oldP,*vars, *regs, *data, value);

WriteToLog("");

break;

}

case EO_CMP:

case EO_TEST:

{

#ifdefWRITE_LOG

if(operation == EO_CMP)

WriteToLog(_T("cmp"), false);

elseif (operation == EO_TEST)

WriteToLog(_T("test"), false);

#endif

intvalue1 = GetValue(p, *vars, *regs, *data);

intvalue2 = GetValue(p, *vars, *regs, *data);

WriteToLog("");

flags= 0;

if(operation == EO_CMP)

{

flags= ((value1 == value2) * EF_ZERO) |

((value1

}

elseif (operation == EO_TEST)

{

flags= (((value1 & value2) == 0) * EF_ZERO);

}

else

CkgExcept();

break;

}

case EO_JMP: {

WriteToLog(_T("jmp"), false);

intaddr = GetValue(p, *vars, *regs, *data);

WriteToLog("\r\n");

p= (&operations) + addr;

break;

}

case EO_CALL: {

WriteToLog(_T("call"), false);

intaddr = GetValue(p, *vars, *regs, *data);

WriteToLog("\r\n");

stack.Add(p- (&operations));

p= (&operations) + addr;

break;

}

case EO_RET: {

WriteToLog(_T("ret\r\n"));

intaddr = stack.Remove(stack.GetSize() - 1);

p= (&operations) + addr;

break;

}

case EO_JZ:

case EO_JNZ:

case EO_JA:

case EO_JNA:

{

#ifdefWRITE_LOG

if(operation == EO_JZ)

WriteToLog(_T("jz"), false);

if(operation == EO_JNZ)

WriteToLog(_T("jnz"), false);

if(operation == EO_JA)

WriteToLog(_T("ja"), false);

if(operation == EO_JNA)

WriteToLog(_T("jna"), false);

#endif


intaddr = GetValue(p, *vars, *regs, *data);

WriteToLog("\r\n");

if(operation == EO_JZ && !(flags & EF_ZERO))

break;

elseif (operation == EO_JNZ && (flags & EF_ZERO))

break;

elseif (operation == EO_JA && !(flags & EF_ABOVE))

break;

elseif (operation == EO_JNA && (flags & EF_ABOVE))

break;

p= (&operations) + addr;

break;

}

caseEO_TEST_TIME_0:

{

WriteToLog(_T("test_time0"), false);

intday = abs(GetValue(p, *vars, *regs, *data));

WriteToLog("");

if(static_cast(GetCurrentDayNum()) > day)

{

WriteToLog("ERRORTIME (except)");

data[0]^= 0x00030001;

break;

}

WriteToLog("OKTIME (continue)");

break;

}

caseEO_TEST_TIME_1:

{

WriteToLog(_T("test_time1"), false);

intdayTmp = GetValue(p, *vars, *regs, *data);

WriteToLog("");

unsignedday = static_cast(abs(dayTmp));

if(GetCurrentDayNum()

{

WriteToLog("OKTIME (continue)");

break;

}

WriteToLog("ERRORTIME (except)");

GetValue(p,*vars, *regs, *data);

GetValue(p,*vars, *regs, *data);

SetValue(p,*vars, *regs, *data, 0);

p= (&operations) - dayTmp;

break;

}

}

}

}

//-----------------------------------------------------------------------------

voidCryptDecryptData(BYTE &dataArray, size_t size, BYTE&algorithmDataArray,

size_talgorithmDataSize, bool crypt)

{

_ASSERT(dataSizeSmoothing>= sizeof(int) * maxNumTransformation);

if (!size ||!algorithmDataSize || size % dataSizeSmoothing != 0)

CkgExcept(ERROR_INVALID_ARGUMENT);

AlgorithmDataStruct&alg = reinterpret_cast

(algorithmDataArray);

if(alg.idSupportAlgorithm != idSupportAlgorithm ||

(crypt &&alg.idType != idCryptAlgorithm) ||

(!crypt &&alg.idType != idDecryptAlgorithm))

CkgExcept(_T("unsupportedcrypt algorithm type"));


if (alg.sizeAll !=algorithmDataSize)

CkgExcept(_T("errorcrypt algorithm size"));


alg.variables[alg.numVarForSetSize]= size / sizeof(int);


BYTE *p =&algorithmDataArray;

p += sizeofAlgorithmDataStruct;

// _ASSERT(DWORD(p) & 0x03 == 0x0);

_ASSERT(DWORD(p) %sizeof(int) == 0x0);

TranslateOperations(*reinterpret_cast(p), *alg.variables,

dataArray);

}

//-----------------------------------------------------------------------------

voidCryptData(BYTE &dataArray, size_t size, BYTE &algorithmDataArray,

size_talgorithmDataSize)

{

CryptDecryptData(dataArray,size, algorithmDataArray,

algorithmDataSize,true);

}

//-----------------------------------------------------------------------------

voidDecryptData(BYTE &dataArray, size_t size, BYTE&algorithmDataArray,

size_talgorithmDataSize)

{

CryptDecryptData(dataArray,size, algorithmDataArray,

algorithmDataSize,false);

}

//-----------------------------------------------------------------------------

voidCryptDecryptData(BYTE &dataArray, size_t size, const TCHAR&fileName,

boolcrypt)

{

FILE *f =_tfopen(&fileName, _T("rb"));

if (!f)

CkgExcept(ERROR_OPEN_FILE);

try

{

if (fseek(f, 0,SEEK_END))

CkgExcept(ERROR_READ_FILE);

longalgorithmDataSize = ftell(f);

cpp_arr_ptralgorithmDataArray(new BYTE[algorithmDataSize]);

TestPtr(algorithmDataArray);

if (fseek(f, 0,SEEK_SET))

CkgExcept(ERROR_READ_FILE);

if(fread(algorithmDataArray, sizeof(BYTE), algorithmDataSize, f) !=

static_cast(algorithmDataSize))

CkgExcept(ERROR_READ_FILE);

if (fclose(f))

CkgExcept(ERROR_CLOSE_FILE);

f = 0;

CryptDecryptData(dataArray,size, *algorithmDataArray,

algorithmDataSize,crypt);

}

catch (...)

{

if (f)

fclose(f);

throw;

}

}

//-----------------------------------------------------------------------------

voidCryptData(BYTE &dataArray, size_t size, const TCHAR &fileName)

{

CryptDecryptData(dataArray,size, fileName, true);

}

//-----------------------------------------------------------------------------

voidDecryptData(BYTE &dataArray, size_t size, const TCHAR &fileName)

{

CryptDecryptData(dataArray,size, fileName, false);

}

//-----------------------------------------------------------------------------

unsignedGetRandomNonUsedRegister(const AlgorithmParameters &parameters)

{

unsigned i;

unsignednumberNonUsedRegisters = 0;

for (i = 0; i

numberNonUsedRegisters+= !parameters.usedRegisters[i];

if(!numberNonUsedRegisters)

CkgExcept();

unsigned randomNum =CoolRand(numberNonUsedRegisters) + 1;

for (i = 0; i

{

randomNum -=!parameters.usedRegisters[i];

if (!randomNum)

break;

}

_ASSERT(!randomNum&& !parameters.usedRegisters[i]);

return i;

}

//-----------------------------------------------------------------------------

unsignedGetRandomNonUsedVariable(const AlgorithmParameters &parameters)

{

unsigned i;

unsignednumberNonUsedVariables = 0;

for (i = 0; i

numberNonUsedVariables+= !parameters.usedVariables[i];

if(!numberNonUsedVariables)

CkgExcept();

unsigned randomNum =CoolRand(numberNonUsedVariables) + 1;

for (i = 0; i

{

randomNum -=!parameters.usedVariables[i];

if (!randomNum)

break;

}

_ASSERT(!randomNum&& !parameters.usedVariables[i]);

return i;

}

//-----------------------------------------------------------------------------

unsignedReserveRandomNonUsedRegister(AlgorithmParameters &parameters)

{

unsigned num =GetRandomNonUsedRegister(parameters);

parameters.usedRegisters[num]= true;

return num;

}

//-----------------------------------------------------------------------------

unsignedReserveRandomNonUsedVariables(AlgorithmParameters &parameters)

{

unsigned num =GetRandomNonUsedVariable(parameters);

parameters.usedVariables[num]= true;

return num;

}

//-----------------------------------------------------------------------------

voidRandomInitAlgorithmParameters(AlgorithmParameters &parameters,

unsignednumTransformation)

{

unsigned i;

for (i = 0; i

parameters.usedRegisters[i]= false;

for (i = 0; i

parameters.usedVariables[i]= false;


parameters.sizeAlgorithm=

CoolRand(maxSizeAlgorithm- minSizeAlgorithm) + minSizeAlgorithm;

parameters.numTransformation= numTransformation;


parameters.addressIsReg= CoolRand(2) == 1;

if(parameters.addressIsReg)

parameters.addressNumber= ReserveRandomNonUsedRegister(parameters);

else

parameters.addressNumber= ReserveRandomNonUsedVariables(parameters);


for (i = 0; i

{

bool isReg =CoolRand(2) == 1;

parameters.modificatoryIsReg[i]= isReg;

if (isReg)

parameters.modificatorsNumbers[i]= ReserveRandomNonUsedRegister(parameters);

else

parameters.modificatorsNumbers[i]= ReserveRandomNonUsedVariables(parameters);

}


parameters.counterIsReg= CoolRand(2);

if(parameters.counterIsReg)

parameters.counterNumber= ReserveRandomNonUsedRegister(parameters);

else

parameters.counterNumber= ReserveRandomNonUsedVariables(parameters);


parameters.initCounterNumber= ReserveRandomNonUsedVariables(parameters);


parameters.totalNumTrueBlocks=

numBlocks +parameters.numTransformation * 2 - 2;

}

//-----------------------------------------------------------------------------

voidRandomInitAlgorithmParameters(AlgorithmParameters (&parameters)[2])

{

SYSTEMTIMElpSystemTime;

GetSystemTime(&lpSystemTime);

srand(unsigned(lpSystemTime.wSecond)* 1000 + lpSystemTime.wMilliseconds);


unsignednumTransformation = (maxNumTransformation > minNumTransformation)?

CoolRand(maxNumTransformation- minNumTransformation) + minNumTransformation :

1;

RandomInitAlgorithmParameters(parameters[0],numTransformation);

RandomInitAlgorithmParameters(parameters[1],numTransformation);

}

//-----------------------------------------------------------------------------

boolSearchSubstitution(const Block &block, unsigned &position)

{

unsigned blockSize =block.GetSize();

_ASSERT(position

for (; position

{

int a =block[position];

for (unsigned i =0; i

if(AllSubstitution[i] == a)

return true;

}

return false;

}

//-----------------------------------------------------------------------------

structSAppropriate

{

bool testSize;

unsigned maxSize;

bool testContain;

const int*shouldContain;

unsignednumShouldContain;

bool testNotContain;

unsignednumNotShouldContain;

const int*notShouldContain;


SAppropriate() :testSize(false), maxSize(0),

testContain(false),shouldContain(NULL), numShouldContain(0),

testNotContain(false),notShouldContain(NULL), numNotShouldContain(0)

{ }

~SAppropriate() { }

};

//-----------------------------------------------------------------------------

boolSearch(const int &block, unsigned blockSize, int needFind)

{

_ASSERT(blockSize);

unsigned j;

for (j = 0; j

if ((&block)[j]== needFind)

break;

return !(j ==blockSize);

}

//-----------------------------------------------------------------------------

boolSearchRandomAppropriateBlock(unsigned numberBlockForTest,

constunsigned &blocksSize,

constint * const &addrBlocks,

constSAppropriate &appropriate,

unsigned&retAppropriateBlock)

{

_ASSERT(numberBlockForTest);

CkgSimpleContainerArrayconvenianceSample;


for (unsigned i = 0;i

{

unsigned blockSize= (&blocksSize)[i];

_ASSERT(blockSize);

if(appropriate.testSize && blockSize > appropriate.maxSize)

continue;

const int *block =(&addrBlocks)[i];

_ASSERT(block);

if(appropriate.testContain)

{

_ASSERT(appropriate.shouldContain&& appropriate.numShouldContain);

bool found =true;

for (unsigned j =0; j

{

int needFind =appropriate.shouldContain[j];

found =Search(*block, blockSize, needFind);

}

if (!found)

continue;

}

if(appropriate.testNotContain)

{

_ASSERT(appropriate.notShouldContain&& appropriate.numNotShouldContain);

bool found =false;

for (unsigned j =0; j

{

int needFind =appropriate.notShouldContain[j];

found =Search(*block, blockSize, needFind);

}

if (found)

continue;

}

convenianceSample.Add(i);

}

unsignednumConvenianceSample = convenianceSample.GetSize();

if(!numConvenianceSample)

return false;

unsigned select =numConvenianceSample > 1 ?

CoolRand(numConvenianceSample):

0;

retAppropriateBlock= convenianceSample[select];

return true;

}

//-----------------------------------------------------------------------------

boolReplacemenRandomEntity(int &entity, const AlgorithmParameters&parameters)

{

switch (entity)

{

case ES_RANDOM_NOP: {

unsignedNumNops = LAST_DEFINED_NOP - EO_NOP_0;

entity= CoolRand(NumNops);

entity+= EO_NOP_0;

_ASSERT(entity>= EO_NOP_0 && entity

break;

}

caseES_RANDOM_CONST: entity = CoolRand(); break;

case ES_RANDOM_REG: entity = GetRandomNonUsedRegister(parameters); break;

case ES_RANDOM_VAR: entity = GetRandomNonUsedVariable(parameters); break;

caseES_RANDOM_USE_REG: entity = CoolRand(registersNum); break;

caseES_RANDOM_USE_VAR: entity = CoolRand(variablesNum); break;

default: returnfalse;

}

return true;

}

//-----------------------------------------------------------------------------

voidCreateNopBlock(Block &block, AlgorithmParameters &parameters,cpp_arr_ptr &,

unsignedmaxSize)

{

_ASSERT(block.IsEmpty());

if (!maxSize)

CkgExcept();


SAppropriateappropriate;

appropriate.testSize= true;

appropriate.maxSize= maxSize;


unsigned index;

if(!SearchRandomAppropriateBlock(sizeBlocksArray_Nops,*sizeBlocks_Nops,

*blocks_Nops,appropriate, index))

CkgExcept();


for (unsigned i = 0;i

block.Add(blocks_Nops[index][i]);


unsigned position =0;

while(SearchSubstitution(block, position))

{

if(!ReplacemenRandomEntity(block.GetRef(position), parameters))

CkgExcept();

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

}

//-----------------------------------------------------------------------------

voidCreateBlock0_(Block &block, AlgorithmParameters &parameters,cpp_arr_ptr &)

{

_ASSERT(block.IsEmpty());

SAppropriateappropriate;

appropriate.testContain= true;


appropriate.numShouldContain= 1;

int whatSearch =parameters.addressIsReg ? ES_REG_0 : ES_VARIABLE_0;

appropriate.shouldContain= &whatSearch;


unsigned index;

if(!SearchRandomAppropriateBlock(sizeBlocksArray_00, *sizeBlocks_00,

*blocks_00,appropriate, index))

CkgExcept();


for (unsigned i = 0;i

block.Add(blocks_00[index][i]);


unsigned position =0;

while(SearchSubstitution(block, position))

{

if(!ReplacemenRandomEntity(block.GetRef(position), parameters))

{

int newValue =EO_ERROR;

int b =block[position];

switch (b)

{

case ES_REG_0: _ASSERT(parameters.addressIsReg);

newValue= parameters.addressNumber;

break;

caseES_VARIABLE_0: _ASSERT(!parameters.addressIsReg);

newValue= parameters.addressNumber;

break;

default:CkgExcept();

}

block.GetRef(position)= newValue;

}

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

}

//-----------------------------------------------------------------------------

voidCreateBlock0(Block block[], AlgorithmParameters parameters[],cpp_arr_ptr vars[])

{

CreateBlock0_(block[0],parameters[0], vars[0]);

CreateBlock0_(block[1],parameters[1], vars[1]);

}

//-----------------------------------------------------------------------------

voidCreateBlock1_(Block &block, AlgorithmParameters &parameters,cpp_arr_ptr &)

{

_ASSERT(block.IsEmpty());

SAppropriateappropriate;

appropriate.testContain= true;


appropriate.numShouldContain= 1;

int whatSearch =parameters.counterIsReg ? ES_REG_0 : ES_VARIABLE_0;

appropriate.shouldContain= &whatSearch;


unsigned index;

if(!SearchRandomAppropriateBlock(sizeBlocksArray_01, *sizeBlocks_01,

*blocks_01,appropriate, index))

CkgExcept();


for (unsigned i = 0;i

block.Add(blocks_01[index][i]);


unsigned position =0;

while(SearchSubstitution(block, position))

{

if(!ReplacemenRandomEntity(block.GetRef(position), parameters))

{

int newValue =EO_ERROR;

int b =block[position];

switch (b)

{

case ES_REG_0: _ASSERT(parameters.counterIsReg);

newValue= parameters.counterNumber;

break;

caseES_VARIABLE_0: _ASSERT(!parameters.counterIsReg);

newValue= parameters.counterNumber;

break;

caseES_VARIABLE_1: newValue =

parameters.initCounterNumber;

break;

default:CkgExcept();

}

block.GetRef(position)= newValue;

}

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

}

//-----------------------------------------------------------------------------

voidCreateBlock1(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptrvars[])

{

CreateBlock1_(block[0],parameters[0], vars[0]);

CreateBlock1_(block[1],parameters[1], vars[1]);

}

//-----------------------------------------------------------------------------

voidCreateBlock2_(Block &block, AlgorithmParameters &parameters,

cpp_arr_ptr&vars, unsigned n, int randValue)

{

_ASSERT(n

SAppropriateappropriate;

appropriate.testContain= true;

appropriate.numShouldContain= 1;

int whatSearch =parameters.modificatoryIsReg[n] ? ES_REG_0 : ES_VARIABLE_0;

appropriate.shouldContain= &whatSearch;


unsigned index;

if(!SearchRandomAppropriateBlock(sizeBlocksArray_02, *sizeBlocks_02,

*blocks_02,appropriate, index))

CkgExcept();


for (unsigned i = 0;i

block.Add(blocks_02[index][i]);


unsigned position =0;

while(SearchSubstitution(block, position))

{

if(!ReplacemenRandomEntity(block.GetRef(position), parameters))

{

int newValue =EO_ERROR;

int b =block[position];

switch (b)

{

case ES_REG_0: _ASSERT(parameters.modificatoryIsReg[n]);

newValue= parameters.modificatorsNumbers[n];

break;

caseES_VARIABLE_0: _ASSERT(!parameters.modificatoryIsReg[n]);

newValue= parameters.modificatorsNumbers[n];

break;

caseES_VARIABLE_1: {

unsignedvarNum =

ReserveRandomNonUsedVariables(parameters);

vars[varNum]= randValue;

newValue= static_cast(varNum);

break;

}

case ES_CONST_0: newValue = randValue;

break;

default:CkgExcept();

}

block.GetRef(position)= newValue;

}

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

}

//-----------------------------------------------------------------------------

voidCreateBlock2(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptrvars[], unsigned n)

{

int randValue =CoolRand();

CreateBlock2_(block[0],parameters[0], vars[0], n, randValue);

CreateBlock2_(block[1],parameters[1], vars[1], n, randValue);

}

//-----------------------------------------------------------------------------

voidCalcBlocksSize(Block (*blocks)[2], unsigned num, unsigned &size1,unsigned &size2)

{

_ASSERT(num);

unsigned i;

size1 = 0;

for (i = 0; i

size1 +=blocks[i][0].GetSize();

size2 = 0;

for (i = 0; i

size2 +=blocks[i][1].GetSize();

}

//-----------------------------------------------------------------------------

voidCreateLoopAddres_(unsigned num, const AlgorithmParameters&parameters,

unsignedsizeBeforeLoop,

unsigned&addr)

{

const doubledispersion = 0.1;

const double k =(static_cast(CoolRand()) / INT_MAX) * dispersion;

_ASSERT(fabs(k)

const double allSize = parameters.sizeAlgorithm;

const doublesizeInBlocks = num;

const doubleallSizeInBlocks = parameters.totalNumTrueBlocks;

double randAddr = sizeInBlocks * allSize / allSizeInBlocks;

_ASSERT(static_cast(randAddr)> sizeBeforeLoop);

randAddr += randAddr* k;

addr =static_cast(randAddr);

_ASSERT(addr >=sizeBeforeLoop);

if (addr

CkgExcept();

}

//-----------------------------------------------------------------------------

voidCreateLoopAddres(unsigned num, const AlgorithmParametersparameters[],

unsignedsizeBeforeLoop1,

unsignedsizeBeforeLoop2,

unsigned&addr1, unsigned &addr2)

{

_ASSERT(sizeBeforeLoop1&& sizeBeforeLoop2);

CreateLoopAddres_(num,parameters[0], sizeBeforeLoop1, addr1);

CreateLoopAddres_(num,parameters[1], sizeBeforeLoop2, addr2);

}

//-----------------------------------------------------------------------------

voidCreateBlock3_(Block &block, AlgorithmParameters &parameters,

cpp_arr_ptr&, unsigned n, int &numSelectedBlock,

booluseCounterForModify)

{

_ASSERT(CALC_ARRAY_SIZE(block_03_operation_AB)==

CALC_ARRAY_SIZE(block_03_operation_BA));


bool isBA =numSelectedBlock != -1;

if (!isBA)

{

numSelectedBlock =CALC_ARRAY_SIZE(block_03_operation_AB) > 1 ?

CoolRand(CALC_ARRAY_SIZE(block_03_operation_AB)): 0;

}


SAppropriateappropriate;

appropriate.testContain= true;

appropriate.numShouldContain= 1 + useCounterForModify;

unsigned index;

int whatSearch[2];

whatSearch[0] =parameters.addressIsReg ? ES_REG_0 : ES_VARIABLE_0;

whatSearch[1] =parameters.counterIsReg ? ES_REG_2 : ES_VARIABLE_2;

appropriate.shouldContain= whatSearch;


appropriate.testNotContain= true;

appropriate.numNotShouldContain= 2 + (!useCounterForModify) * 2;

intwhatNotContain[4];

appropriate.notShouldContain= whatNotContain;

whatNotContain[0] =!parameters.modificatoryIsReg[n] ?

ES_REG_1: ES_VARIABLE_1;

whatNotContain[1] =!parameters.counterIsReg ?

ES_REG_2: ES_VARIABLE_2;

whatNotContain[2] =ES_VARIABLE_2;

whatNotContain[3] =ES_REG_2;


if(!SearchRandomAppropriateBlock(sizeBlocksArray_03, *sizeBlocks_03,

*blocks_03,appropriate, index))

CkgExcept();

index;


for (unsigned i = 0;i

block.Add(blocks_03[index][i]);


unsigned position =0;

int checkCountUse =useCounterForModify;

while(SearchSubstitution(block, position))

{

if(!ReplacemenRandomEntity(block.GetRef(position), parameters))

{

int newValue =EO_ERROR;

int b =block[position];

switch (b)

{

case ES_REG_0: _ASSERT(parameters.addressIsReg);

newValue= parameters.addressNumber;

break;

case ES_REG_1: _ASSERT(parameters.modificatoryIsReg[n]);

newValue= parameters.modificatorsNumbers[n];

break;

case ES_REG_2: _ASSERT(parameters.counterIsReg);

newValue= parameters.counterNumber;

checkCountUse--;

_ASSERT(checkCountUse== 0);

break;

caseES_VARIABLE_0: _ASSERT(!parameters.addressIsReg);

newValue= parameters.addressNumber;

break;

caseES_VARIABLE_1: _ASSERT(!parameters.modificatoryIsReg[n]);

newValue= parameters.modificatorsNumbers[n];

break;

caseES_VARIABLE_2: _ASSERT(!parameters.counterIsReg);

newValue= parameters.counterNumber;

checkCountUse--;

_ASSERT(checkCountUse== 0);

break;

caseES_SPECIFIC_0: if (isBA)

newValue= block_03_operation_BA[numSelectedBlock];

else

newValue= block_03_operation_AB[numSelectedBlock];

break;

default:CkgExcept();

}

block.GetRef(position)= newValue;

}

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

if (checkCountUse !=0)

CkgExcept(_T("Ошибкав алгоритмегенерацииUPT-файлов (functionCreateBlock3_). Обратитеськ разработчику."));

}

//-----------------------------------------------------------------------------

voidCreateBlock3AB(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptrvars[], unsigned n,

int&numSelectedBlock, bool useCounterForModify)

{

_ASSERT(vars &&n

numSelectedBlock =-1;

CreateBlock3_(block[0],parameters[0], vars[0], n, numSelectedBlock,

useCounterForModify);

_ASSERT(numSelectedBlock>= 0);

}

//-----------------------------------------------------------------------------

voidCreateBlock3BA(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptrvars[], unsigned n,

intnumSelectedBlock, bool useCounterForModify)

{

_ASSERT(vars &&n

_ASSERT(numSelectedBlock>= 0);

CreateBlock3_(block[1],parameters[1], vars[1], n, numSelectedBlock,

useCounterForModify);

}

//-----------------------------------------------------------------------------

voidCreateBlock4_(Block &block, AlgorithmParameters &parameters,cpp_arr_ptr &)

{

_ASSERT(block.IsEmpty());

SAppropriateappropriate;

appropriate.testContain= true;


appropriate.numShouldContain= 1;

int whatSearch =parameters.addressIsReg ? ES_REG_0 : ES_VARIABLE_0;

appropriate.shouldContain= &whatSearch;


unsigned index;

if(!SearchRandomAppropriateBlock(sizeBlocksArray_04, *sizeBlocks_04,

*blocks_04,appropriate, index))

CkgExcept();


for (unsigned i = 0;i

block.Add(blocks_04[index][i]);


unsigned position =0;

while(SearchSubstitution(block, position))

{

if(!ReplacemenRandomEntity(block.GetRef(position), parameters))

{

int newValue =EO_ERROR;

int b =block[position];

switch (b)

{

case ES_REG_0: _ASSERT(parameters.addressIsReg);

newValue= parameters.addressNumber;

break;

caseES_VARIABLE_0: _ASSERT(!parameters.addressIsReg);

newValue= parameters.addressNumber;

break;

default:CkgExcept();

}

block.GetRef(position)= newValue;

}

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

}

//-----------------------------------------------------------------------------

voidCreateBlock4(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptrvars[])

{

CreateBlock4_(block[0],parameters[0], vars[0]);

CreateBlock4_(block[1],parameters[1], vars[1]);

}

//-----------------------------------------------------------------------------

voidCreateBlock5_(Block &block, AlgorithmParameters &parameters,

cpp_arr_ptr&, unsigned addr)

{

_ASSERT(block.IsEmpty());

SAppropriateappropriate;

appropriate.testContain= true;


appropriate.numShouldContain= 1;

int whatSearch =parameters.counterIsReg ? ES_REG_0 : ES_VARIABLE_0;

appropriate.shouldContain= &whatSearch;


unsigned index;

if(!SearchRandomAppropriateBlock(sizeBlocksArray_05, *sizeBlocks_05,

*blocks_05,appropriate, index))

CkgExcept();


for (unsigned i = 0;i

block.Add(blocks_05[index][i]);


unsigned position =0;

while(SearchSubstitution(block, position))

{

if(!ReplacemenRandomEntity(block.GetRef(position), parameters))

{

int newValue =EO_ERROR;

int b =block[position];

switch (b)

{

case ES_REG_0: _ASSERT(parameters.counterIsReg);

newValue= parameters.counterNumber;

break;

caseES_VARIABLE_0: _ASSERT(!parameters.counterIsReg);

newValue= parameters.counterNumber;

break;

caseES_ADDRESS_0: newValue = static_cast(addr);

break;

default:CkgExcept();

}

block.GetRef(position)= newValue;

}

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

}

//-----------------------------------------------------------------------------

voidCreateBlock5(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptrvars[], unsigned addr1, unsigned addr2)

{

CreateBlock5_(block[0],parameters[0], vars[0], addr1);

CreateBlock5_(block[1],parameters[1], vars[1], addr2);

}

//-----------------------------------------------------------------------------

voidCreateBlock6_(Block &block, AlgorithmParameters &parameters,

cpp_arr_ptr&vars, int deltaTime)

{

_ASSERT(block.IsEmpty());

SAppropriateappropriate;

unsigned index;

if(!SearchRandomAppropriateBlock(sizeBlocksArray_06, *sizeBlocks_06,

*blocks_06,appropriate, index))

CkgExcept();


for (unsigned i = 0;i

block.Add(blocks_06[index][i]);


unsigned position =0;

while(SearchSubstitution(block, position))

{

if(!ReplacemenRandomEntity(block.GetRef(position), parameters))

{

int newValue =EO_ERROR;

int b =block[position];

switch (b)

{

case ES_CONST_0: newValue = deltaTime;

break;

caseES_VARIABLE_0: newValue = ReserveRandomNonUsedVariables(parameters);

vars[static_cast(newValue)]= deltaTime;

break;

default:CkgExcept();

}

block.GetRef(position)= newValue;

}

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

}

//-----------------------------------------------------------------------------

voidCreateBlock6(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptrvars[], unsigned deltaTimeCrypt,

unsigneddeltaTimeDecrypt)

{

_ASSERT((deltaTimeCrypt== 0) == (deltaTimeDecrypt == 0));

if (!deltaTimeCrypt)

{

int entity;

unsigned NumNops =LAST_DEFINED_NOP - EO_NOP_0;

entity =CoolRand(NumNops);

entity += EO_NOP_0;

_ASSERT(entity >=EO_NOP_0 && entity

block->Add(entity);

return;

}


if(deltaTimeCrypt > maxUseTime || deltaTimeCrypt > INT_MAX ||

deltaTimeDecrypt> maxUseTime || deltaTimeDecrypt > INT_MAX)

CkgExcept(_T("Заданслишком большойпериод временидля возможностииспользованияалгоритма."));

boolinvert = CoolRand(2) == 1;

intnewDeltaTimeCrypt = invert ? -static_cast(deltaTimeCrypt):

static_cast(deltaTimeCrypt);

invert = CoolRand(2)== 1;

intnewDeltaTimeDecrypt = invert ? -static_cast(deltaTimeDecrypt):

static_cast(deltaTimeDecrypt);

CreateBlock6_(block[0],parameters[0], vars[0], newDeltaTimeCrypt);

CreateBlock6_(block[1],parameters[1], vars[1], newDeltaTimeDecrypt);

}

//-----------------------------------------------------------------------------

voidCreateBlock7_(Block &block, AlgorithmParameters &parameters,

cpp_arr_ptr&)

{

_ASSERT(block.IsEmpty());

SAppropriateappropriate;


unsigned index;

if(!SearchRandomAppropriateBlock(sizeBlocksArray_07, *sizeBlocks_07,

*blocks_07,appropriate, index))

CkgExcept();


for (unsigned i = 0;i

block.Add(blocks_07[index][i]);


unsigned position =0;

while(SearchSubstitution(block, position))

{

if(!ReplacemenRandomEntity(block.GetRef(position), parameters))

CkgExcept();

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

}

//-----------------------------------------------------------------------------

voidCreateBlock7(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptrvars[])

{

CreateBlock7_(block[0],parameters[0], vars[0]);

CreateBlock7_(block[1],parameters[1], vars[1]);

}

//-----------------------------------------------------------------------------

voidGenerateArrayRndDeltas(CkgSimpleContainerArray&deltas,

unsignednum, unsigned freeRegionSize)

{

_ASSERT(num &&freeRegionSize);

_ASSERT(deltas.IsEmpty());

unsigned i;

for (i = 0; i

{

unsigned rnd;

#ifdef_DEBUG

unsigned counter =0;

#endif

do

{

_ASSERT(counter++

rnd =CoolRand(freeRegionSize);

if(freeRegionSize

CkgExcept(_T("Ошибкав алгоритмегенерацииUPT-файлов (functionGenerateArrayRndDeltas). Обратитеськ разработчику."));

}while(deltas.IndexOf(rnd) != -1);

deltas.Add(rnd);

}


deltas.Add(freeRegionSize);


for(i = 0; i

for (unsigned j = i+ 1; j

if (deltas[j]

deltas.Swap(j,i);


for (i =deltas.GetSize() - 1; i > 0; i--)

{

_ASSERT(deltas[i] >deltas[i - 1]);

deltas.GetRef(i) -=deltas[i - 1];

}


#ifdef _DEBUG

{

unsigned size = 0;

for (i = 0; i

size +=deltas[i];

_ASSERT(size ==freeRegionSize);

}

#endif

}

//-----------------------------------------------------------------------------

voidGenerateAndAddNopBlocks(const CkgSimpleContainerArray&deltas,

CkgArray&newArray,

AlgorithmParameters&parameters,

cpp_arr_ptrvars[],

Block(*blocks)[2], bool isBA,

unsignednumFirstBlock)

{

_ASSERT(!deltas.IsEmpty());

for (unsigned i = 0;i

{

unsigned delta =deltas[i];

while (delta)

{

cpp_ptrnopBlock(new Block);

TestPtr(nopBlock);

CreateNopBlock(*nopBlock,parameters, *vars, delta);

unsignednopBlockSize = nopBlock->GetSize();

_ASSERT(nopBlockSize&& nopBlockSize

delta -=nopBlockSize;

newArray.Add(*nopBlock);

nopBlock.Detach();

}

if (i !=deltas.GetSize() - 1)

{

cpp_ptrtmp(new Block);

TestPtr(tmp);

unsigned size =blocks[numFirstBlock + i][isBA].GetSize();

for (unsigned j =0; j

tmp->Add(blocks[numFirstBlock+ i][isBA][j]);

newArray.Add(*tmp);

tmp.Detach();

}

}

}

//-----------------------------------------------------------------------------

voidSmearAndAddNopBlocks(Block (*blocks)[2], bool isBA,

AlgorithmParameters&parameters,

cpp_arr_ptrvars[],

CkgArray&newArray, unsigned addr)

{

_ASSERT(blocks &&vars && newArray.IsEmpty());

unsigned i;

unsignedfreeRegionSize = addr;

unsignedtotalNumTrueBlocks = parameters.totalNumTrueBlocks;

unsignedblocksBeforeLoop = numBlocksBeforeLoop +parameters.numTransformation - 1;

unsignedblocksAfterLoop = totalNumTrueBlocks - blocksBeforeLoop;

for (i = 0; i

freeRegionSize -=blocks[i][isBA].GetSize();

_ASSERT(static_cast(freeRegionSize)> 0); // Не ошибка,но "рисково"получилось.


CkgSimpleContainerArraydeltas;

GenerateArrayRndDeltas(deltas,blocksBeforeLoop, freeRegionSize);

_ASSERT(deltas.GetSize()== blocksBeforeLoop + 1);


GenerateAndAddNopBlocks(deltas,newArray, parameters, vars,

blocks,isBA, 0);

#ifdef _DEBUG

{

unsigned size = 0;

for (i = 0; i

size +=newArray[i].GetSize();

_ASSERT(size ==addr);

}

#endif


deltas.Clear();


_ASSERT(parameters.sizeAlgorithm> addr);

freeRegionSize =parameters.sizeAlgorithm - addr;

for (i =blocksBeforeLoop; i

freeRegionSize -=blocks[i][isBA].GetSize();

_ASSERT(static_cast(freeRegionSize)> 0); // Не ошибка,но "рисково"получилось.


GenerateArrayRndDeltas(deltas,blocksAfterLoop, freeRegionSize);

_ASSERT(deltas.GetSize()== blocksAfterLoop + 1);


GenerateAndAddNopBlocks(deltas,newArray, parameters, vars,

blocks,isBA, blocksBeforeLoop);

}

//-----------------------------------------------------------------------------

staticint DebugFindMaxBlockSize(unsigned n, const unsigned *sizes)

{

_ASSERT(n &&sizes);

unsigned max = 0;

for (unsigned i = 0;i

if (max

max = sizes[i];

_ASSERT(max);

return max;

}

//-----------------------------------------------------------------------------

staticvoid DebugTestParam()

{

unsigned sum = 0;

sum +=DebugFindMaxBlockSize(sizeBlocksArray_00, sizeBlocks_00);

sum +=DebugFindMaxBlockSize(sizeBlocksArray_01, sizeBlocks_01);

sum +=DebugFindMaxBlockSize(sizeBlocksArray_02, sizeBlocks_02);

sum +=DebugFindMaxBlockSize(sizeBlocksArray_03, sizeBlocks_03);

sum +=DebugFindMaxBlockSize(sizeBlocksArray_04, sizeBlocks_04);

sum +=DebugFindMaxBlockSize(sizeBlocksArray_05, sizeBlocks_05);

sum +=DebugFindMaxBlockSize(sizeBlocksArray_06, sizeBlocks_06);

sum+= DebugFindMaxBlockSize(sizeBlocksArray_07, sizeBlocks_07);

WriteToLog(_T("CalcMax Algorithm Size = "), false);

WriteToLog(sum);

// Еслименьше, то навернолегко словитьошибку.

_ASSERT(sum* 2

}

//-----------------------------------------------------------------------------

voidGenerateAlgorithm(pure_c_ptr &algorithmCrypt, size_t &sizeCrypt,

pure_c_ptr&algorithmDecrypt, size_t &sizeDecrypt,

unsigneddeltaTimeCrypt, unsigned deltaTimeDecrypt)

{

WriteToLog(_T("GenerateAlgorithm()"));

#ifdef _DEBUG

DebugTestParam();

#endif

unsigned i, j;

AlgorithmParametersparameters[2];

RandomInitAlgorithmParameters(parameters);


cpp_arr_ptrvars[2];

for (unsigned k = 0;k

{

vars[k] = newint[variablesNum * sizeof(int)];

TestPtr(vars[k]);

for (i = 0; i

vars[k][i] =CoolRand();

}


Block (*blocks)[2] =new Block[parameters[0].totalNumTrueBlocks][2];

cpp_arr_ptrmemControl(blocks);


unsigned num = 0;

CreateBlock0(blocks[num++],parameters, vars);

CreateBlock1(blocks[num++],parameters, vars);


for (i = 0; i

CreateBlock2(blocks[num++],parameters, vars, i);

unsignedsizeBeforeLoop1, sizeBeforeLoop2;

CalcBlocksSize(blocks,num, sizeBeforeLoop1, sizeBeforeLoop2);

unsigned addr1 = 0,addr2 = 0;


CreateLoopAddres(num,parameters, sizeBeforeLoop1, sizeBeforeLoop2, addr1, addr2);


CkgSimpleContainerArrayselectedBlocks;

CkgSimpleContainerArrayarrUseCounterForModify;


for (i = 0; i

{

intnumSelectedBlock = -1;

booluseCounterForModify = CoolRand(2) == 1;

CreateBlock3AB(blocks[num++],parameters, vars, i, numSelectedBlock,

useCounterForModify);

selectedBlocks.Add(numSelectedBlock);

arrUseCounterForModify.Add(useCounterForModify);

}


_ASSERT(selectedBlocks.GetSize()== parameters[0].numTransformation);


for (i = 0; i

{

CreateBlock3BA(blocks[num- 1 - i], parameters, vars, i,

selectedBlocks[i],arrUseCounterForModify[i]);

}


CreateBlock4(blocks[num++],parameters, vars);

CreateBlock5(blocks[num++],parameters, vars, addr1, addr2);

CreateBlock6(blocks[num++],parameters, vars, deltaTimeCrypt, deltaTimeDecrypt);

CreateBlock7(blocks[num++],parameters, vars);

_ASSERT(num ==parameters[0].totalNumTrueBlocks);


CkgArrayblocksAB;

CkgArrayblocksBA;


SmearAndAddNopBlocks(blocks,false, parameters[0], vars, blocksAB, addr1);

SmearAndAddNopBlocks(blocks,true, parameters[1], vars, blocksBA, addr2);


#ifdef _DEBUG

{

unsigned sizeAB =0;

for (i = 0; i

sizeAB +=blocksAB[i].GetSize();

unsigned sizeBA =0;

for (i = 0; i

sizeBA +=blocksBA[i].GetSize();

_ASSERT(sizeAB ==parameters[0].sizeAlgorithm);

_ASSERT(sizeBA ==parameters[1].sizeAlgorithm);

}

#endif

unsigned sizeAB =sizeof(AlgorithmDataStruct) +

parameters[0].sizeAlgorithm* sizeof(int);

unsigned sizeBA =sizeof(AlgorithmDataStruct) +

parameters[1].sizeAlgorithm* sizeof(int);


pure_c_ptralgorithmAB(static_cast(AccurateMalloc(sizeAB)));

pure_c_ptralgorithmBA(static_cast(AccurateMalloc(sizeBA)));


AlgorithmDataStruct&algorithmStructAB =

reinterpret_cast(*algorithmAB);

AlgorithmDataStruct&algorithmStructBA =

reinterpret_cast(*algorithmBA);


algorithmStructAB.idSupportAlgorithm= idSupportAlgorithm;

algorithmStructAB.idType= idCryptAlgorithm;

algorithmStructAB.sizeAll= sizeAB;

algorithmStructAB.numVarForSetSize= parameters[0].initCounterNumber;

memcpy(algorithmStructAB.variables,vars[0], sizeof(int) * variablesNum);


algorithmStructBA.idSupportAlgorithm= idSupportAlgorithm;

algorithmStructBA.idType= idDecryptAlgorithm;

algorithmStructBA.sizeAll= sizeBA;

algorithmStructBA.numVarForSetSize= parameters[1].initCounterNumber;

memcpy(algorithmStructBA.variables,vars[1], sizeof(int) * variablesNum);


_ASSERT(sizeof(AlgorithmDataStruct)% sizeof(int) == 0);

int *p = algorithmAB+ sizeof(AlgorithmDataStruct) / sizeof(int);

for (i = 0; i

for (j = 0; j

*p++ =blocksAB[i][j];

p = algorithmBA +sizeof(AlgorithmDataStruct) / sizeof(int);

for (i = 0; i

for (j = 0; j

*p++ =blocksBA[i][j];


algorithmCrypt =reinterpret_cast(algorithmAB.ptr());

algorithmAB.Detach();

sizeCrypt = sizeAB;

algorithmDecrypt =reinterpret_cast(algorithmBA.ptr());

algorithmBA.Detach();

sizeDecrypt =sizeBA;

}

//-----------------------------------------------------------------------------

voidGenerateAlgorithm(const TCHAR &algorithmCryptFileName,

constTCHAR &algorithmDecryptFileName,

unsigneddeltaTimeCrypt,

unsigneddeltaTimeDecrypt)

{

pure_c_ptralgorithmCrypt;

size_t sizeCrypt;

pure_c_ptralgorithmDecrypt;

size_t sizeDecrypt;


GenerateAlgorithm(algorithmCrypt,sizeCrypt, algorithmDecrypt, sizeDecrypt,

deltaTimeCrypt,deltaTimeDecrypt);

if(!algorithmCrypt|| !sizeCrypt || !algorithmDecrypt || !sizeDecrypt)

CkgExcept();


FILE *f = NULL;

try

{

f =_tfopen(&algorithmCryptFileName, _T("wb"));

if (!f)

CkgExcept(ERROR_OPEN_FILE);

if(fwrite(algorithmCrypt, sizeof(BYTE), sizeCrypt, f) != sizeCrypt)

CkgExcept(ERROR_WRITE_FILE);

if (fclose(f))

CkgExcept(ERROR_CLOSE_FILE);

f =_tfopen(&algorithmDecryptFileName, _T("wb"));

if (!f)

CkgExcept(ERROR_OPEN_FILE);

if(fwrite(algorithmDecrypt, sizeof(BYTE), sizeDecrypt, f) !=sizeDecrypt)

CkgExcept(ERROR_WRITE_FILE);

if (fclose(f))

CkgExcept(ERROR_CLOSE_FILE);

}

catch (...)

{

if (f)

fclose(f);

throw;

}

}

//-----------------------------------------------------------------------------

intCoolRand()

{

static unsignedflagInit;


int a = rand();

if (flagInit == 0)

{

SYSTEMTIMElpSystemTime;

GetSystemTime(&lpSystemTime);

srand(unsigned(lpSystemTime.wSecond)* 1000 + lpSystemTime.wMilliseconds);

flagInit = 1000;

}

else

flagInit--;


int b = rand();

int c = rand();

a

b

c += a;

c ^= b;

return c;

}

//-----------------------------------------------------------------------------

intCoolRand(unsigned limit)

{

_ASSERT(limit >1);

returnstatic_cast(CoolRand()) % limit;

}

//-----------------------------------------------------------------------------

staticunsigned DataToDay(unsigned Year, unsigned Month, unsigned Day)

{

if (Month > 2)

++Month;

else

{

Month+=13;

--Year;

}

returnstatic_cast(365.25*Year) +

static_cast(30.6*Month)+ Day;

}

//=============================================================================unsignedGetCurrentDayNum()

unsignedGetCurrentDayNum()

{

SYSTEMTIMElpSystemTime;

GetSystemTime(&lpSystemTime);

unsigned year =lpSystemTime.wYear;

unsigned month =lpSystemTime.wMonth;

unsigned day =lpSystemTime.wDay;


unsigned temp =DataToDay(year, month, day);


if (year

CkgExcept(_T("Накомпьютеревыставленневерный год."));

year-= MIN_YEAR;


unsigned result =DataToDay(year, month, day);


if (temp == result)

return INT_MAX - 1;


if(DataToDay(year, month, day + 12) != result + 12)

return INT_MAX;


return result;

}

//-----------------------------------------------------------------------------


ФайлArchiverBase.h.


#ifndef__ARCHIVERBASE_H_

#define__ARCHIVERBASE_H_


#include"resource.h" // main symbols


conststatic DWORD signature = 0xCAB00100;


enumEIAB_ErrorNum

{

IAB_OK = 0,

IAB_ERROR_BUF_SIZE = 1,

IAB_ERROR_ALLOCATE_MEMORY = 2,

IAB_CRC_ERROR = 3,

IAB_THIS_IS_NOT_ARCHIVE = 4,

IAB_UNKNOWN_ERROR = 5

};


structTitleArcData

{

DWORD signature;// Для идентификации,что это действительно

//поддерживаемаяTitleArcData

unsignedlongcrcPack; // CRCвсех данныхпосле упаковки,кроме

//этого первогои второго пля

//(TitleArcDataестественноне пакуется)

bool isPacked; // = true - данные былисжаты

//= false- данные не сжаты,так как слишком

// плохо пакуются(записаны какесть)

unsignedlongsizeUnpack;//Размер распакованныхданных

unsignedlongcrcUnpack;// CRCраспакованныхданных

unsignedlong titleSize; // РазмерструктурыTitleArcData

//Предназначенодля возможностидальнейшего

//расширенияэтой структуры

staticinlineGetSizeSkeep()// Сколько отступит,чтоб посчитатьcrcPack

{return sizeof(DWORD) + sizeof(unsigned long); }

};


boolCrc32(

/* [in] */ unsigned long size,

/*[size_is][in] */ byte __RPC_FAR *buf,

/* [retval][out] */unsigned long __RPC_FAR *crc);

boolCrc32Continue(

/* [in] */ unsigned long oldCrc,

/* [in] */ unsigned long size,

/* [size_is][in] */byte __RPC_FAR *buf,

/* [retval][out] */unsigned long __RPC_FAR *crc);

boolPack(

/* [in] */ byte compressionLevel,

/* [in] */ unsigned long sizeIn,

/* [size_is][in] */byte __RPC_FAR *bufIn,

/* [out] */ unsigned long __RPC_FAR *sizeOut,

/*[size_is][size_is][out] */ byte __RPC_FAR *__RPC_FAR *bufOut,

/* [retval][out] */enum EIAB_ErrorNum __RPC_FAR *errorNum);

boolUnpacking(

/* [in] */ unsigned long sizeIn,

/* [size_is][in] */byte __RPC_FAR *bufIn,

/* [out] */ unsigned long __RPC_FAR *sizeOut,

/*[size_is][size_is][out] */ byte __RPC_FAR *__RPC_FAR *bufOut,

/* [retval][out] */enum EIAB_ErrorNum __RPC_FAR *errorNum);


voidArcExcept(EIAB_ErrorNum errNum);


#endif//__ARCHIVERBASE_H_


ФайлArchiverBase.cpp.


#include"stdafx.h"

#include"ArchiverBase.h"

#include"zlib.h"

#include"ckg_str.h"

#include"com_mem.h"

#include"ckg_error_com.h"

#include"pdebug.h"


//-----------------------------------------------------------------------------

boolCrc32(

/* [in] */ unsigned long size,

/* [size_is][in] */byte __RPC_FAR *buf,

/* [retval][out] */unsigned long __RPC_FAR *crc)

{

try {

if (!size || !buf)

return false;


*crc = crc32(0L,buf, size);


return true;

}

catch(...)

{ }

return false;

}

//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------

boolCrc32Continue(

/* [in] */ unsigned long oldCrc,

/* [in] */ unsigned long size,

/* [size_is][in] */byte __RPC_FAR *buf,

/* [retval][out] */unsigned long __RPC_FAR *crc)

{

try {

if (!size || !buf)

return false;


*crc =crc32(oldCrc, buf, size);


return true;

}

catch(...)

{ }

return false;

}

//-----------------------------------------------------------------------------

boolPack(

/* [in] */ byte compressionLevel,

/* [in] */ unsigned long sizeIn,

/* [size_is][in] */byte __RPC_FAR *bufIn,

/* [out] */ unsigned long __RPC_FAR *sizeOut,

/*[size_is][size_is][out] */ byte __RPC_FAR *__RPC_FAR *bufOut,

/* [retval][out] */enum EIAB_ErrorNum __RPC_FAR *errorNum)

{

WriteToLog(_T("Pack()"));

try {

int level =compressionLevel;

if (level >Z_BEST_COMPRESSION)

level =Z_BEST_COMPRESSION;

else if (level ==0)

level =Z_DEFAULT_COMPRESSION;


*sizeOut = 0;

*bufOut = NULL;

if (!bufIn ||!sizeIn)

throwIAB_ERROR_BUF_SIZE;


unsigned titleSize= sizeof(TitleArcData);

unsignedassumedSizePackData = sizeIn + 12 +

unsigned(float(sizeIn)* 0.001f + 0.5f);

unsigned size =titleSize + assumedSizePackData;

pure_com_membuf((byte *)CoTaskMemAlloc(size));

if (!buf)

throwIAB_ERROR_ALLOCATE_MEMORY;


TitleArcData &title= *((TitleArcData *)buf.ptr());


title.signature =signature;

title.sizeUnpack =sizeIn;

title.crcUnpack =crc32(0L, bufIn, sizeIn);

title.titleSize =titleSize;


unsigned longretSize = assumedSizePackData;

if (compress2(buf +titleSize, &retSize, bufIn, sizeIn, level)

!= Z_OK)

throwIAB_UNKNOWN_ERROR;


title.isPacked =(retSize

if (title.isPacked)

size = titleSize+ retSize;

else

{

size = titleSize+ sizeIn;

memcpy(buf +titleSize, bufIn, sizeIn);

}


unsigned skip =TitleArcData::GetSizeSkeep();

title.crcPack =crc32(0L, buf + skip, size - skip);


*bufOut = (byte*)CoTaskMemRealloc(buf, size);

if (*bufOut)

buf.Detach();

else

throwIAB_ERROR_ALLOCATE_MEMORY;


*sizeOut = size;

*errorNum = IAB_OK;

return true;

}

catch(EIAB_ErrorNumnum)

{

*errorNum = num;

return false;

}

catch(...)

{

*errorNum =IAB_UNKNOWN_ERROR;

return false;

}

}

//-----------------------------------------------------------------------------

boolUnpacking(

/* [in] */ unsigned long sizeIn,

/* [size_is][in] */byte __RPC_FAR *bufIn,

/* [out] */ unsigned long __RPC_FAR *sizeOut,

/*[size_is][size_is][out] */ byte __RPC_FAR *__RPC_FAR *bufOut,

/* [retval][out] */enum EIAB_ErrorNum __RPC_FAR *errorNum)

{

WriteToLog(_T("Unpacking()"));

try {

*sizeOut = 0;

*bufOut = NULL;

if (!bufIn ||

sizeIn

//байт данных

throwIAB_ERROR_BUF_SIZE;


TitleArcData &title= *((TitleArcData *)bufIn);

if (title.signature!= signature)

throwIAB_THIS_IS_NOT_ARCHIVE;


unsigned skip =TitleArcData::GetSizeSkeep();

if (title.crcPack!= crc32(0L, bufIn + skip, sizeIn - skip))

throwIAB_CRC_ERROR;


skip =title.titleSize;

unsigned size =sizeIn - skip;


pure_com_membuf;

if(!title.isPacked)

{

buf = (byte*)CoTaskMemAlloc(size);

if (!buf)

throwIAB_ERROR_ALLOCATE_MEMORY;

memcpy(buf, bufIn+ skip, size);

}

else

{

buf = (byte*)CoTaskMemAlloc(title.sizeUnpack);

unsigned long len= title.sizeUnpack;

if(uncompress(buf, &len, bufIn + skip, size) != Z_OK)

throwIAB_UNKNOWN_ERROR;

}


if (title.crcUnpack!= crc32(0L, buf, title.sizeUnpack))

throwIAB_CRC_ERROR;


*errorNum = IAB_OK;

*sizeOut =title.sizeUnpack;

*bufOut =buf.Detach();

return true;

}

catch(EIAB_ErrorNumnum)

{

*errorNum = num;

return false;

}

catch(...)

{

*errorNum =IAB_UNKNOWN_ERROR;

return false;

}

}

//-----------------------------------------------------------------------------

voidArcExcept(EIAB_ErrorNum errNum)

{

WriteToLog(_T("Error:run ArcExcept()"));

if (errNum ==IAB_OK)

return;

DWORD id;

switch(errNum)

{

caseIAB_ERROR_BUF_SIZE: id = IDS_IABE_ERROR_BUF_SIZE; break;

caseIAB_ERROR_ALLOCATE_MEMORY: id = IDS_IABE_ERROR_ALLOCATE_MEMORY; break;

case IAB_CRC_ERROR: id = IDS_IABE_ERROR_CRC_ERROR; break;

caseIAB_THIS_IS_NOT_ARCHIVE: id =IDS_IABE_ERROR_THIS_IS_NOT_ARCHIVE;break;

default:

id= IDS_IABE_ERROR_UNKNOWN;

}

CkgExcept(id,EXTERNAL_COM_ERROR);

}

//-----------------------------------------------------------------------------


ФайлglobalDef.h.


#ifndef__GLOBAL_DEF_H_

#define__GLOBAL_DEF_H_


//Версиямодуля. Используетсяпри запросеинформации.

constshort moduleVersionInfo = 0x0110; // 1.10


#endif//__GLOBAL_DEF_H_


Файлprotect.h.


//protect.h : Declaration of the CProtect


#ifndef__PROTECT_H_

#define__PROTECT_H_


#include"resource.h" // main symbols

#include"cpp_ptr.h"

#include"ckg_array.h"

#include"ckg_buf.h"


enumE_FILE_OPEN_MODE

{

EF_READONLY,EF_READWRITE

};


classObjectFile

{

CreateMode fileMode;

FILE *f;

cpp_ptrbuffer;

E_FILE_OPEN_MODE mode;

CkgString uptFileNameForWrite;

CkgString uptFileNameForRead;

bool isOpened;

bool isClosed;


ObjectFile() :f(NULL), isOpened(false), isClosed(false) { };

void CryptBuf();

void DecryptBuf();

public:

static ObjectFile&Create(BSTR name, BSTR uptFileNameForWrite,

CreateModemode);

static ObjectFile&Open(BSTR name, BSTR uptFileNameForWrite,

BSTRuptFileNameForRead);

void Write(constvoid *buf, unsigned size);

void Read(void *buf,unsigned size);

void Seek(intposition, int mode);

unsignedGetPosition() const { return buffer->GetPosition(); }

void Close();

~ObjectFile();

};


/////////////////////////////////////////////////////////////////////////////

//CProtect

classATL_NO_VTABLE CProtect :

publicCComObjectRootEx,

publicCComCoClass,

publicISupportErrorInfo,

publicIDispatchImpl,

publicIDispatchImpl,

publicIDispatchImpl

// public IDispatchImpl

{

staticCkgArray files;

staticCkgSimpleContainerArray handles;


voidContinueOpen(ObjectFile &file, short &handle);

voidContinueGenerateTimeLimitUPTfiles(BSTR algorithmCryptFileName,

BSTRalgorithmDecryptFileName,

longLimitDaysCrypt,

longLimitDaysDecrypt);

HRESULTInternalGetAlgName(const CkgString &Strings,

CkgStringSearchName,

CkgString&Result);

HRESULTInternalGetDataName(const CkgString &Strings,

CkgStringSearchName,

CkgString&Result);

public:

CProtect()

{

}


DECLARE_REGISTRY_RESOURCEID(IDR_PROTECT)


DECLARE_PROTECT_FINAL_CONSTRUCT()


BEGIN_COM_MAP(CProtect)

COM_INTERFACE_ENTRY(IProtect)

//DEL COM_INTERFACE_ENTRY(IDispatch)

COM_INTERFACE_ENTRY(ISupportErrorInfo)

COM_INTERFACE_ENTRY2(IDispatch,IProtect)

COM_INTERFACE_ENTRY(IProtectFile)

COM_INTERFACE_ENTRY(IProtectConformity)

// COM_INTERFACE_ENTRY(IProtectBase)

END_COM_MAP()


//ISupportsErrorInfo

STDMETHOD(InterfaceSupportsErrorInfo)(REFIIDriid);


//IProtect

public:

STDMETHOD(GenerateTimeLimitUPTfiles2)(/*[in]*/BSTR algorithmCryptFileName, /*[in]*/ BSTR algorithmDecryptFileName,/*[in]*/ long LimitDaysCrypt, /*[in]*/ long LimitDaysDecrypt);

STDMETHOD(GenerateTimeLimitUPTfiles)(/*[in]*/BSTR algorithmCryptFileName, /*[in]*/ BSTR algorithmDecryptFileName,/*[in]*/ long LimitDays);

STDMETHOD(GenerateUPTfiles)(/*[in]*/BSTR algorithmCryptFileName, /*[in]*/ BSTR algorithmDecryptFileName);

STDMETHOD(GetInfo)(/*[out]*/short *version, /*[out]*/ BSTR *info);

//IProtectFile

STDMETHOD(Create)(/*[in]*/BSTR name, /*[in]*/ CreateMode mode, /*[in]*/ BSTR uptFileName,/*[out, retval]*/ short *handle);

STDMETHOD(Open)(/*[in]*/BSTR name, /*[in]*/ BSTR uptFileNameForRead, /*[in]*/ BSTRuptFileNameForWrite, /*[out, retval]*/ short *handle);

STDMETHOD(Write)(/*[in]*/short handle, /*[in]*/ VARIANT buffer, /*[out, retval]*/ long*written);

STDMETHOD(Read)(/*[in]*/short handle, /*[out]*/ VARIANT *buffer, /*[out, retval]*/ long*read);

STDMETHOD(Close)(/*[in]*/short handle);

STDMETHOD(WriteString)(/*[in]*/short handle, /*[in]*/ BSTR buffer, /*[out, retval]*/ long *written);

STDMETHOD(ReadString)(/*[in]*/short handle, /*[out]*/ BSTR *buffer, /*[out, retval]*/ long *read);

STDMETHOD(ToFile)(/*[in]*/short handle, /*[in]*/ BSTR FileName, /*[oit, retval]*/ long*written);

STDMETHOD(FromFile)(/*[in]*/short handle, /*[in]*/ BSTR FileName, /*[oit, retval]*/ long *read);

//IProtectConformity

STDMETHOD(CreateConformityFile)(/*[in]*/BSTR name, /*[in]*/ BSTR uptFileNameForRead, /*[in]*/ BSTRuptFileNameForWrite, /*[in]*/ BSTR ArrayOfStrings);

STDMETHOD(EasyCreateConformityFile)(/*[in]*/BSTR name, /*[in]*/ BSTR uptFileNameForCreate, /*[in]*/ BSTRArrayOfStrings);

STDMETHOD(ReadConformityFile)(/*[in]*/BSTR name, /*[in]*/ BSTR uptFileNameForRead, /*[out, retval]*/ BSTR*ArrayOfStrings);

STDMETHOD(GetAlgName)(/*[in]*/BSTR Strings, /*[in]*/ BSTR SearchName, /*[out, retval]*/ BSTR*ResultStr);

STDMETHOD(GetDataName)(/*[in]*/BSTR Strings, /*[in]*/ BSTR SearchName, /*[out, retval]*/ BSTR*ResultStr);

STDMETHOD(GetAlgFromFile)(/*[in]*/BSTR FileName, /*[in]*/ BSTR uptFileNameForRead, /*[in]*/ BSTRSearchName, /*[out, retval]*/ BSTR *ResultStr);

STDMETHOD(GetDataFromFile)(/*[in]*/BSTR FileName, /*[in]*/ BSTR uptFileNameForRead, /*[in]*/ BSTRSearchName, /*[out, retval]*/ BSTR *ResultStr);


//IProtectBase

};


#endif//__PROTECT_H_


Файлprotect.cpp.


//protect.cpp : Implementation of CProtect

#include"stdafx.h"

#include

#include

#include

#include"globalDef.h"

#include"c_ptr.h"

#include"cpp_ptr.h"

#include"ckg_str.h"

#include"ckg_error_com.h"

#include"com_mem.h"

#include"Uniprot.h"

#include"protect.h"

#include"polymorphism.h"

#include"ArchiverBase.h"

#include"pdebug.h"


//В VisaulBasicвсе равно большенельзя

conststatic unsigned maxDimDimensions = 60;


staticbool TestFilePresent(BSTR name, bool maybeUnnecessary = false)

{

WriteToLog(_T("TestFilePresent()"));

if (!name &&maybeUnnecessary)

return true;

if (!name)

return false;


USES_CONVERSION;

CkgStringstrName(W2T(name));

if(strName.IsEmpty() && maybeUnnecessary)

return true;

if(strName.IsEmpty())

return false;


FILE *f =_tfopen(strName, _T("rb"));

if (!f)

return false;

if (fclose(f))

CkgExcept(ERROR_CLOSE_FILE);

return true;

}


//=============================================================================

//classObjectFile

//-----------------------------------------------------------------------------

voidObjectFile::CryptBuf()

{

WriteToLog(_T("ObjectFile::CryptBuf()"));

bytecompressionLevel;

if (fileMode ==DISABLE_ARC)

compressionLevel =1; // min compression level

else

compressionLevel =0; // default

unsigned longsizeOut;

BYTE *bufOut;

EIAB_ErrorNum err;

if(!Pack(compressionLevel, buffer->GetSize(),

static_cast(buffer->GetBuf()), &sizeOut, &bufOut, &err))

ArcExcept(err);

_ASSERT(sizeOut &&bufOut);

pure_com_mempacket(bufOut);

buffer->Clear();

buffer->Write(&sizeOut,sizeof(unsigned));

buffer->Write(bufOut,sizeOut);


unsigned needAdd =static_cast(

(ROUND_SATA_SIZE -(sizeOut % ROUND_SATA_SIZE)) % ROUND_SATA_SIZE);

_ASSERT(needAdd !=ROUND_SATA_SIZE);


for (unsigned i = 0;i

{

int rnd =CoolRand();

Write(&rnd, 1);

}

_ASSERT((buffer->GetSize()- sizeof(unsigned)) % ROUND_SATA_SIZE == 0);


CryptData(*(static_cast(buffer->GetBuf()) + sizeof(unsigned)),

buffer->GetSize()- sizeof(unsigned),

*static_cast(uptFileNameForWrite));

}

//-----------------------------------------------------------------------------

voidObjectFile::DecryptBuf()

{

WriteToLog(_T("ObjectFile::DecryptBuf()"));

if(buffer->GetSize()

CkgExcept(ERROR_FILE_FORMAT);


unsigned packSize =*(static_cast(buffer->GetBuf()));

DecryptData(*(static_cast(buffer->GetBuf()) + sizeof(unsigned)),

buffer->GetSize()- sizeof(unsigned),

*static_cast(uptFileNameForRead));


unsigned longsizeOut;

BYTE *bufOut;

EIAB_ErrorNum err;

if(!Unpacking(packSize,

static_cast(buffer->GetBuf()) + sizeof(unsigned),

&sizeOut,&bufOut, &err))

ArcExcept(err);

_ASSERT(sizeOut &&bufOut);

pure_com_memunpacket(bufOut);

buffer->Clear();

buffer->Write(bufOut,sizeOut);

}

//-----------------------------------------------------------------------------

ObjectFile&ObjectFile::Create(BSTR name, BSTR uptFileNameForWrite,

CreateModemode)

{

WriteToLog(_T("ObjectFile::Create()"));

USES_CONVERSION;

if ((mode != DEFAULT&& mode != DISABLE_ARC) || !uptFileNameForWrite ||

!name)

CkgExcept(ERROR_INVALID_ARGUMENT);

CkgStringfileName(W2T(name));

if(fileName.IsEmpty())

CkgExcept(ERROR_OPEN_FILE);


if(!TestFilePresent(uptFileNameForWrite))

CkgExcept(_T("UPT-файлдля шифрованияфайла не найден."));


cpp_ptrobj(new ObjectFile);

TestPtr(obj);

obj->fileMode =mode;

obj->mode =EF_READWRITE;

obj->uptFileNameForWrite= W2T(uptFileNameForWrite);


obj->buffer =&CkgBuffer::Create(4096);


obj->f =_tfopen(fileName, _T("wb"));

if (!obj->f)

CkgExcept(ERROR_OPEN_FILE);

obj->isOpened =true;

return*obj.Detach();

}

//-----------------------------------------------------------------------------

ObjectFile&ObjectFile::Open(BSTR name, BSTR uptFileNameForWrite,

BSTRuptFileNameForRead)

{

WriteToLog(_T("ObjectFile::Open()"));

USES_CONVERSION;

if (!name)

CkgExcept(ERROR_INVALID_ARGUMENT);

CkgStringfileName(W2T(name));

if(fileName.IsEmpty())

CkgExcept(ERROR_OPEN_FILE);


if(!TestFilePresent(uptFileNameForWrite, true))

CkgExcept(_T("UPT-файлдля шифрованияфайла не найден."));

if(!TestFilePresent(uptFileNameForRead))

CkgExcept(_T("UPT-файлдля расшифровкифайла не найден."));


cpp_ptrobj(new ObjectFile);

TestPtr(obj);

if(uptFileNameForWrite)

obj->uptFileNameForWrite= W2T(uptFileNameForWrite);

if(uptFileNameForRead)

obj->uptFileNameForRead= W2T(uptFileNameForRead);


obj->mode =(!uptFileNameForWrite ||CkgString(obj->uptFileNameForWrite).IsEmpty()) ?

EF_READONLY: EF_READWRITE;


obj->f =_tfopen(fileName, _T("r+b"));

if (!obj->f)

CkgExcept(ERROR_OPEN_FILE);

if(fread(&obj->fileMode, sizeof(BYTE), sizeof(CreateMode),obj->f) != sizeof(CreateMode))

CkgExcept(ERROR_READ_FILE);

unsigned fileSize;

if (fread(&fileSize,sizeof(BYTE), sizeof(unsigned), obj->f) != sizeof(unsigned))

CkgExcept(ERROR_READ_FILE);


cpp_arr_ptrbuf(new BYTE[fileSize]);

TestPtr(buf);

if (fread(buf,sizeof(BYTE), fileSize, obj->f) != fileSize)

CkgExcept(ERROR_READ_FILE);


BYTE tmp;

if (fread(&tmp,sizeof(BYTE), 1, obj->f) == 1)

CkgExcept(ERROR_READ_FILE);


obj->buffer =&CkgBuffer::Create(4096);

obj->buffer->Write(buf,fileSize);

obj->DecryptBuf();

obj->buffer->LSeek(0);

obj->isOpened =true;

return*obj.Detach();

}

//-----------------------------------------------------------------------------

voidObjectFile::Write(const void *buf, unsigned size)

{

WriteToLog(_T("ObjectFile::Write()"));

if (mode ==EF_READONLY)

CkgExcept(_T("Файлоткрыт толькодля чтения."));

if(!size)

{

buffer->SetSize(buffer->GetPosition());

return;

}

buffer->Write(buf,size);

}

//-----------------------------------------------------------------------------

voidObjectFile::Read(void *buf, unsigned size)

{

_ASSERT(!isClosed);

unsigned position =buffer->GetPosition();

if(buffer->GetSize() - position

CkgExcept(ERROR_INVALID_ARGUMENT);

memcpy(buf,static_cast(buffer->GetBuf()) + position, size);

buffer->LSeek(position+ size);

}

//-----------------------------------------------------------------------------

voidObjectFile::Seek(int position, int mode)

{

WriteToLog(_T("ObjectFile::Seek()"));

_ASSERT(!isClosed);

if (mode ==SEEK_SET)

buffer->LSeek(position);

else if (mode ==SEEK_CUR)

buffer->LSeek(buffer->GetPosition()+ position);

else if (mode ==SEEK_END)

buffer->LSeek(buffer->GetSize()+ position);

else

CkgExcept(ERROR_INVALID_ARGUMENT);

}

//-----------------------------------------------------------------------------

voidObjectFile::Close()

{

WriteToLog(_T("ObjectFile::Close()"));

_ASSERT(!isClosed &&isOpened);

isClosed= true;// Даже если ине закроем(возникнетисключение),то больше

//пробовать всеравно толкунет

if(mode == EF_READWRITE)

{

if (fseek(f, 0,SEEK_SET))

CkgExcept(ERROR_WRITE_FILE);


if(fwrite(&fileMode, sizeof(BYTE), sizeof(CreateMode), f) !=sizeof(CreateMode))

CkgExcept(ERROR_WRITE_FILE);


CryptBuf();

unsigned dataSize =buffer->GetSize();

if(fwrite(&dataSize, sizeof(BYTE), sizeof(unsigned), f) !=sizeof(unsigned))

CkgExcept(ERROR_WRITE_FILE);

if(fwrite(buffer->GetBuf(), sizeof(BYTE),

dataSize, f) !=dataSize)

CkgExcept(ERROR_WRITE_FILE);

if (fwrite(0, 1, 0,f) != 0)

CkgExcept(ERROR_WRITE_FILE);

}

if (fclose(f))

CkgExcept(ERROR_CLOSE_FILE);

f = NULL;

buffer = 0;

}

//-----------------------------------------------------------------------------

ObjectFile::~ObjectFile()

{

WriteToLog(_T("ObjectFile::~ObjectFile()"));

_ASSERT(isClosed);

if (isOpened &&!isClosed)

Close();

if (f)

fclose(f);

}

//-----------------------------------------------------------------------------


/////////////////////////////////////////////////////////////////////////////

//CProtect

CkgArrayCProtect::files(true);

CkgSimpleContainerArrayCProtect::handles;


STDMETHODIMPCProtect::InterfaceSupportsErrorInfo(REFIID riid)

{

static constIID* arr[] =

{

&IID_IProtect

};

for (int i=0; i

{

if(InlineIsEqualGUID(*arr[i],riid))

returnS_OK;

}

return S_FALSE;

}


STDMETHODIMPCProtect::GetInfo(short *version, BSTR *info)

{

try

{

*version =moduleVersionInfo;

CComBSTR str;

str.LoadString(IDS_MODULE_INFO);

*info = str.Copy();

return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::GenerateUPTfiles(BSTR algorithmCryptFileName,

BSTRalgorithmDecryptFileName)

{

returnGenerateTimeLimitUPTfiles(algorithmCryptFileName,

algorithmDecryptFileName,

0);

}


voidCProtect::ContinueGenerateTimeLimitUPTfiles(

BSTRalgorithmCryptFileName, BSTR algorithmDecryptFileName,

longLimitDaysDecrypt, long LimitDaysCrypt)

{

if(LimitDaysDecrypt)

LimitDaysDecrypt +=GetCurrentDayNum();

if (LimitDaysCrypt)

LimitDaysCrypt +=GetCurrentDayNum();


USES_CONVERSION;

if(!algorithmCryptFileName || !algorithmDecryptFileName)

CkgExcept(_T("Строкас именем upt-файлапустая."));

LPCTSTRfileNameCrypt(W2T(algorithmCryptFileName));

LPCTSTRfileNameDecrypt(W2T(algorithmDecryptFileName));

if(!_tcslen(fileNameCrypt) || !_tcslen(fileNameDecrypt))

CkgExcept(_T("Строкас именем upt-файлапустая."));


GenerateAlgorithm(*fileNameCrypt,*fileNameDecrypt,

static_cast(LimitDaysDecrypt),

static_cast(LimitDaysCrypt));

}


STDMETHODIMPCProtect::GenerateTimeLimitUPTfiles(BSTR algorithmCryptFileName,

BSTRalgorithmDecryptFileName,

longLimitDays)

{

WriteToLog(_T("CProtect::GenerateTimeLimitUPTfiles()"));

try

{

ContinueGenerateTimeLimitUPTfiles(algorithmCryptFileName,

algorithmDecryptFileName,

LimitDays,LimitDays);

return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

return S_OK;

}


STDMETHODIMPCProtect::GenerateTimeLimitUPTfiles2(BSTR algorithmCryptFileName,

BSTRalgorithmDecryptFileName, long LimitDaysDecrypt,

long LimitDaysCrypt)

{

WriteToLog(_T("CProtect::GenerateTimeLimitUPTfiles2()"));

try

{

ContinueGenerateTimeLimitUPTfiles(algorithmCryptFileName,

algorithmDecryptFileName,

LimitDaysCrypt,LimitDaysDecrypt);

return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

return S_OK;

}


voidCProtect::ContinueOpen(ObjectFile &file, short &handle)

{

files.Add(file);


short i;

for (i = 1; i

{

if(handles.IndexOf(i) == -1)

{

handle = i;

handles.Add(i);

break;

}

}

if (i == SHRT_MAX)

CkgExcept(_T("Нетбольше свободныхдескипторов."));

_ASSERT(handle);

}


STDMETHODIMPCProtect::Create(BSTR name, CreateMode mode, BSTR uptFileName, short*handle)

{

WriteToLog(_T("CProtect::Create()"));

try

{

_ASSERT(handle);

ContinueOpen(ObjectFile::Create(name,uptFileName, mode),

*handle);

return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::Open(BSTR name, BSTR uptFileNameForRead,

BSTRuptFileNameForWrite, short *handle)

{

WriteToLog(_T("CProtect::Open()"));

try

{

_ASSERT(handle);

ContinueOpen(ObjectFile::Open(name,uptFileNameForWrite,

uptFileNameForRead),*handle);

return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::Close(short handle)

{

WriteToLog(_T("CProtect::Close()"));

try

{

int index =handles.IndexOf(handle);

if (index == -1)

CkgExcept(_T("Ошибказакрытия файла.(Неверныйдескриптор.)"));


handles.Remove(index);

files[index].Close();

files.Remove(index,true);


return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


template

voidWriteVariable(ObjectFile &file, const T &var, VARTYPEvarType)

{

file.Write(&varType,sizeof(VARTYPE));

file.Write(&var,sizeof(T));

}


STDMETHODIMPCProtect::Write(short handle, VARIANT buffer, long *written)

{

WriteToLog(_T("CProtect::Write()"));

try

{

int index =handles.IndexOf(handle);

if(index== -1)

CkgExcept(_T("Ошибказаписи в файл.(Неверныйдескриптор.)"));


VARTYPEvt = buffer.vt;

ObjectFile &file= files[index];

unsigned oldSize =file.GetPosition();


if (!(vt &VT_BYREF) && !(vt & VT_ARRAY))

{

if (vt == VT_UI1)

WriteVariable(file,buffer.bVal, VT_UI1);

else if (vt ==VT_I2)

WriteVariable(file,buffer.iVal, VT_I2);

else if (vt ==VT_I4)

WriteVariable(file,buffer.lVal, VT_I4);

else if (vt ==VT_R4)

WriteVariable(file,buffer.fltVal, VT_R4);

else if (vt ==VT_R8)

WriteVariable(file,buffer.dblVal, VT_R8);

else if (vt ==VT_BOOL)

WriteVariable(file,buffer.boolVal, VT_BOOL);

else if (vt ==VT_ERROR)

WriteVariable(file,buffer.scode, VT_ERROR);

else if (vt ==VT_CY)

WriteVariable(file,buffer.cyVal, VT_CY);

else if (vt ==VT_DATE)

WriteVariable(file,buffer.date, VT_DATE);

else if (vt ==VT_I1)

WriteVariable(file,buffer.cVal, VT_I1);

else if (vt ==VT_UI2)

WriteVariable(file,buffer.uiVal, VT_UI2);

else if (vt ==VT_UI4)

WriteVariable(file,buffer.ulVal, VT_UI4);

else if (vt ==VT_INT)

WriteVariable(file,buffer.intVal, VT_INT);

else if (vt ==VT_UINT)

WriteVariable(file,buffer.uintVal, VT_UINT);

else if (vt ==VT_BSTR)

{

file.Write(&vt,sizeof(VARTYPE));

CComBSTRstr(buffer.bstrVal);

unsigned len =str.Length();

file.Write(&len,sizeof(unsigned));

file.Write(static_cast(str),len * sizeof(OLECHAR));

}

else

CkgExcept(_T("Ошибказаписи в файл.(VARIANTданного типане поддерживается)"));

}

else if (vt &VT_ARRAY)

{

if (vt &VT_BSTR)

CkgExcept(ERROR_INVALID_ARGUMENT);


SAFEARRAY&safeArray = *buffer.parray;

if(safeArray.fFeatures == FADF_RECORD ||

safeArray.fFeatures== FADF_HAVEIID ||

safeArray.fFeatures== FADF_BSTR ||

safeArray.fFeatures== FADF_UNKNOWN ||

safeArray.fFeatures== FADF_DISPATCH ||

safeArray.fFeatures== FADF_VARIANT ||

safeArray.cDims> maxDimDimensions)

CkgExcept(_T("Ошибказаписи в файл.(VARIANTс массивомданного типане поддерживается)"));


file.Write(&vt,sizeof(VARTYPE));

file.Write(&safeArray.cDims,sizeof(safeArray.cDims));

file.Write(&safeArray.cbElements,sizeof(safeArray.cbElements));

file.Write(&safeArray.fFeatures,sizeof(safeArray.fFeatures));


constSAFEARRAYBOUND *bound = safeArray.rgsabound;

unsigned size =0;

for (unsigned i =0; i

{

const long&Lbound = bound[i].lLbound;

const unsigned&cElements = bound[i].cElements;

file.Write(&Lbound,sizeof(Lbound));

file.Write(&cElements,sizeof(cElements));

if (!cElements)

CkgExcept(ERROR_INVALID_ARGUMENT);

size +=cElements;

}

if (size == 0)

CkgExcept(ERROR_INVALID_ARGUMENT);


size *=safeArray.cbElements;

file.Write(safeArray.pvData,size);

}

else

CkgExcept(_T("Ошибказаписи в файл.(VARIANTданного типане поддерживается)"));


_ASSERT(file.GetPosition()- oldSize);

*written =file.GetPosition() - oldSize;

return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::WriteString(short handle, BSTR buffer, long *written)

{

WriteToLog(_T("CProtect::WriteString()"));

try

{

int index =handles.IndexOf(handle);

if(index== -1)

CkgExcept(_T("Ошибказаписи в файл.(Неверныйдескриптор.)"));


ObjectFile&file = files[index];

unsigned oldSize =file.GetPosition();


CComBSTRstr(buffer);

unsigned len =str.Length();

file.Write(&len,sizeof(unsigned));

file.Write(buffer,len * sizeof(OLECHAR));


_ASSERT(file.GetPosition()- oldSize);

*written =file.GetPosition() - oldSize;

return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


template

TReadVariable(ObjectFile &file)

{

T tmp;

file.Read(&tmp,sizeof(T));

return tmp;

}


STDMETHODIMPCProtect::Read(short handle, VARIANT *buffer, long *read)

{

WriteToLog(_T("CProtect::Read()"));

try

{

int index =handles.IndexOf(handle);

if(index== -1)

CkgExcept(_T("Ошибкачтения из файла.(Неверныйдескриптор.)"));


ObjectFile&file = files[index];

unsigned oldSize =file.GetPosition();


CComVariant var;

VARTYPE vt = 0;

file.Read(&vt,sizeof(vt));

if (!(vt &VT_BYREF) && !(vt & VT_ARRAY))

{

if (vt == VT_UI1)

var =ReadVariable(file);

else if (vt ==VT_I2)

var =ReadVariable(file);

else if (vt ==VT_I4)

var =ReadVariable(file);

else if (vt ==VT_R4)

var =ReadVariable(file);

else if (vt ==VT_R8)

var =ReadVariable(file);

else if (vt ==VT_BOOL)

var =ReadVariable(file);

else if (vt ==VT_ERROR)

var =ReadVariable(file);

else if (vt ==VT_CY)

var =ReadVariable(file);

else if (vt ==VT_DATE)

var =ReadVariable(file);

else if (vt ==VT_I1)

var =ReadVariable(file);

else if (vt ==VT_UI2)

var =ReadVariable(file);

else if (vt ==VT_UI4)

var =ReadVariable(file);

else if (vt ==VT_INT)

var =ReadVariable(file);

else if (vt ==VT_UINT)

var =ReadVariable(file);

else if (vt ==VT_BSTR)

{

unsignedlen = 0;

file.Read(&len,sizeof(len));

CComBSTRstr(len);

file.Read(static_cast(str),len * sizeof(OLECHAR));

var = str;

}

else

CkgExcept(_T("Ошибкачтения из файла.(Возможнофайл поврежденили имеетнесовместимыйформат)"));

*buffer= var;

}

else if (vt &VT_ARRAY)

{

CComVariant tmp;

memset(&tmp,0, sizeof(tmp));

VariantInit(&tmp);

tmp.vt = vt;

struct {

SAFEARRAYsafeArray;

SAFEARRAYBOUNDbuf[maxDimDimensions];

} trueSafeArr;

SAFEARRAY&safeArray = trueSafeArr.safeArray;

memset(&safeArray,0, sizeof(safeArray));

tmp.parray =&safeArray;


file.Read(&safeArray.cDims,sizeof(safeArray.cDims));

file.Read(&safeArray.cbElements,sizeof(safeArray.cbElements));

file.Read(&safeArray.fFeatures,sizeof(safeArray.fFeatures));

_ASSERT(safeArray.cDims&& safeArray.cbElements);


unsigned size =0;

_ASSERT(safeArray.cDims

for (unsigned i =0; i

{

long &Lbound= safeArray.rgsabound[i].lLbound;

ULONG&cElements = safeArray.rgsabound[i].cElements;

file.Read(&Lbound,sizeof(Lbound));

file.Read(&cElements,sizeof(cElements));

size +=cElements;

}


size *=safeArray.cbElements;

if(!size)

CkgExcept(_T("Ошибкачтения из файла.(Возможно файлповрежден илиимеет несовместимыйформат)"));

cpp_arr_ptrdata(new BYTE[size]);

TestPtr(data);

file.Read(data,size);

safeArray.pvData= data;

HRESULT hr =var.Copy(&tmp);

if(FAILED(hr))

CkgExceptHresult(hr);

if(FAILED(var.Detach(buffer)))

CkgExcept();

}

else

CkgExcept(_T("Ошибкачтения из файла.(Возможнофайл поврежденили имеетнесовместимыйформат)"));


_ASSERT(file.GetPosition()- oldSize);

*read =file.GetPosition() - oldSize;

return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::ReadString(short handle, BSTR *buffer, long *read)

{

WriteToLog(_T("CProtect::ReadString()"));

try

{

int index =handles.IndexOf(handle);

if(index== -1)

CkgExcept(_T("Ошибкачтения из файла.(Неверныйдескриптор.)"));


ObjectFile&file = files[index];

unsigned oldSize =file.GetPosition();


unsigned len = 0;

file.Read(&len,sizeof(len));

CComBSTR str(len);

file.Read(static_cast(str),len * sizeof(OLECHAR));

*buffer =str.Copy();


_ASSERT(file.GetPosition()- oldSize);

*read =file.GetPosition() - oldSize;

return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::CreateConformityFile(BSTR name, BSTR uptFileNameForRead,

BSTRuptFileNameForWrite,

BSTRArrayOfStrings)

{

WriteToLog(_T("CProtect::Create()"));

try

{

HRESULT Result;

Result =GenerateUPTfiles(uptFileNameForWrite, uptFileNameForRead);

if (FAILED(Result))

return Result;

short handle;

Result =Create(name, DEFAULT, uptFileNameForWrite, &handle);

if (FAILED(Result))

return Result;

long tmp;

Result =WriteString(handle, ArrayOfStrings, &tmp);

Close(handle);

returnResult;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::EasyCreateConformityFile(BSTR name, BSTRuptFileNameForCreate,

BSTRArrayOfStrings)

{

WriteToLog(_T("CProtect::EasyCreate()"));

try

{

HRESULT Result;

short handle;

Result =Create(name, DEFAULT, uptFileNameForCreate, &handle);

if (FAILED(Result))

return Result;

long tmp;

Result =WriteString(handle, ArrayOfStrings, &tmp);

Close(handle);

returnResult;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::ReadConformityFile(BSTR name, BSTR uptFileNameForRead,

BSTR*ArrayOfStrings)

{

WriteToLog(_T("CProtect::Read()"));

try

{

HRESULT Result;

short handle;

Result = Open(name,uptFileNameForRead, NULL, &handle);

if (FAILED(Result))

return Result;

long tmp;

Result =ReadString(handle, ArrayOfStrings, &tmp);

Close(handle);

returnResult;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


HRESULTCProtect::InternalGetAlgName(const CkgString &Strings,

CkgStringSearchName,

CkgString&Result)

{

if(Strings.IsEmpty() || SearchName.IsEmpty())

CkgExcept(ERROR_INVALID_ARGUMENT);


if (SearchName[0u]!= CkgText('"'))

{

SearchName.Insert(CkgText('"'),0);

SearchName =SearchName + CkgText('"');

}


Result =CkgText("");


const CkgChar *p =CkgStrStr(Strings, SearchName);

if (!p)

return S_FALSE;


p +=SearchName.GetLength();

const CkgChar *Start= CkgStrChr(p, CkgText('"'));

if (!Start)

return S_FALSE;

Start++;

const CkgChar *End =CkgStrChr(Start, CkgText('"'));

return S_FALSE;

CkgString tmp(Start,End - Start);

Result = tmp;

return S_OK;

}


HRESULTCProtect::InternalGetDataName(const CkgString &Strings,

CkgStringSearchName,

CkgString&Result)

{

if(Strings.IsEmpty() || SearchName.IsEmpty())

CkgExcept(ERROR_INVALID_ARGUMENT);


if (SearchName[0u]!= CkgText('"'))

{

SearchName.Insert(CkgText('"'),0);

SearchName =SearchName + CkgText('"');

}


const CkgChar *p =CkgStrStr(Strings, SearchName);

if (!p)

{

Result =CkgText("");

return S_FALSE;

}


unsigned Len = p -Strings;

if (!Len)

CkgExcept(ERROR_INVALID_DATA);

p--;

const CkgChar *End =CkgStrChrBk(p, CkgText('"'), Strings);

if (!End)

CkgExcept(ERROR_INVALID_DATA);

End--;

const CkgChar *Start= CkgStrChrBk(End, CkgText('"'), Strings);

if (!Start)

CkgExcept(ERROR_INVALID_DATA);

Start++;

CkgString tmp(Start,End - Start + 1);

Result = tmp;

return S_OK;

}


STDMETHODIMPCProtect::GetAlgName(BSTR Strings, BSTR SearchName,

BSTR*ResultStr)

{

WriteToLog(_T("CProtect::GetAlgName()"));

try

{

USES_CONVERSION;

CkgStringBuf(W2T(Strings));

CkgStringName(W2T(SearchName));

CkgString Result;


Buf.MakeLower();

Name.MakeLower();

HRESULT Res =InternalGetAlgName(Buf, Name, Result);


CComBSTR bstr;

bstr = T2W(Result);

*ResultStr =bstr.Copy();

return Res;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::GetDataName(BSTR Strings, BSTR SearchName, BSTR *ResultStr)

{

WriteToLog(_T("CProtect::GetDataName()"));

try

{

USES_CONVERSION;

CkgStringBuf(W2T(Strings));

CkgStringName(W2T(SearchName));

CkgString Result;


Buf.MakeLower();

Name.MakeLower();

HRESULT Res =InternalGetDataName(Buf, Name, Result);


CComBSTR bstr;

bstr = T2W(Result);

*ResultStr =bstr.Copy();

return Res;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::GetAlgFromFile(BSTR FileName, BSTR uptFileNameForRead,

BSTRSearchName, BSTR *ResultStr)

{

WriteToLog(_T("CProtect::GetAlgFromFile()"));

try

{

HRESULT Result;

CComBSTR SmartPtr;

BSTR ArrayOfString;

Result =ReadConformityFile(FileName, uptFileNameForRead, &ArrayOfString);

if (FAILED(Result))

return Result;

SmartPtr.Attach(ArrayOfString);

returnGetAlgName(SmartPtr, SearchName, ResultStr);

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::GetDataFromFile(BSTR FileName, BSTR uptFileNameForRead,/*[in]*/ BSTR SearchName, BSTR *ResultStr)

{

WriteToLog(_T("CProtect::GetDataFromFile()"));

try

{

HRESULT Result;

CComBSTR SmartPtr;

BSTR ArrayOfString;

Result =ReadConformityFile(FileName, uptFileNameForRead, &ArrayOfString);

if (FAILED(Result))

return Result;

SmartPtr.Attach(ArrayOfString);

returnGetDataName(SmartPtr, SearchName, ResultStr);

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::FromFile(short handle, BSTR FileName, long *read)

{

WriteToLog(_T("CProtect::FromFile()"));

try

{

intindex = handles.IndexOf(handle);

if(index== -1)

CkgExcept(_T("Ошибказаписи в файл.(Неверныйдескриптор.)"));

ObjectFile&file = files[index];


USES_CONVERSION;

CkgStringName(W2T(FileName));


DWORDLen;

FILE *f= _tfopen(Name, _T("rb"));

if(!f)

CkgExcept(ERROR_OPEN_FILE);

if (fseek(f, 0,SEEK_END))

CkgExcept(ERROR_READ_FILE);

Len =ftell(f);

if (fseek(f, 0,SEEK_SET))

CkgExcept(ERROR_READ_FILE);

pure_c_ptrBuf((char *)malloc(Len));

TestPtr(Buf);

if(fread(Buf, sizeof(char), Len, f) != Len)

CkgExcept(ERROR_READ_FILE);

fclose(f);


file.Write(&Len,sizeof(Len));

file.Write(Buf,Len);

*read =Len + sizeof(Buf);


returnS_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMPCProtect::ToFile(short handle, BSTR FileName, long *written)

{

WriteToLog(_T("CProtect::ToFile()"));

try

{

intindex = handles.IndexOf(handle);

if(index== -1)

CkgExcept(_T("Ошибказаписи в файл.(Неверныйдескриптор.)"));

ObjectFile&file = files[index];


DWORDLen;

file.Read(&Len,sizeof(Len));

pure_c_ptrBuf((char *)malloc(Len));

TestPtr(Buf);

file.Read(Buf,Len);


USES_CONVERSION;

CkgStringName(W2T(FileName));

FILE *f= _tfopen(Name, _T("wb"));

if (!f)

CkgExcept(ERROR_CREATE_FILE);

if(fwrite(Buf, sizeof(char), Len, f) != Len)

CkgExcept(ERROR_WRITE_FILE);

fclose(f);

*written= Len + sizeof(Buf);


returnS_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


ФайлUniprot.idl.


//Uniprot.idl : IDL source for Uniprot.dll

//


//This file will be processed by the MIDL tool to

//produce the type library (Uniprot.tlb) and marshalling code.


import"oaidl.idl";

import"ocidl.idl";


typedef

[uuid(60B14ABC-035B-43f4-B1D0-B2A29A1BC02C),v1_enum]

enumCreateMode

{

DEFAULT = 0,

DISABLE_ARC = 1

}CreateMode;


[

object,

uuid(0BF8C246-389C-42FF-845F-198C5550BCED),

dual,oleautomation,

helpstring("IProtectInterface"),

pointer_default(unique)

]

interfaceIProtect : IDispatch

{

[id(1),helpstring("method GetInfo")] HRESULT GetInfo([out] short*version, [out] BSTR *info);

[id(2),helpstring("method Generate UPT files")] HRESULTGenerateUPTfiles([in] BSTR algorithmCryptFileName, [in] BSTRalgorithmDecryptFileName);

[id(3),helpstring("method Generate Time Limit UPT files")] HRESULTGenerateTimeLimitUPTfiles([in] BSTR algorithmCryptFileName, [in] BSTRalgorithmDecryptFileName, [in] long LimitDays);

[id(4),helpstring("method Generate Time Limit UPT files")] HRESULTGenerateTimeLimitUPTfiles2([in] BSTR algorithmCryptFileName, [in]BSTR algorithmDecryptFileName, [in] long LimitDaysCrypt, [in] longLimitDaysDecrypt);

};


[

object,

uuid(1F3ADD8E-45DE-44e7-8953-CD7CC302154A),

dual,oleautomation,

helpstring("IProtectFileInterface"),

pointer_default(unique)

]

interfaceIProtectFile : 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] BSTRname, [in] BSTR uptFileNameForRead, [in] BSTR uptFileNameForWrite,[out, retval] short *handle);

[id(3),helpstring("method Close File")] HRESULT Close([in] shorthandle);

[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")] HRESULTWriteString([in] short handle, [in] BSTR buffer, [out, retval] long*written);

[id(7),helpstring("method Read String From File")] HRESULTReadString([in] short handle, [out] BSTR *buffer, [out, retval] long*read);

[id(8),helpstring("method From File")] HRESULT FromFile([in] shorthandle, [in] BSTR FileName, [out, retval] long *read);

[id(9),helpstring("method To File")] HRESULT ToFile([in] shorthandle, [in] BSTR FileName, [out, retval] long *written);

};


[

object,

uuid(FEB052E7-05D5-4a38-A40B-D5895DE69F87),

dual,oleautomation,

helpstring("IProtectConformityInterface"),

pointer_default(unique)

]

interfaceIProtectConformity : IDispatch

{

[id(1),helpstring("method Create Conformity File")] HRESULTCreateConformityFile([in] BSTR name, [in] BSTR uptFileNameForRead,[in] BSTR uptFileNameForWrite, [in] BSTR ArrayOfStrings);

[id(2),helpstring("method Easy Create Conformity File")] HRESULTEasyCreateConformityFile([in] BSTR name, [in] BSTRuptFileNameForCreate, [in] BSTR ArrayOfStrings);

[id(3),helpstring("method Read Conformity File")] HRESULTReadConformityFile([in] BSTR name, [in] BSTR uptFileNameForRead,[out, retval] BSTR *ArrayOfStrings);

[id(4),helpstring("method Get UptAlgName by FileName")] HRESULTGetAlgName([in] BSTR Strings, [in] BSTR SearchName, [out, retval]BSTR *ResultStr);

[id(5),helpstring("method Get FileName by UptAlgName")] HRESULTGetDataName([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] BSTRuptFileNameForRead, [in] BSTR SearchName, [out, retval] BSTR*ResultStr);

[id(7),helpstring("method Get FileName by UptAlgName From File")]HRESULT GetDataFromFile([in] BSTR FileName, [in] BSTRuptFileNameForRead, [in] BSTR SearchName, [out, retval] BSTR*ResultStr);

};


/*

[

object,

uuid(15A99543-9A8F-4032-B61F-8EDF01101A93),

dual,oleautomation,

helpstring("IProtectBaseInterface"),

pointer_default(unique)

]

interfaceIProtectBase : IDispatch

{

};

*/

[

uuid(8B9F6840-7A50-4A94-AC80-B2C85F3C469C),

version(1.0),

helpstring("Uniprot1.0 Type Library")

]


libraryUNIPROTLib

{

importlib("stdole32.tlb");

importlib("stdole2.tlb");


[

uuid(75581251-6B01-4164-850D-CD6A93D860BB),

helpstring("protectClass")

]

coclass protect

{

[default]interface IProtect;

interfaceIProtectFile;

interfaceIProtectConformity;

};

};


МинистерствообразованияРоссийскойФедерации

Тульскийгосударственныйуниверситет

Кафедраавтоматикии телемеханики


магистерская диссертация


направление553000

Системныйанализ и управление


ЗАЩИТАИНФОРМАЦИИВ СИСТЕМАХДИСТАНЦИОННОГООБУЧЕНИЯ СМОНОПОЛЬНЫМДОСТУПОМ


Студентгруппы 240681/05

__________________

А.Н.Карпов

Научныйруководитель

__________________

д.т.н.,проф. М.Ю.Богатырев

Консультанты

__________________

к.т.н.,проф. Г.Н. Теличко

Руководитель

магистерскойпрограммы


__________________



д.т.н.,проф. А.А. Фомичев

Заведующийкафедрой

__________________

д.т.н.,проф. А.А. Фомичев

Тула,2004

МинистерствообразованияРоссийскойФедерации

Тульскийгосударственныйуниверситет

Кафедраавтоматикии телемеханики


магистерская диссертация


направление553000

Системныйанализ и управление


Приложение

Исходныетексты библиотекиUniprot


Студентгруппы 240681/05

__________________

А.Н.Карпов

Научныйруководитель

__________________

д.т.н.,проф. М.Ю.Богатырев

Консультанты

__________________

к.т.н.,проф. Г.Н. Теличко

Руководитель

магистерскойпрограммы


__________________



д.т.н.,проф. А.А. Фомичев

Заведующийкафедрой

__________________

д.т.н.,проф. А.А. Фомичев

Тула,2004

МИНИСТЕРСТВООБРАЗОВАНИЯРОССИЙСКОЙФЕДЕРАЦИИ


ТУЛЬСКИЙГОСУДАРСТВЕННЫЙУНИВЕРСИТЕТ


Кафедраавтоматикии телемеханики


УТВЕРЖДАЮ

Зав.кафедрой ___________А.А. Фомичев

«__»_____________200г.


Задание

навыполнениемагистерскойдиссертации


понаправлению553000 Системныйанализ и управление

магистерскойпрограмме553005Системныйанализ данныхи модели принятиярешений


студентуКарповуА. Н. группы240681


  1. Темадиссертации"Защитаинформациив системахдистанционногообучения смонопольнымдоступом"

утвержденаприказом поуниверситетуот «23» января2004 г. № 64ст


  1. Сроксдачи студентомзаконченнойдиссертации«___» июня 2004 г.


  1. Переченьвопросов, подлежащихразработкеи исследованиюв диссертации:

1) Созданиезащиты дляпрограммныхпакетов, напримере системыдистанционногообучения.________________________________________

2)Предлагаемыеметоды созданияинтегрируемойсистемы защитыинформации____________________________________________________

3) Реализациясистемызащиты.____________________________________

4) Применениесистемызащиты____________________________________


4. Переченьграфическогоматериала:

1) Общийпринцип работыполиморфныхалгоритмовшифрованияирасшифрования._________________________________________________

2) Расположениефункциональныхблоков полиморфногоалгоритма.____

3) Алгоритмгенерацииполиморфныхкодов

._________________________

4) АСДОпостроеннаяпо принципуКлиент-сервер.___________________

5) АСДОиспользуемаяв монопольномрежиме.______________________

6) Примерзащиты данныхпри обменемежду автоматизированнымрабочим местом(АРМ) студентаи преподавателя.____________________

Всего6 листов


Консультациипо разделам

Наименованиераздела

Подпись

Фамилия

Вопросызащиты информации,стоящие передавтоматизированнымисистемамидистанционногообучения


_________________


Г.Н.Теличко


Датавыдачи задания«2» февраля2004 г.

Научныйруководитель_____________


Заданиепринял к исполнению


«2»февраля 2004 г.студент ____________ А.Н.Карпов