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

Защита информации в системах дистанционного обучения с монопольным доступом
Вопросы защиты информации, стоящие перед автоматизированными системами дистанционного обучения Возможность модификации программного кода системы тестирования с целью изменения алгоритма выставления оценок Возможность модификации программного кода системы тестирования, с целью изменения алгоритма выставления оценок или другого кода Выводы Шифрование данных Асимметричные криптосистемы Адаптированный метод асимметричного шифрования Функциональность системы защиты Краткая характеристика среды Visual C++ Общие принципы работы полиморфных алгоритмов шифрования и расшифрования Виртуальная машина для выполнения полиморфных алгоритмов Генератор полиморфного кода Таблицы блоков для генерации полиморфного кода Особенности реализации модуля защиты Руководство программиста по использованию модуля Uniprot.dll Руководство программиста по использованию программы ProtectEXE.exe Подключение модуля защиты к программе на языке Visual Basic Пример использования программы ProtectEXE.exe Виртуальная память, используемая в алгоритме, заполняется случайными значения
284992
знака
7
таблиц
0
изображений

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

Далее в главе описано использования системы защиты на примерах. Так например рассмотрено подключение модуля защиты к программе на языке Visual C++ и Visual Basic. Приведен пример использования модуля защиты в программе на языке Visual Basiс, Пример использования программы ProtectEXE.exe.

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

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

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


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


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

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

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

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


СПИСОК ОСНОВНЫХ ПУБЛИКАЦИЙ ПО ТЕМЕ ДИССЕРТАЦИИ


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


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


ђ §¤Ґ«: Їа®Ја ¬¬Ёа®ў ­ЁҐ
”?Ћ: Љ аЇ®ў Ђ­¤аҐ© ЌЁЄ®« ҐўЁз
forsp@list.ru
‡ йЁв Ё­д®а¬ жЁЁ ў бЁб⥬ е ¤Ёбв ­жЁ®­­®Ј® ®Ўг祭Ёп б ¬®­®Ї®«м­л¬ ¤®бвгЇ®¬
„ЁЇ«®¬

168



Часть исходных текстов вспомогательного характера опущена. В качестве примера можно привести класс com_ptr, представляющий вспомогательный класс для более удобной работы с COM интерфейсом. Также полностью опущены исходные тектсыт свободно распрострняемой библиотеки ZLIB 1.1.2.


Файл blocks.h.


#ifndef __BLOCKS_H__

#define __BLOCKS_H__


#ifndef CALC_ARRAY_SIZE

#define CALC_ARRAY_SIZE(arr) ((int) (sizeof arr / sizeof arr[0]))

#endif


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

#define BLOCK_END(num) }; const size_t sizeBlock_##num = CALC_ARRAY_SIZE(block_##num);


#define BLOCKS_START(num) const static int * const blocks_##num [] = {

#define BLOCKS_END(num) }; const size_t sizeBlocksArray_##num = CALC_ARRAY_SIZE(blocks_##num);

#define BLOCK(num) static_cast(block_##num),


#define BLOCKS_SIZE_START(num) const static unsigned sizeBlocks_##num [] = {

#define BLOCK_SIZE(num) sizeBlock_##num,

#define BLOCKS_SIZE_END(num) };


// Абстрактный алгоритм

// [ADDR(REG|VAR) "), false);

int result = 0; // anti warning

if (operation == EO_XOR)

result = value1 ^ value2;

else if (operation == EO_AND)

result = value1 & value2;

else if (operation == EO_OR)

result = value1 | value2;

else if (operation == EO_ADD)

result = value1 + value2;

else if (operation == EO_SUB)

result = value1 - value2;

else if (operation == EO_MUL)

result = value1 * value2;

