Статья: О некоторых задачах анализа и трансформации программ
Рис. 3. Пример эмулирования кэша
Для учета событий как временной, так и пространственной локальности необходимо моделирование линий кэша, т.е. помещение в кэш не одной переменной, а некоторого блока памяти, окружающего нужную переменную. Моделирование различных типов кэшей приведет к разным результатам при разделении на нити.
Пример моделирования событий локальности изображен на Рис. 3.
2.2. Экспериментальные результаты
Мы применили нашу реализацию алгоритма к тестовой функции, решающей алгебраическое уравнение четвертой степени x4+ax3+bx2+cx+d=0.
Функция не содержит циклов и не может быть распараллелена традиционными способами. Полученная многопоточная версия функции была реализована с помощью библиотеки pthread под операционной системой Linux. Экспериментальные запуски были проведены на четырехпроцессорном Intel Itanium, на которых установлена ОС RedHat Linux 7; использовались компиляторы GCC 3.3.1 и ICC 8.00b. Программа запускалась 100 раз, время ее выполнения измерялось с помощью высокоточных аппаратных счетчиков. Вычислялось среднее значение времени выполнения μ и среднеквадратичное отклонение σ. Все значения времени выполнения, не укладывающиеся в промежуток [μ-2σ,μ+2σ] удалялись из выборки, после чего среднее значение пересчитывалось. Эта величина использовалась для подсчета ускорения. Результаты эксперимента приведены на Рис. 4.
Рис. 4. Ускорение, достигнутое на Itanium
3. Маскирующие преобразования программ
Другим направлением, развиваемым в рамках IRE является исследование маскировки (obfuscation) программ. Мы рассматриваем проблему защиты программ от обратной инженерии, проводимой с целью модификации и/или включения фрагментов защищаемой программы во вновь разрабатываемый программный код. Защита в данном случае состоит в том, чтобы затруднить понимание деталей реализации компонент большой программной системы, сделав его настолько дорогим, чтобы дешевле было разработать оригинальное программное обеспечение.
Одним из способов такой защиты является маскировка программ, заклю-чающаяся в применении к исходному тексту программы цепочки маски-рующих преобразований, то есть преобразований, сохраняющих реализуемую программой функцию (являющихся функционально эквивалентными), но затрудняющих понимание этой функции.
Целью нашего исследования является новый метод маскировки программ, удовлетворяющего следующим требованиям:
Исходная и замаскированная программа записаны на языке Си.
В методе применяются цепочки маскирующих преобразований, элементы которых берутся из некоторого заранее зафиксированного множества параметризованных маскирующих преобра-зований.
Все цепочки таких преобразований порождаются автоматически поддерживающими метод инструментальными средствами и являются допустимыми по своим характеристикам, то есть уве-личивают размер маскируемой программы и/или уменьшают скорость её работы не более чем в фиксированное количество раз.
Метод маскировки устойчив относительно современных методов ста-тического и полустатического анализа программ, развитых для языка Си.
Предложена новая методология анализа маскирующих преобразований, которая позволяет давать качественную и количественную характеристику преобразований. Количественная характеристика преобразований позволяет дать их классификацию и выявить среди них наиболее подходящие для использования при маскировке программ. Основываясь на проведённом исследовании нами предложен новый метод маскировки программ, который удовлетворяет всем целям, сформулированным выше.
3.1. Методология анализа маскирующих преобразований программ
Для оценки действия маскирующих преобразований на программу мы используем несколько показателей сложности кода программ. Традиционно, подобного рода показатели называются "метрики", в дальнейшем мы будем придерживаться этого термина и в нашей работе. Метрики сложности кода программы ставят в соответствие любой программе некоторое число, которое тем больше, чем "сложнее" программа. Простейшая метрика LC размера процедуры равна количеству инструкций промежуточного представления MIF в записи процедуры. Метрика YC сложности циклической структуры равна мощности транзитивного замыкания отношения достижимости в графе потока управления процедуры. Метрика DC сложности потока данных определяется как количество дуг в графе зависимостей по данным, строящемся по результатам анализа достигающих определений программы. Метрика UC количества недостижимого кода определяется как количество инструкций в программе, которые не выполняются ни при каких наборах входных данных. Известно, что точное вычисление метрик DC и UC является алгоритмически неразрешимой задачей.
Через O(p,e) мы обозначим применение метода маскировки O к программе p. e - это параметр, который позволяет выбрать единственную программу p' = O(p,e) из множества функционально эквивалентных замаскированных программ O(p). В частности, параметр e может быть случайным числом. Множество изменения параметра e обозначим через E. Тогда LC(p) - значение метрики LC до маскировки, а LC(O(p,e)) - после маскировки.
Композитная метрика цены TC преобразования O(p,e) вычисляется по метрикам LC и UC следующим образом:
Для конечного множества D программ цена маскирующего преобразования определяется как .
Метод маскировки называется допустимым для множества D, если , где константа TCMAX устанавливается директивно, исходя из эксплуатационных требований к замаскированной программе.
Композитная метрика MC усложнения программы вычисляется по метрикам YC и DC следующим образом:
Для конечного множества D программ усложнение определяется как . Чем больше метрика усложнения программы, тем сложнее для понимания становится замаскированная программа в силу увеличения числа информационных и управляющих связей.
Для оценки сложности самого маскирующего преобразования вводится оценка OC сложности маскирующего преобразования, которая определяется как требуемая для выполнения данного маскирующего преобразования глубина анализа программы согласно таблице 1.
Требуемая глубина анализа | Значение OC |
Лексический анализ | 0 |
Синтаксический анализ | 1 |
Семантический анализ | 2 |
Анализ потока управления | 3 |
Консервативный анализ потока данных | 4 |
Полустатический анализ | 5 |
Точный анализ потока данных | 6 |
Таблица 1. Шкала оценки сложности маскирующих преобразований
Для оценки степени различия текстов программ вводится расстояние ρ(p1,p2) между текстами программ p1 и p2, которое используется для оценки устойчивости маскирующего преобразования. Введём расстояние ρC между графами потока управления двух процедур, равное минимальному количеству операций удаления и добавления рёбер и дуг, переводящих один граф в граф, изоморфный другому. Аналогично введём расстояние ρD между графами зависимостей по данным двух процедур. Обозначим через ρCD(f1,f2) сумму ρC(f1,f2)+ρD(f1,f2). Тогда расстояние ρ(p1,p2) вычисляется по формуле
Здесь минимум берётся по всевозможным множествам M, состоящим из пар (f1,f2), где f1 - процедура из программы p1, f2 - процедура из программы p2. Все процедуры f1 и f2 встречаются в M не более одного раза. Через M1 обозначено множество процедур программы p1, отсутствующих в M, а через M2 - множество процедур программы p2, отсутствующих в M. E - это пустой граф.