Автор: Пользователь скрыл имя, 23 Марта 2012 в 03:04, дипломная работа
Актуальность работы. Многие направления науки и техники, имеющие отношение к получению, обработке, хранению и передаче информации, в значительной степени ориентируются на развитие современных компьютерных систем (КС) [30]. Такие системы представляют разнообразную и весьма сложную совокупность вычислительных устройств, систем обработки информации, телекоммуникационных технологий, программного обеспечения и высокоэффективных средств его проектирования и в общем случае представляющие гетерогенную программно-аппаратную среду.
Введение 4
Глава 1. Анализ методов защиты программных средств 11
1.1 Методы защиты информации с помощью аппаратных средств 12
1.2 Программные средства защиты информации 16
1.3 Анализ программных средств как объекта защиты 21
1.4 Анализ структуры программных систем защиты информации 24
1.5 Выводы 26
Глава 2. Построение методов защиты программных средств с помощью,
запутывающих преобразований 28
2.1 Понятие запутывающих преобразований для реализации защиты
программных средств вне доверенной вычислительной среды 29
2.2 Классификация запутывающих преобразований 32
2.2.1 Преобразования форматирования 32
2.2.2 Преобразования структур данных 33
2.2.3 Преобразования потока управления .34
2.3 Классификация методов анализа программ .44
2.3.1 Методы статического анализа .45
2.3.2 Методы статистического и динамического анализа 47
2.4 Классификация способов запутывания к применяемым методам анализа и распутывания программ 48
2.5 Оценка эффективности применения запутывающих преобразований 50
2.6 Выводы .51
ГлаваЗ. Построение метода защиты программных средств с помощью
запутывающих преобразований ;.53
3.1 Построение графа потока управления 56
з
3.2 Преобразование графа потока управления 60
3.5 Теоретическое обоснование устойчивости метода 68
3.6 Практическое обоснование устойчивости мето да 71
3.7 Выводы 72
Глава 4. Решение практических задач защиты программных средств 74
4.1 Анализ характеристик методов защиты программных средств 74
4.2 Выбор объектов тестирования 74
4.3 Методика оценки эффективности защиты 75
4.3.1 Оценка эффективности программных средств 80
4.4 Оценка устойчивости метода к ручному анализу и дизассемблированию85
4.4.1 Подготовка эксперимента 85
4.4.2 Описание результатов эксперимента 86
4.4.3 Результаты дизассемблирования 90
4.5 Определение размера требуемых ресурсов вычислительной системы 91
4.6 Показатели применимости разработанного метода защиты программных средств 99
4.7 Выводы 101
Заключение 103
Список использованной литературы 106
Если есть обратная дуга т->п, тогда цикл, соответствующий дуге т-їп состоит из вершины п (заголовок цикла) и всех вершин, из которых достигается т, не проходя через п.
Современные языки программирования поддерживают стандартный набор управляющих конструкций (if-then, do-while и пр.). Структурные конструкции порождают специфические графы потока управления. Для оператора if-then-else (рис. 3.3(a)) на месте блоков then и else могут находиться другие структурные подграфы. Проанализировав структурные управляющие конструкции, для каждой конструкции можно представить шаблон графа потока управления (рис.3.3).
і
а)
б)
в)
г)
т\
е)
д)
з)
ж)
Рисунок 3.3 - Пример шаблонных конструкций: if-then-else (а), последовательность блоков (б), if-then (в), собственный цикл (г), естественный цикл (д), пример условной области (е), цикл while (ж), пример не сводимой области (з)
60
3.2 Преобразование графа потока управления
Преобразования циклов заключаются в том, что в цикл вносится ложное условие, при этом дуга, которая соответствует «истине» переходит внутрь цикла, а дуга, которая соответствует значению «ложь», переходит в начало цикла. Так же возможно создание цикла с двумя и более входами, например, перед началом цикла ставится условие, которое всегда принимает значение «истина», истинная дуга переходит на начало цикла, ложная на базовый блок, который помещается в конец физической последовательности, представляющий данный граф, а выходную дугу из этого блока на начало цикла.
На этом этапе так же используются метки (указатели), перемешивание и их переименование.
На рис. 3.4 приведен граф потока управления для исходного текста программы сортировки методом Шелла (метки L1,L2 иЬЗ для блоков 2 ,4 и 6 соответственно).
Перед операторами while, until, for и foreach, а также перед блоками ставятся указатели. В качестве указателя может использоваться любой идентификатор, который не является зарезервированным словом.
В данном случае применение меток используется для усложнения передачи управления программы, т.е. когда метки используются для передачи управления из внешнего цикла к глубоко вложенному циклу. Оператор перехода goto передает управление оператору с указанной меткой и заменяет конструкции if-then-else и циклы.
Все используемые метки рис. 3.4 фиксируют начало цикла. После замены циклов на метки, мы получаем множество новых указателей. В результате получим следующий граф потока, рис. 3.5. Базовые блоки, полученные в результате преобразования, остаются эквивалентными исходному графу.
61
int increment(long inc[], long size) { int pi, p2, p3, s/ pi = p2 = p3 = 1; s = -1; do {
if (++s % 2) {
inc[s] = 8*pl - 6*p2 + 1/} else {
inc[s} = 9*pl - 9*p3 + 1; p2 *= 2; p3 *= 2/ }pl *= 2;} while(3*inc[s] < size)/
return s > 0 ? —s : 0;} template<class T>
void shellSort(T a[], long size) { long inc, i, j, seq[40]/ int s/ s = increment(seq, size)/ while (s >= 0) {
inc = seqts—]/ for (i = inc/ і < size/ i++) { T temp = a[i]/ for (j = i-inc/ (j >= 0) && (a[j] > temp)/ j -= inc)
a[j+inc] = a[j]/a[j+inc] = temp/}}} void main () { int arr[1000]/ srand(time(NULL))/ int size = 0/ size = sizeof(arr)/sizeof(int)/
for(int і = 0/ і < size/ i++){
arr[і] = rand() - rand()/} for(int і = 0/ і < size/ i++){ printf("%d\t", arr[i])/} shellSort(arr, size)/ for(int і = 0; і < size/ i++){ printf("%d\t", arr[i])/} clock_t tot_time=0/ tot_time = clockO/ float a=0/
a = (float)tot_time / (float)CLKJTCK/
printf("\ntotal time:%f\n%f", a, (float)tot_time)/
getch() / }
О (вход)
12 (выход)
Исходный текст программы
Граф потока управления исходного текста
Рисунок 3.4 - Граф потока управления исходного текста программы сортировки методом Шелла
62
long inc, і, j, seq[40]; int
s, k;
int kof[10];k=l; kof[l]=50;
kof[2]=25; kof[3]=13;kof[4]=6;
kof[5]=3; kof[6]=2; kof[7]=l;
L3:
if (k<=7) goto LI;
else goto L2;
LI: {
inc = kof[k]; i=inc; L5:
if (Ksize)
goto L4;
else goto L6; L4:
{ T temp = a[i]; j = i-inc; L9: if ((j >= 0) && (a[j] > temp))
goto L7;
else goto L8; L7:
a[j+inc] = a[j]; j -= inc;
goto L9; L8:
a[j+inc] = temp;
} i=i++;
goto L5; L6:
k=k++; goto L3; } L2:}
Текст программы после внесения меток
Граф потока управления после внесения
меток
Рисунок 3.5 - Вид графа потока управления после замены циклов метками
При сравнении графов потока управления исходной и запутанной программы видно, что изменились только метки. Такая программа не вызывает особых трудностей даже при синтаксическом анализе.
Преобразование графа потока управления включает в себя введение блока мертвого кода программы и связности между блоками основного и мертвого кода с помощью указателей.
Следуя авторской работе А.В. Чернова, построение блока мертвого кода может осуществляться из нескольких этапов.
Этап создания мертвого кода состоит из следующих под этапов: ■ определение пула типов;
определение пула переменных;
генерация мертвого кода. На рис. 3.6 представлен граф после применения таких преобразований.
Рисунок 3.6 - Вид графа потока управления с внесением мертвого кода
64 Блок 1 рис. 3.6 соответствует указателям L3, Ы (метки имеют иные имена, это связано с прикладной реализацией). Блок 2 соответствует указателям L5, L4, L6. Блок 3 соответствует L9, L7, L7. Блок 4 соответствует мертвому коду.
На следующем этапе, для дальнейшего запутывания применим преобразования структур данных с помощью введения массива для хранения переменных одного типа. Объединение и переупорядочивание элементов массива.
Листинг программы сортировки методом Шелла после объединения
переменных в массив будет выглядеть следующим образом:
long inc,і,j,seq[40];
int s,k;
intkof[10];k=l;kof[1]=50;kof[
kof[4]=6;kof[5]=3;kof[6]=2;kof
L3:
if (b[3]<=7) goto LI;
else goto L2;
LI:
{b[4] = kof [b[3]]; b[l]=b[4];
L5:
if (b[l]<size) goto L4;
else goto L6;
L4
{
T temp = a[b[l] ] ; b[2] =b[l]-b[4];
L9
if ((b[2] >= 0) && (a[b[2]] > temp)) goto L7; else goto L8;
L7
a[b[2]+b[4]] = a[b[2]]; b[2] -= b[4]; goto L9;
L8
a[b[2]+b[4]] = temp;} b[l]=b[l]++; goto L5;
L6:
b[3]=b[3]++; goto L3;} L2:
65 Связность блоков основного и мертвого кода программы осуществляется с помощью введения в тело этих блоков меток (указателей), что является трудноанализируемым свойством программы для проведения статического и синтаксического анализа. Кроме того, переменные одного типа мертвого и основного кода объединены в массив и используются в теле функций выполнения блоков только индексы массива. Чтобы затруднить анализ элементы массива заполняются случайным образом. Массив содержит переменные, которые вычисляются основной функцией программы и переменные, которые используются при перевычислении.
Полученный граф потока управления после таких преобразований представлен на рис. 3.8, и имеет свойство конечного графа 32-го порядка и размерностью 43.
Рисунок 3.8 - Граф потока управления запутанного кода программы
66
Листинг программы для графа потока управления представленного
рис. 3.7 выглядит следующим образом: long inc, і, j, seq[40];
int d,s,k,h=4,q=ll;int kof[10];int b[50]; k=l;b[ll]=5;b[21]=-6;kof[3]=
Ll:{b[4] = kof [b[3] ] ;b[l]=b[4] ; goto L5; L20:
if (h>l){b[l]=b[ll]+b[21]+b[31];
goto L21;}
else goto Ll; L6:b[3]=b[3]++; goto L3; L4:{T temp = a[b[l]];
b[2] =b[l]-b[4]; goto L9;
L7:a[b[2]+b[4]] = a[b[2]]; b[2] -= b[4];goto L9; L9: if ((b[2] >= 0) && (a[b[2]] > temp)) goto L7;
else goto L8; L8: a[b[2]+b[4]] = temp; } b[l]=b[l]++; goto L5;} L21: if (q<12) {h=5; goto L22;} L5: if (b[l]<size) goto L4;
else goto L6; L3: if (b[3]<=7) goto Ll;
else goto L2; L22: if (d=5)
{b[3]=b[13]+b[23]+b[33];b[4]=
goto Ll; L2:
68
3.5 Теоретическое обоснование устойчивости метода
Для теоретического обоснования устойчивости метода используется аппарат дискретной математики, теории схем программ, машин Тьюринга [20, 21,22,76,83].
Пусть S = {0,1}, poly{n) - произвольный многочлен от переменной п.
Определение 1. Пусть f: Sm -> S", т = poly(ri).
Функция / (отображение) называется односторонней функцией, если
для любого xeSm существует полиномиальный алгоритм вычисления значений f(x) и не существует полиномиального алгоритма инвертирования
функции /. Для любой полиномиальной вероятностной машины Тьюринга
РгТ выполнено следующее:
P{f{A{f(x))) = f(x)} < Vpolyim).
Вероятность здесь определяется случайным выбором х и случайными величинами, которые Ргт использует в своей работе.
Определение 2. Взаимнооднозначная односторонняя функция f:S"->Sn называется односторонней перестановкой.
Определение 3. є -приближённым алгоритмом решения оптимизационной задачи называется алгоритм, находящий решение не более чем в є раз хуже оптимального решения.
Пример. Задача М минимизации некоторого функционала /.
Пусть А - є -приближённый алгоритм нахождения решения задачи М. Пусть для некоторой реализации задачи оптимальное значение функционала равно X. Тогда алгоритм А найдёт решение задачи, при котором значение / равно Y, причём будет справедливо неравенство X < Y < РХ.
Определение 4. Пусть f:Sm^S", x = {xx,...,xm), У = (ух,.-.,уп), y = f{x). Переменная хк называется существенной, если существуют
\Х\)...,Хк_\,Хкл.\,...,Хт) Є о И J Є \1,...,Щ
такие, что выполняется условие:
69 J j\xx,...,xk_x,\),xk+x,...,xm) Ф jj{xl,...,xk_l,i,xk+l,...,xm).
Теорема 1. Пусть f:Sm^>Sn, f записана как система булевых формул в базисе {и.п,-,}, 1 < к < т.
Задача проверки существенности переменной хк NP -полна.
Доказательство.
Пусть ех Ф ег = (ех п е2) и (ех п е2),
где ех, е2 - булевы формулы.
Обозначим х = (хх,...,хт), у = (у1,...,уя) и *|/=а= (*,,.. jrM,o-,*/+1,...xJ.
1. Задача существенности находится в классе NP.
п
Пусть g(x) = \J(fj(x\i^)^(fj(x\i=x)) булева формула.
Если переменная существенна, то существует такой вектор х, для которого g(x) = 1. Если переменная не существенна, то на всех наборах х выполняется g(x) = 0.
И наоборот, если g(x) принадлежит языку «выполнения» (выполняется),
то переменная хк существенна. Если g(x) не принадлежит языку «выполнения», то хк - не существенна.
*S Таким образом, задача проверки существенности сведена к задаче про-
верки выполнимости булевой формулы. Последняя находится в классе NP. Следовательно, и задача проверки существенности находится в классе NP, как показано в работе Чернова А.В. [83] и Ященко В.В.
2. Задача выполнения, которая является NP - полной, полиноми
ально сводится к задаче существенности.
"#* Пусть g{x) - некоторая формула в базисе {u,n,-,}. Тогда формула, реали-
зующая функцию / = 1, принадлежит языку «выполнения», но ни одна переменная в такой формуле не является существенной.
70 В формуле, реализующей функцию f = 0, которая не принадлежит языку «выполнения», также нет существенных переменных. Все прочие формулы, принадлежат языку «выполнения», и хотя бы одна переменная в них является существенной. Таким образом, формула не принадлежит «выполнению», если её значение на любом битовом наборе равно 0, и в ней нет существенных переменных.
Для проверки выполнимости формулы нужно проверить её значение в одной точке и т раз проверить существенность переменных формулы. Следовательно задача выполнения полиномиально по Тьюрингу сводится к задаче существенности, что доказывает NP -полноту последней.
Определение 5. Пусть f:Sm->Sn,x = (xlt...,xm), у = (yv...,yn), у = f(x). Пусть множество / - это множество индексов компонент у.
Переменная хк называется существенной относительно множества /, если существуют такие (xv...,xk_x,xk+x,...,xm) є £ и такая j є І, что выполняется условие f.{xv...,xk_x,Q,xM,...,xm).
Теорема 2. Пусть даны т, п, f:Sm->Sn, I £ 2(1--л), к. Задача проверки существенности переменной хк относительно множества / NP -полна.
Доказательство принадлежности задачи к классу NP аналогично доказательству теоремы 1.
Пусть / = {1,...,«} задача существенности является частным случаем для
доказательства NP.
Определение 6. Задача анализа зависимостей по данным определяется как задача нахождения минимального множества переменных Win с Vin такого, что переменные из множества Vin-Wы несущественны относительно W
где V = {vx,...,vk} - множество переменных запутанной программы,
/ :Sm -» S" - базовый блок представляющий вычисление булевой функции над переменными из Vin;
71
Vin Q V,\Vin\ = m - переменные, значения которых используются при вычислении /,
Уош Я: V, \У0Ш\ = п - переменные, которые получают новые значения в результате вычисления, если для некоторой переменной veVin и veV0Ut, при вычислении используется старое значение переменной;
Wout с Vout - множество «существенных» переменных на выходе из базового блока.
Теорема 3. Задача ЗАВ NP-полна.
Доказательство.
Принадлежность задачи классу NP следует из того, что для каждого / такого, что (1 < і < к) можно найти решение задачи существенности относительно множества (то есть определить принадлежит ли множеству Vin). Далее за полиномиальное время проверяется, что |^л|</, число /такое, что (0</<£).
Определение 7. «Мёртвые» инструкции - это инструкции, которые относятся к вычислению несущественных переменных.
Из доказанного выше следует, что задача выявления мёртвого кода в программе, состоящей из одного базового блока, NP- полна, и, более того, не существует £-приближённого полиномиального алгоритма выявления мёртвого кода.
Переменные произвольных целых типов могут рассматриваться как набор переменных булева типа.
3.6 Практическое обоснование устойчивости метода
Устойчивость запутанной программы к автоматическому анализу обосновывается следующим:
- При статическом анализе массивов невозможно сделать анализ с точностью до каждого элемента массива. Следовательно, такой анализ окажется не эффективным.
Информация о работе Метод защиты программных средств на основе запутывающих преобразований