else if (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:

{

const int *oldP = p;

#ifdef WRITE_LOG

if (operation == EO_NOT)

WriteToLog(_T("not "), false);

else if (operation == EO_NEG)

WriteToLog(_T("neg "), false);

else if (operation == EO_INC)

WriteToLog(_T("inc "), false);

else if (operation == EO_DEC)

WriteToLog(_T("dec "), false);

#endif

int value = GetValue(p, *vars, *regs, *data);

if (operation == EO_NOT)

value = 0 ^ value;

else if (operation == EO_NEG)

value = -value;

else if (operation == EO_INC)

value++;

else if (operation == EO_DEC)

value--;

else

CkgExcept();

WriteToLog(" ==> ", false);

SetValue(oldP, *vars, *regs, *data, value);

WriteToLog("");

break;

}

case EO_CMP:

case EO_TEST:

{

#ifdef WRITE_LOG

if (operation == EO_CMP)

WriteToLog(_T("cmp "), false);

else if (operation == EO_TEST)

WriteToLog(_T("test "), false);

#endif

int value1 = GetValue(p, *vars, *regs, *data);

int value2 = GetValue(p, *vars, *regs, *data);

WriteToLog("");

flags = 0;

if (operation == EO_CMP)

{

flags = ((value1 == value2) * EF_ZERO) |

((value1 < value2) * EF_ABOVE);

}

else if (operation == EO_TEST)

{

flags = (((value1 & value2) == 0) * EF_ZERO);

}

else

CkgExcept();

break;

}

case EO_JMP: {

WriteToLog(_T("jmp "), false);

int addr = GetValue(p, *vars, *regs, *data);

WriteToLog("\r\n");

p = (&operations) + addr;

break;

}

case EO_CALL: {

WriteToLog(_T("call "), false);

int addr = GetValue(p, *vars, *regs, *data);

WriteToLog("\r\n");

stack.Add(p - (&operations));

p = (&operations) + addr;

break;

}

case EO_RET: {

WriteToLog(_T("ret\r\n"));

int addr = stack.Remove(stack.GetSize() - 1);

p = (&operations) + addr;

break;

}

case EO_JZ:

case EO_JNZ:

case EO_JA:

case EO_JNA:

{

#ifdef WRITE_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


int addr = GetValue(p, *vars, *regs, *data);

WriteToLog("\r\n");

if (operation == EO_JZ && !(flags & EF_ZERO))

break;

else if (operation == EO_JNZ && (flags & EF_ZERO))

break;

else if (operation == EO_JA && !(flags & EF_ABOVE))

break;

else if (operation == EO_JNA && (flags & EF_ABOVE))

break;

p = (&operations) + addr;

break;

}

case EO_TEST_TIME_0:

{

WriteToLog(_T("test_time0 "), false);

int day = abs(GetValue(p, *vars, *regs, *data));

WriteToLog("");

if (static_cast(GetCurrentDayNum()) > day)

{

WriteToLog("ERROR TIME (except)");

data[0] ^= 0x00030001;

break;

}

WriteToLog("OK TIME (continue)");

break;

}

case EO_TEST_TIME_1:

{

WriteToLog(_T("test_time1 "), false);

int dayTmp = GetValue(p, *vars, *regs, *data);

WriteToLog("");

unsigned day = static_cast(abs(dayTmp));

if (GetCurrentDayNum() = 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("unsupported crypt algorithm type"));


if (alg.sizeAll != algorithmDataSize)

CkgExcept(_T("error crypt algorithm size"));


alg.variables[alg.numVarForSetSize] = size / sizeof(int);


BYTE *p = &algorithmDataArray;

p += sizeof AlgorithmDataStruct;

// _ASSERT(DWORD(p) & 0x03 == 0x0);

_ASSERT(DWORD(p) % sizeof(int) == 0x0);

TranslateOperations(*reinterpret_cast(p), *alg.variables,

dataArray);

}

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

void CryptData(BYTE &dataArray, size_t size, BYTE &algorithmDataArray,

size_t algorithmDataSize)

{

CryptDecryptData(dataArray, size, algorithmDataArray,

algorithmDataSize, true);

}

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

void DecryptData(BYTE &dataArray, size_t size, BYTE &algorithmDataArray,

size_t algorithmDataSize)

{

CryptDecryptData(dataArray, size, algorithmDataArray,

algorithmDataSize, false);

}

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

void CryptDecryptData(BYTE &dataArray, size_t size, const TCHAR &fileName,

bool crypt)

{

FILE *f = _tfopen(&fileName, _T("rb"));

if (!f)

CkgExcept(ERROR_OPEN_FILE);

try

{

if (fseek(f, 0, SEEK_END))

CkgExcept(ERROR_READ_FILE);

long algorithmDataSize = ftell(f);

cpp_arr_ptr algorithmDataArray(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;

}

}

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

void CryptData(BYTE &dataArray, size_t size, const TCHAR &fileName)

{

CryptDecryptData(dataArray, size, fileName, true);

}

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

void DecryptData(BYTE &dataArray, size_t size, const TCHAR &fileName)

{

CryptDecryptData(dataArray, size, fileName, false);

}

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

unsigned GetRandomNonUsedRegister(const AlgorithmParameters &parameters)

{

unsigned i;

unsigned numberNonUsedRegisters = 0;

for (i = 0; i < registersNum; i++)

numberNonUsedRegisters += !parameters.usedRegisters[i];

if (!numberNonUsedRegisters)

CkgExcept();

unsigned randomNum = CoolRand(numberNonUsedRegisters) + 1;

for (i = 0; i < registersNum; i++)

{

randomNum -= !parameters.usedRegisters[i];

if (!randomNum)

break;

}

_ASSERT(!randomNum && !parameters.usedRegisters[i]);

return i;

}

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

unsigned GetRandomNonUsedVariable(const AlgorithmParameters &parameters)

{

unsigned i;

unsigned numberNonUsedVariables = 0;

for (i = 0; i < variablesNum; i++)

numberNonUsedVariables += !parameters.usedVariables[i];

if (!numberNonUsedVariables)

CkgExcept();

unsigned randomNum = CoolRand(numberNonUsedVariables) + 1;

for (i = 0; i < variablesNum; i++)

{

randomNum -= !parameters.usedVariables[i];

if (!randomNum)

break;

}

_ASSERT(!randomNum && !parameters.usedVariables[i]);

return i;

}

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

unsigned ReserveRandomNonUsedRegister(AlgorithmParameters &parameters)

{

unsigned num = GetRandomNonUsedRegister(parameters);

parameters.usedRegisters[num] = true;

return num;

}

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

unsigned ReserveRandomNonUsedVariables(AlgorithmParameters &parameters)

{

unsigned num = GetRandomNonUsedVariable(parameters);

parameters.usedVariables[num] = true;

return num;

}

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

void RandomInitAlgorithmParameters(AlgorithmParameters &parameters,

unsigned numTransformation)

{

unsigned i;

for (i = 0; i < registersNum; i++)

parameters.usedRegisters[i] = false;

for (i = 0; i < variablesNum; 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 < parameters.numTransformation; 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;

}

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

void RandomInitAlgorithmParameters(AlgorithmParameters (&parameters)[2])

{

SYSTEMTIME lpSystemTime;

GetSystemTime(&lpSystemTime);

srand(unsigned(lpSystemTime.wSecond) * 1000 + lpSystemTime.wMilliseconds);


unsigned numTransformation = (maxNumTransformation > minNumTransformation) ?

CoolRand(maxNumTransformation - minNumTransformation) + minNumTransformation :

1;

RandomInitAlgorithmParameters(parameters[0], numTransformation);

RandomInitAlgorithmParameters(parameters[1], numTransformation);

}

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

bool SearchSubstitution(const Block &block, unsigned &position)

{

unsigned blockSize = block.GetSize();

_ASSERT(position 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 < appropriate.numShouldContain && found; 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 < appropriate.numNotShouldContain && !found; j++)

{

int needFind = appropriate.notShouldContain[j];

found = Search(*block, blockSize, needFind);

}

if (found)

continue;

}

convenianceSample.Add(i);

}

unsigned numConvenianceSample = convenianceSample.GetSize();

if (!numConvenianceSample)

return false;

unsigned select = numConvenianceSample > 1 ?

CoolRand(numConvenianceSample) :

0;

retAppropriateBlock = convenianceSample[select];

return true;

}

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

bool ReplacemenRandomEntity(int &entity, const AlgorithmParameters &parameters)

{

switch (entity)

{

case ES_RANDOM_NOP: {

unsigned NumNops = LAST_DEFINED_NOP - EO_NOP_0;

entity = CoolRand(NumNops);

entity += EO_NOP_0;

_ASSERT(entity >= EO_NOP_0 && entity = sizeBeforeLoop);

if (addr < sizeBeforeLoop)

CkgExcept();

}

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

void CreateLoopAddres(unsigned num, const AlgorithmParameters parameters[],

unsigned sizeBeforeLoop1,

unsigned sizeBeforeLoop2,

unsigned &addr1, unsigned &addr2)

{

_ASSERT(sizeBeforeLoop1 && sizeBeforeLoop2);

CreateLoopAddres_(num, parameters[0], sizeBeforeLoop1, addr1);

CreateLoopAddres_(num, parameters[1], sizeBeforeLoop2, addr2);

}

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

void CreateBlock3_(Block &block, AlgorithmParameters &parameters,

cpp_arr_ptr &, unsigned n, int &numSelectedBlock,

bool useCounterForModify)

{

_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;

}


SAppropriate appropriate;

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;

int whatNotContain[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 < sizeBlocks_03[index]; 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;

case ES_VARIABLE_0: _ASSERT(!parameters.addressIsReg);

newValue = parameters.addressNumber;

break;

case ES_VARIABLE_1: _ASSERT(!parameters.modificatoryIsReg[n]);

newValue = parameters.modificatorsNumbers[n];

break;

case ES_VARIABLE_2: _ASSERT(!parameters.counterIsReg);

newValue = parameters.counterNumber;

checkCountUse--;

_ASSERT(checkCountUse == 0);

break;

case ES_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-файлов (function CreateBlock3_). Обратитесь к разработчику."));

}

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

void CreateBlock3AB(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptr vars[], unsigned n,

int &numSelectedBlock, bool useCounterForModify)

{

_ASSERT(vars && n < maxNumTransformation);

numSelectedBlock = -1;

CreateBlock3_(block[0], parameters[0], vars[0], n, numSelectedBlock,

useCounterForModify);

_ASSERT(numSelectedBlock >= 0);

}

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

void CreateBlock3BA(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptr vars[], unsigned n,

int numSelectedBlock, bool useCounterForModify)

{

_ASSERT(vars && n < maxNumTransformation);

_ASSERT(numSelectedBlock >= 0);

CreateBlock3_(block[1], parameters[1], vars[1], n, numSelectedBlock,

useCounterForModify);

}

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

void CreateBlock4_(Block &block, AlgorithmParameters &parameters, cpp_arr_ptr &)

{

_ASSERT(block.IsEmpty());

SAppropriate appropriate;

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 < sizeBlocks_04[index]; 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;

case ES_VARIABLE_0: _ASSERT(!parameters.addressIsReg);

newValue = parameters.addressNumber;

break;

default: CkgExcept();

}

block.GetRef(position) = newValue;

}

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

}

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

void CreateBlock4(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptr vars[])

{

CreateBlock4_(block[0], parameters[0], vars[0]);

CreateBlock4_(block[1], parameters[1], vars[1]);

}

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

void CreateBlock5_(Block &block, AlgorithmParameters &parameters,

cpp_arr_ptr &, unsigned addr)

{

_ASSERT(block.IsEmpty());

SAppropriate appropriate;

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 < sizeBlocks_05[index]; 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;

case ES_VARIABLE_0: _ASSERT(!parameters.counterIsReg);

newValue = parameters.counterNumber;

break;

case ES_ADDRESS_0: newValue = static_cast(addr);

break;

default: CkgExcept();

}

block.GetRef(position) = newValue;

}

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

}

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

void CreateBlock5(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptr vars[], unsigned addr1, unsigned addr2)

{

CreateBlock5_(block[0], parameters[0], vars[0], addr1);

CreateBlock5_(block[1], parameters[1], vars[1], addr2);

}

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

void CreateBlock6_(Block &block, AlgorithmParameters &parameters,

cpp_arr_ptr &vars, int deltaTime)

{

_ASSERT(block.IsEmpty());

SAppropriate appropriate;

unsigned index;

if (!SearchRandomAppropriateBlock(sizeBlocksArray_06, *sizeBlocks_06,

*blocks_06, appropriate, index))

CkgExcept();


for (unsigned i = 0; i < sizeBlocks_06[index]; 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;

case ES_VARIABLE_0: newValue = ReserveRandomNonUsedVariables(parameters);

vars[static_cast(newValue)] = deltaTime;

break;

default: CkgExcept();

}

block.GetRef(position) = newValue;

}

DEBUG_TEST_BLOCK(block.Get(position));

position++;

}

}

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

void CreateBlock6(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptr vars[], unsigned deltaTimeCrypt,

unsigned deltaTimeDecrypt)

{

_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 Add(entity);

return;

}


if (deltaTimeCrypt > maxUseTime || deltaTimeCrypt > INT_MAX ||

deltaTimeDecrypt > maxUseTime || deltaTimeDecrypt > INT_MAX)

CkgExcept(_T("Задан слишком большой период времени для возможности использования алгоритма."));

bool invert = CoolRand(2) == 1;

int newDeltaTimeCrypt = invert ? -static_cast(deltaTimeCrypt) :

static_cast(deltaTimeCrypt);

invert = CoolRand(2) == 1;

int newDeltaTimeDecrypt = invert ? -static_cast(deltaTimeDecrypt) :

static_cast(deltaTimeDecrypt);

CreateBlock6_(block[0], parameters[0], vars[0], newDeltaTimeCrypt);

CreateBlock6_(block[1], parameters[1], vars[1], newDeltaTimeDecrypt);

}

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

void CreateBlock7_(Block &block, AlgorithmParameters &parameters,

cpp_arr_ptr &)

{

_ASSERT(block.IsEmpty());

SAppropriate appropriate;


unsigned index;

if (!SearchRandomAppropriateBlock(sizeBlocksArray_07, *sizeBlocks_07,

*blocks_07, appropriate, index))

CkgExcept();


for (unsigned i = 0; i < sizeBlocks_07[index]; 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++;

}

}

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

void CreateBlock7(Block block[], AlgorithmParameters parameters[],

cpp_arr_ptr vars[])

{

CreateBlock7_(block[0], parameters[0], vars[0]);

CreateBlock7_(block[1], parameters[1], vars[1]);

}

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

void GenerateArrayRndDeltas(CkgSimpleContainerArray &deltas,

unsigned num, unsigned freeRegionSize)

{

_ASSERT(num && freeRegionSize);

_ASSERT(deltas.IsEmpty());

unsigned i;

for (i = 0; i < num; i++)

{

unsigned rnd;

#ifdef _DEBUG

unsigned counter = 0;

#endif

do

{

_ASSERT(counter++ < 10);

rnd = CoolRand(freeRegionSize);

if (freeRegionSize 0; i--)

{

_ASSERT(deltas[i] > deltas[i - 1]);

deltas.GetRef(i) -= deltas[i - 1];

}


#ifdef _DEBUG

{

unsigned size = 0;

for (i = 0; i < deltas.GetSize(); i++)

size += deltas[i];

_ASSERT(size == freeRegionSize);

}

#endif

}

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

void GenerateAndAddNopBlocks(const CkgSimpleContainerArray &deltas,

CkgArray &newArray,

AlgorithmParameters &parameters,

cpp_arr_ptr vars[],

Block (*blocks)[2], bool isBA,

unsigned numFirstBlock)

{

_ASSERT(!deltas.IsEmpty());

for (unsigned i = 0; i < deltas.GetSize(); i++)

{

unsigned delta = deltas[i];

while (delta)

{

cpp_ptr nopBlock(new Block);

TestPtr(nopBlock);

CreateNopBlock(*nopBlock, parameters, *vars, delta);

unsigned nopBlockSize = nopBlock->GetSize();

_ASSERT(nopBlockSize && nopBlockSize Add(blocks[numFirstBlock + i][isBA][j]);

newArray.Add(*tmp);

tmp.Detach();

}

}

}

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

void SmearAndAddNopBlocks(Block (*blocks)[2], bool isBA,

AlgorithmParameters &parameters,

cpp_arr_ptr vars[],

CkgArray &newArray, unsigned addr)

{

_ASSERT(blocks && vars && newArray.IsEmpty());

unsigned i;

unsigned freeRegionSize = addr;

unsigned totalNumTrueBlocks = parameters.totalNumTrueBlocks;

unsigned blocksBeforeLoop = numBlocksBeforeLoop + parameters.numTransformation - 1;

unsigned blocksAfterLoop = totalNumTrueBlocks - blocksBeforeLoop;

for (i = 0; i < blocksBeforeLoop; i++)

freeRegionSize -= blocks[i][isBA].GetSize();

_ASSERT(static_cast(freeRegionSize) > 0); // Не ошибка, но "рисково" получилось.


CkgSimpleContainerArray deltas;

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 < newArray.GetSize(); i++)

size += newArray[i].GetSize();

_ASSERT(size == addr);

}

#endif


deltas.Clear();


_ASSERT(parameters.sizeAlgorithm > addr);

freeRegionSize = parameters.sizeAlgorithm - addr;

for (i = blocksBeforeLoop; i < totalNumTrueBlocks; 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);

}

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

static int DebugFindMaxBlockSize(unsigned n, const unsigned *sizes)

{

_ASSERT(n && sizes);

unsigned max = 0;

for (unsigned i = 0; i < n; i++)

if (max < sizes[i])

max = sizes[i];

_ASSERT(max);

return max;

}

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

static void 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("Calc Max Algorithm Size = "), false);

WriteToLog(sum);

// Если меньше, то наверно легко словить ошибку.

_ASSERT(sum * 2 < minSizeAlgorithm);

}

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

void GenerateAlgorithm(pure_c_ptr &algorithmCrypt, size_t &sizeCrypt,

pure_c_ptr &algorithmDecrypt, size_t &sizeDecrypt,

unsigned deltaTimeCrypt, unsigned deltaTimeDecrypt)

{

WriteToLog(_T("GenerateAlgorithm()"));

#ifdef _DEBUG

DebugTestParam();

#endif

unsigned i, j;

AlgorithmParameters parameters[2];

RandomInitAlgorithmParameters(parameters);


cpp_arr_ptr vars[2];

for (unsigned k = 0; k < 2; k++)

{

vars[k] = new int[variablesNum * sizeof(int)];

TestPtr(vars[k]);

for (i = 0; i < variablesNum; i++)

vars[k][i] = CoolRand();

}


Block (*blocks)[2] = new Block[parameters[0].totalNumTrueBlocks][2];

cpp_arr_ptr memControl(blocks);


unsigned num = 0;

CreateBlock0(blocks[num++], parameters, vars);

CreateBlock1(blocks[num++], parameters, vars);


for (i = 0; i < parameters[0].numTransformation; i++)

CreateBlock2(blocks[num++], parameters, vars, i);

unsigned sizeBeforeLoop1, sizeBeforeLoop2;

CalcBlocksSize(blocks, num, sizeBeforeLoop1, sizeBeforeLoop2);

unsigned addr1 = 0, addr2 = 0;


CreateLoopAddres(num, parameters, sizeBeforeLoop1, sizeBeforeLoop2, addr1, addr2);


CkgSimpleContainerArray selectedBlocks;

CkgSimpleContainerArray arrUseCounterForModify;


for (i = 0; i < parameters[0].numTransformation; i++)

{

int numSelectedBlock = -1;

bool useCounterForModify = 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 < parameters[0].numTransformation; 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);


CkgArray blocksAB;

CkgArray blocksBA;


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 < blocksAB.GetSize(); i++)

sizeAB += blocksAB[i].GetSize();

unsigned sizeBA = 0;

for (i = 0; i < blocksBA.GetSize(); 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_ptr algorithmAB(static_cast(AccurateMalloc(sizeAB)));

pure_c_ptr algorithmBA(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 < blocksAB.GetSize(); i++)

for (j = 0; j < blocksAB[i].GetSize(); j++)

*p++ = blocksAB[i][j];

p = algorithmBA + sizeof(AlgorithmDataStruct) / sizeof(int);

for (i = 0; i < blocksBA.GetSize(); i++)

for (j = 0; j < blocksBA[i].GetSize(); j++)

*p++ = blocksBA[i][j];


algorithmCrypt = reinterpret_cast(algorithmAB.ptr());

algorithmAB.Detach();

sizeCrypt = sizeAB;

algorithmDecrypt = reinterpret_cast(algorithmBA.ptr());

algorithmBA.Detach();

sizeDecrypt = sizeBA;

}

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

void GenerateAlgorithm(const TCHAR &algorithmCryptFileName,

const TCHAR &algorithmDecryptFileName,

unsigned deltaTimeCrypt,

unsigned deltaTimeDecrypt)

{

pure_c_ptr algorithmCrypt;

size_t sizeCrypt;

pure_c_ptr algorithmDecrypt;

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;

}

}

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

int CoolRand()

{

static unsigned flagInit;


int a = rand();

if (flagInit == 0)

{

SYSTEMTIME lpSystemTime;

GetSystemTime(&lpSystemTime);

srand(unsigned(lpSystemTime.wSecond) * 1000 + lpSystemTime.wMilliseconds);

flagInit = 1000;

}

else

flagInit--;


int b = rand();

int c = rand();

a GetPosition(); }

void Close();

~ObjectFile();

};


/////////////////////////////////////////////////////////////////////////////

// CProtect

class ATL_NO_VTABLE CProtect :

public CComObjectRootEx,

public CComCoClass,

public ISupportErrorInfo,

public IDispatchImpl,

public IDispatchImpl,

public IDispatchImpl

// public IDispatchImpl

{

static CkgArray files;

static CkgSimpleContainerArray handles;


void ContinueOpen(ObjectFile &file, short &handle);

void ContinueGenerateTimeLimitUPTfiles(BSTR algorithmCryptFileName,

BSTR algorithmDecryptFileName,

long LimitDaysCrypt,

long LimitDaysDecrypt);

HRESULT InternalGetAlgName(const CkgString &Strings,

CkgString SearchName,

CkgString &Result);

HRESULT InternalGetDataName(const CkgString &Strings,

CkgString SearchName,

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)(REFIID riid);


// 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]*/ BSTR uptFileNameForWrite, /*[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]*/ BSTR uptFileNameForWrite, /*[in]*/ BSTR ArrayOfStrings);

STDMETHOD(EasyCreateConformityFile)(/*[in]*/ BSTR name, /*[in]*/ BSTR uptFileNameForCreate, /*[in]*/ BSTR ArrayOfStrings);

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]*/ BSTR SearchName, /*[out, retval]*/ BSTR *ResultStr);

STDMETHOD(GetDataFromFile)(/*[in]*/ BSTR FileName, /*[in]*/ BSTR uptFileNameForRead, /*[in]*/ BSTR SearchName, /*[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"


// В Visaul Basic все равно больше нельзя

const static unsigned maxDimDimensions = 60;


static bool TestFilePresent(BSTR name, bool maybeUnnecessary = false)

{

WriteToLog(_T("TestFilePresent()"));

if (!name && maybeUnnecessary)

return true;

if (!name)

return false;


USES_CONVERSION;

CkgString strName(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;

}


//=============================================================================

//class ObjectFile

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

void ObjectFile::CryptBuf()

{

WriteToLog(_T("ObjectFile::CryptBuf()"));

byte compressionLevel;

if (fileMode == DISABLE_ARC)

compressionLevel = 1; // min compression level

else

compressionLevel = 0; // default

unsigned long sizeOut;

BYTE *bufOut;

EIAB_ErrorNum err;

if (!Pack(compressionLevel, buffer->GetSize(),

static_cast(buffer->GetBuf()), &sizeOut, &bufOut, &err))

ArcExcept(err);

_ASSERT(sizeOut && bufOut);

pure_com_mem packet(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 < needAdd; 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));

}

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

void ObjectFile::DecryptBuf()

{

WriteToLog(_T("ObjectFile::DecryptBuf()"));

if (buffer->GetSize() < sizeof(TitleArcData) + sizeof(unsigned))

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 long sizeOut;

BYTE *bufOut;

EIAB_ErrorNum err;

if(!Unpacking(packSize,

static_cast(buffer->GetBuf()) + sizeof(unsigned),

&sizeOut, &bufOut, &err))

ArcExcept(err);

_ASSERT(sizeOut && bufOut);

pure_com_mem unpacket(bufOut);

buffer->Clear();

buffer->Write(bufOut, sizeOut);

}

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

ObjectFile &ObjectFile::Create(BSTR name, BSTR uptFileNameForWrite,

CreateMode mode)

{

WriteToLog(_T("ObjectFile::Create()"));

USES_CONVERSION;

if ((mode != DEFAULT && mode != DISABLE_ARC) || !uptFileNameForWrite ||

!name)

CkgExcept(ERROR_INVALID_ARGUMENT);

CkgString fileName(W2T(name));

if (fileName.IsEmpty())

CkgExcept(ERROR_OPEN_FILE);


if (!TestFilePresent(uptFileNameForWrite))

CkgExcept(_T("UPT-файл для шифрования файла не найден."));


cpp_ptr obj(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,

BSTR uptFileNameForRead)

{

WriteToLog(_T("ObjectFile::Open()"));

USES_CONVERSION;

if (!name)

CkgExcept(ERROR_INVALID_ARGUMENT);

CkgString fileName(W2T(name));

if (fileName.IsEmpty())

CkgExcept(ERROR_OPEN_FILE);


if (!TestFilePresent(uptFileNameForWrite, true))

CkgExcept(_T("UPT-файл для шифрования файла не найден."));

if (!TestFilePresent(uptFileNameForRead))

CkgExcept(_T("UPT-файл для расшифровки файла не найден."));


cpp_ptr obj(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_ptr buf(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();

}

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

void ObjectFile::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);

}

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

void ObjectFile::Read(void *buf, unsigned size)

{

_ASSERT(!isClosed);

unsigned position = buffer->GetPosition();

if (buffer->GetSize() - position < size)

CkgExcept(ERROR_INVALID_ARGUMENT);

memcpy(buf, static_cast(buffer->GetBuf()) + position, size);

buffer->LSeek(position + size);

}

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

void ObjectFile::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);

}

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

void ObjectFile::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

CkgArray CProtect::files(true);

CkgSimpleContainerArray CProtect::handles;


STDMETHODIMP CProtect::InterfaceSupportsErrorInfo(REFIID riid)

{

static const IID* arr[] =

{

&IID_IProtect

};

for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)

{

if (InlineIsEqualGUID(*arr[i],riid))

return S_OK;

}

return S_FALSE;

}


STDMETHODIMP CProtect::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

}


STDMETHODIMP CProtect::GenerateUPTfiles(BSTR algorithmCryptFileName,

BSTR algorithmDecryptFileName)

{

return GenerateTimeLimitUPTfiles(algorithmCryptFileName,

algorithmDecryptFileName,

0);

}


void CProtect::ContinueGenerateTimeLimitUPTfiles(

BSTR algorithmCryptFileName, BSTR algorithmDecryptFileName,

long LimitDaysDecrypt, long LimitDaysCrypt)

{

if (LimitDaysDecrypt)

LimitDaysDecrypt += GetCurrentDayNum();

if (LimitDaysCrypt)

LimitDaysCrypt += GetCurrentDayNum();


USES_CONVERSION;

if (!algorithmCryptFileName || !algorithmDecryptFileName)

CkgExcept(_T("Строка с именем upt-файла пустая."));

LPCTSTR fileNameCrypt(W2T(algorithmCryptFileName));

LPCTSTR fileNameDecrypt(W2T(algorithmDecryptFileName));

if (!_tcslen(fileNameCrypt) || !_tcslen(fileNameDecrypt))

CkgExcept(_T("Строка с именем upt-файла пустая."));


GenerateAlgorithm(*fileNameCrypt, *fileNameDecrypt,

static_cast(LimitDaysDecrypt),

static_cast(LimitDaysCrypt));

}


STDMETHODIMP CProtect::GenerateTimeLimitUPTfiles(BSTR algorithmCryptFileName,

BSTR algorithmDecryptFileName,

long LimitDays)

{

WriteToLog(_T("CProtect::GenerateTimeLimitUPTfiles()"));

try

{

ContinueGenerateTimeLimitUPTfiles(algorithmCryptFileName,

algorithmDecryptFileName,

LimitDays, LimitDays);

return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

return S_OK;

}


STDMETHODIMP CProtect::GenerateTimeLimitUPTfiles2(BSTR algorithmCryptFileName,

BSTR algorithmDecryptFileName, 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;

}


void CProtect::ContinueOpen(ObjectFile &file, short &handle)

{

files.Add(file);


short i;

for (i = 1; i < SHRT_MAX; i++)

{

if (handles.IndexOf(i) == -1)

{

handle = i;

handles.Add(i);

break;

}

}

if (i == SHRT_MAX)

CkgExcept(_T("Нет больше свободных дескипторов."));

_ASSERT(handle);

}


STDMETHODIMP CProtect::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

}


STDMETHODIMP CProtect::Open(BSTR name, BSTR uptFileNameForRead,

BSTR uptFileNameForWrite, short *handle)

{

WriteToLog(_T("CProtect::Open()"));

try

{

_ASSERT(handle);

ContinueOpen(ObjectFile::Open(name, uptFileNameForWrite,

uptFileNameForRead), *handle);

return S_OK;

}

CONVERT_EXCEPTION_TO_COM_EXCEPTION

}


STDMETHODIMP CProtect::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

void WriteVariable(ObjectFile &file, const T &var, VARTYPE varType)

{

file.Write(&varType, sizeof(VARTYPE));

file.Write(&var, sizeof(T));

}


STDMETHODIMP CProtect::Write(short handle, VARIANT buffer, long *written)

{

WriteToLog(_T("CProtect::Write()"));

try

{

int index = handles.IndexOf(handle);

if (index == -1)

CkgExcept(_T("Ошибка записи в файл. (Неверный дескриптор.)"));


VARTYPE vt = 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));

CComBSTR str(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));


const SAFEARRAYBOUND *bound = safeArray.rgsabound;

unsigned size = 0;

for (unsigned i = 0; i < safeArray.cDims; 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

}


STDMETHODIMP CProtect::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();


CComBSTR str(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

T ReadVariable(ObjectFile &file)

{

T tmp;

file.Read(&tmp, sizeof(T));

return tmp;

}


STDMETHODIMP CProtect::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)

{

unsigned len = 0;

file.Read(&len, sizeof(len));

CComBSTR str(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 {

SAFEARRAY safeArray;

SAFEARRAYBOUND buf[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


Информация о работе «Защита информации в системах дистанционного обучения с монопольным доступом»
Раздел: Информатика, программирование
Количество знаков с пробелами: 284992
Количество таблиц: 7
Количество изображений: 0

Похожие работы

Скачать
40302
0
0

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

Скачать
568458
20
78

... для реализации системы бюджетирования Консультационной группы "Воронов и Максимов". Статья о проблемах выбора системы бюджетирования - в проекте "УПРАВЛЕНИЕ 3000". Бюджетный автомат Если вы решитесь на автоматизацию системы бюджетирования компании, перед вами сразу встанут вопросы: что выбрать, сколько платить, как внедрять. Примеряйте! О ЧЕМ РЕЧЬ В “Капитале” на стр. 44, 45 мы рассказали ...

Скачать
26363
0
0

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

Скачать
61070
3
3

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

0 комментариев


Наверх