О проблеме логико-термальной эквивалентности последовательных программ с динамической памятью
В. А. Захаров. К. С. Иванов
Аннотация. Некоторые методы обфускации программ предусматривают использование аппарата указателей. Это обусловлено тем. что задача анализа программ, в которых используются указатели, относится к числу алгоритмически трудных задач. Для разработки методов анализа программ, использующих динамическую намять, целесообразно ввести и исследовать строгую математическую модель, которая могла бы позволить проводить доказательство корректности полученных алгоритмов, оценивать их сложность и описывать с ее помощью обфускирующие и деобфускирующие преобразования.
В предложенной работе предпринята попытка создать такую модель на основе известной модели стандартных схем программ. В статье рассматривается расширенный вариант стандартных схем программ, обогащенных средствами работы с указателями и динамической памятью. Для предложенной модели рассмотрена задача проверки логико-термальной эквиавлентности, которая ранее была исследована для обычных стандартных схем программ. Показано, что проблема логико-термальной эквивалентности для схем программ с динамической памятью разрешима за полиномиальное время.
1. Введение
Развитие скрипт-языков (Perl. РНР. JavaScript. VBScript), внедрение программных окружений (Java. Microsoft.NET) поставили перед разработчиками новую задачу: защищать от несанкционированного использования и плагиата свои программы. Особенность этих задач для подобных платформ заключается в том. что распространяемый код зачастую является ^откомпилированным, или же откомпилированным в форму, из которой легко извлекается исходный код на высокоуровневом языке. Таким образом становится трудно защитить не столько саму программу, сколько лицензированные алгоритмы, используемые в ней. Поэтому необходимо самим защищать. или подписывать свой код . Иногда это позволяет крупным компаниям выделять направления утечки данных и прекращать сотрудничество с дилерами, пиратирующими их продукцию.
Одной из развивающихся областей в защите информации является об-фускация — эквивалентные преобразования кода программ, как исходного. так и откомпилированного, в форму менее понятную для человека и
автоматического анализатора. В идеале после применения методов обфус-кации программа должна быть абсолютно непонятной, т.е. из нее нельзя извлечь полезной информации (обычно рассматриваются определенные классы свойств). При этом функциональное поведение программы должно сохраняться. Одно из самых крупных исследований таких преобразований провел Wroblewski [а]. В работе [а] выделены все атомарные преобразования над программами, показана эффективность обфускации, проведен ряд статистических исследований.
Доказано [12], что универсального обфускатора не существует. Однако. в частных случаях можно строить эффективные преобразования. Одними из первых разработчиков методов обфускации являются Collberg и Thomborson [3. 4|. Стоит заметить, что в их работах используются структуры. хранящиеся в динамической памяти. На основе подобных структур, сложность анализа которых высока, строятся предикаты тина: указывает ли одна переменная туда же, куда и другая. Использование аппарата указателей является одним из мощнейших инструментов запутывания кода программ.
Однако, существует ряд алгоритмов анализа (Steensgaard [9], Shapiro and Horwitz [10], Andersen [8], Hind [11]), направленных на исследование диапазонов значений переменных-указателей. Первые три алгоритма являются нечувствительными к потоку управления и контексту. Множества, получаемые в результате их работы, действительны для всей программы в целом. Такие алгоритмы не учитывают порядок операций в программе. За счет этого существенно повышается скорость анализа программы, но снижается точность анализа. Тем не менее, такой анализ позволяет получить представление о структурах в динамической памяти программы. Четвертый алгоритм (Hind) является чувствительным как к потоку, так и к контексту. Его результат берется в определенной точки программы для определенной переменной. Анализ учитывает практически все особенности программы, длится существенно дольше, чем у предыдущих алгоритмов, но и результат получается высокой степени точности.
Такие алгоритмы могут выделять множества, на которые ссылаются указатели. Благодаря этому возможно избавиться от не влияющих на код указателей и конструкций в динамической памяти. Хотя и доказано, что полный точный анализ указателей является NP-трудным [6], в программах часто встречаются простые и разрешимые случаи. А иногда не обязательно исследовать все указатели, достаточно лишь выделить некоторые необходимые множества.
Основным подходом в обфускации является сложностной подход, когда выяснить какое-либо свойство программы можно, решив сложную (NP-
трудную) задачу. Но специалист может выделить частный случай задачи, проанализировать ее. воспользоваться опытом и либо решить ее реализацию. либо обойти поставленную задачу и в итоге получить полезную информацию о свойстве программы. Поэтому был рассмотрен вопрос о целесообразности постановки именно сложных задач перед алгоритмами анализа. Оказалось, что можно поступить иначе. Был введен новый подход к обфускации [7|. Его основная идея состоит в том. чтобы сводить к минимуму полезную информацию, которая может быть извлечена из программы применением алгоритмов анализа. Оценка осуществляется относительно существующих алгоритмов анализа. В случае анализа диапазона указателей минимизировать полезность можно, если все указатели но результатам анализа будут ссылаться на одно, общее множество адресов. В работе [7] так же был представлен алгоритм для минимизации полезности применения алгоритмов из [9|,[10|,[8|.
Во всех перечисленных работах каждый раз используется свое представление программ, что затрудняет доказательство применимости алгоритмов обфускации. Более того, чтобы ввести эквивалентные преобразования программ в рамках обфускации. необходимо доказать их эквивалентность, что требует наличия сформулированного понятия эквивалентности, а также распознающих ее алгоритмов.
При разработке методов обфускации (маскировки) программ требуется обоснование стойкости этих методов относительно анализа программ. Однако, ни в одной работе не приводится строгого обоснования стойкости этих методов. В значительной части это обусловлено отсутствием такой же корректной постановки работы алгоритмов анализа, а так же критериев стойкости методов обфускации.
Проблемы с корректностью описания связаны с отсутствием формальных моделей программ, для которых было бы удобно провести корректное обоснование. Поэтому первый этан в исследовании и обосновании методов и критериев обфускации — создание адекватной модели. В свою очередь алгоритмы распознавания эквивалентности необходимо строить на основе некоторой математической модели программ. Наличие в преобразованиях динамической памяти требует описание ее в модели. Были проведены поиски подходящей модели, но положительного результата они не дали. На сегодняшний день языковые модели ограничиваются лишь спецификациями. меняющимися от реализации к реализации. Что касается формальных моделей, абстрагированных от реализации, большинство из них строятся на базе Abstract State Machines. Одна из таких моделей описана Замулиным в работе [2|. Это направление исследований представляется перспективным для построения новых алгоритмов верификации моделей программ.
Тем не менее авторами настоящей статьи была предпринята попытка создать собственную модель с динамической памятью, которая:
• приближала бы в некотором роде современные языки программирования.
• имела строгое математическое описание.
• просто описывала операции над динамической памятью.
Такая модель описывается в разделе 2 в качестве расширения стандартных схем программ, полностью математически описанных в [1|.
Функциональная эквивалентность стандартных схем программ неразрешима [1|. поэтому следует искать такие отношения эквивалентности, которые служили бы более грубым приближением функциональной экивав-лентности. Примером такой эквивалентности является логико-термальная эквивалентность программ. Для программ без ветвлений и циклов она полностью совпадает с функциональной. А для остальных программ из логико-термальной эквивалентности следует функциональная. Обратное, вообще говоря, не верно. Поэтому в этой работе и исследуется разрешимость логико-термальной эквивалентности для программ с динамической памятью. На этой базе уже будет возможно создавать эквивалентные преобразования.
Логико-термальная эквивалентность важна еще но следующей причине. Для обфускации и в задачах анализа программ необходимо оценивать схожесть поведения программ. Например, при анализе метаморфных вирусов. Каждый такой вирус имеет автоматный шаблон своего кода. При попадании на конкретную машину он автоматически подставляет вместо шаблонных переменных некоторые машинно-зависимые конструкции. Необходимо уметь распознавать такие шаблоны и сличать их с уже сделанной подстановкой.
В разделах 4 и 5 исследуется проблема разрешимости логико-термаль-ной эквивалентности при наличии динамической памяти.
2. Модель программ с динамической памятью
Определение 1. Множеством термов сигнатуры £ (Тегпг^) называется наименьшее множество, содержащее все слова алфавита Е.
Для определения структуры и функционирования программ, рассматриваемых в дальнейшим, будем пользоваться схемами программ.
Определение 2. Под схемой модели программ 5 в базисе операторов 2 сигнатуры, £ буде,м понимать конечный размеченный ориентированный граф, вершины которого имеют: 5 типов:
1. Начальная вершина. В схеме имеется ровно одна начальная вершина, помеченная начальным оператором из Z. Она имеет, одну исходящую дугу и ни одной входящей.
2. Заключительная вершина. Схема может, иметь несколько заключительных вершин, помеченных заключительным оператором. Из вершин, этого типа не исходит, ни одной, дуги.
3. Вершина-нреобразователь. Вершина этого типа помечена преобразующим оператором и имеет, одну исходящую дугу.
4- Вершина-распознаватель. Данная вершина помечена некоторым am,омом сигнатуры, S и, имеет, две исходящие дуги, намеченные как И и Л(в соответствие истинности, и ложности рассматриваемого am,ома).
5. Пустой цикл. Специальный, вид распознавателя, с обеими, исходящими дугами, направленными, на вход этому же оператору.
Определим модель с динамической памятью (далее МДП). Сигнатура £ состоит из следующих ненересекающихся множеств:
• Vаг = {.ті,..., ж,,} — множество предметных переменных.
• Func = ■ ■ ■, fmт\I — множество функциональных
символов. Верхние индексы ki задают арность (местность) символа.
• Precl = • • • iPr ^ j — множество предикатных символов (отно-
шений). Верхний индекс задаёт местность отношения.
• Const = {сі,..., с;, _L} — множество констант.
• ли nil — множество всех адресных имен (Л — счетное).
Замечание 1. Дополнительно будем рассматривать следующие множества: X = Var, AJ- = {*,&}. J- = (Func \ AJ-) U Const, AJ~{X) = /.../(ж).
/ Є АТ, х Є X, і > 0.
Теперь можно построить терм над сигнатурой £ (но определению). Далее будут рассматриваться термы только над этим множеством.
Определим базис операторов Z для модели программы:
• Начальный, оператор — staH(xi, ...,Xk), где к > 0. а х\,..., хи — попарно различные переменные, называемые результатом этого оператора.
• Заключительный оператор — stop(r\,..., тп). где п > 0. a 7i,.. ., т„ — термы(аргументы stop).
• Оператор присваивания — ж := т, где ж, т € Terms-
• Атом — pf’Vi, ■■■,Tki), где € Pred, ть ..., rfcj е Terms-
• Оператор выделения памяти — new(xi). где ж,; € Terms
Определение 3. Интерпретацией сигнатуры. £ называется функция I, которая сопоставляет:
• любой константе 1(c) = d, d € Dj, где Dj — конечная статическая область интерпретации;
• любому адресу 1(a) = d, d € Mi, где Mi — конечная динамическая область интерпретации;
• функциональным символам вида € Func — отображение:
I (if0) = P/fci) : - Dj
• предикатным символам p^1^ всюду определенный предикат,
1 (р?}) = Pjh) : D(T) U MiS) -> №
r Js 0, s Js 0, lj ^ 0, r + s = lj
• функциональным символам * и & — функциональные операторы *ф и & 0, зависящие от состояния памяти.
Определение 4. Пара (S,I), где S — схема в базисе операторов Z сигнатуры £, а I — интерпретация сигнатуры. £, называется интерпретированной схемой или программой.
Определение 5. Состояние памяти г/> — это пара г/> = (М, (01,02)), где:
1. Адресное пространство М — некоторое конечное подмножество
МАМ с Mi);
2. Оценка — пара (cri, сг2), где о\ : Vаг —> М U _L, а2 : М —> М U Р/.
Заметим, что оценка <7i — биекция. Множество всех состояний — Ф. Следующие выражения для ж G Var,a G М можно интерпретировать как: 02(a) — значение но адрес)' a. 02(oi(x)) — значение ж.
Тогда каждый оператор интерпретируется как отображение одного состояния памяти в другое:
Ор : Ф -> Ф, Ф = {ф | ф = (М, (<Ti,<T2)}}
Далее определим значение Qф на состоянии памяти ф = (М, (tri, сг2)}:
1(т), т € Const V т € Л;
02(0-1(7-)), г € Far;
П,/,(т) = * (Г2(п)), г = * (ri);
& (Г2(п)), г = & (п);
Д/)№(п), ■ ■ .,Щтп)), т = /(п,... ,r„),/ € Prev U Func;
Теперь можно определить интерпретацию функциональных символов * и & на состояние памяти ф = (М, (01,02)}:
/(*) = *,/,
, ч f 02(ГЫт)), если ГЫт) € М
*ф(т) = \ ,
_L, иначе
/(&) =
_L, т € Const V г € Л;
o'!(г), г G Уаг;
^</>(п), г = *ri;
_L, иначе
Определим функционирование программы. До начала программы — состояние памяти фо определяется следующим образом:
^2
При переходе через начальную вершину с начальным оператором staH(x 1, ...,Xk) осуществляется следующие преобразование:
ф0 = (М°, (СГ?,СГ2)) —> V>1 = (М1, (crj,^1))
М1 = {а 1, ..., aft, m/}
л .
а,-, 1 г fc
Пусть далее мы приходим в вершину v схемы S с состоянием ф = (М, (сг1,сг2)), тогда возможны следующие случаи.
Если v — вершина-нреобразователь с оператором выделения памяти пеги(т) для к,ф(т) € М, тогда мы получим состояние памяти ф' = (М1, но следующему правилу:
М' = М U {а;}, а; € Mi \ М
{ nil, а = сц\
а;, а = а2(&ф(т));
(72(а), иначе.
Если же &ф(т) $ М, то ф' = ф. Далее осуществляется переход но единственной исходящей из v дуге с состоянием памяти ф'.
Если v — вершина-нреобразователь с оператором присваивания вида П := т2, тогда:
1. новое состояние определяется как Ф' = где
02(a), а ф &^,(п)
МфЫ), а = &£ф(т1)
Осуществляется переход но единственной исходящей из v дуге с состоянием памяти ф'.
Если v — вершина-раснознаватель с атомом pj(ti, , п}). то происходит переход но дуге, соответствующей значению этого атома на аргументах 71,.. ., 7}. € Di U М. Состояние памяти при переходе сохраняется.
Если v — заключительная вершина с оператором output{x 1,..., xm). тогда ф' = (А1, определяется следующим образом:
X ^ СГ2 (01 (ж)) — значение переменной X
01 01 I {л’1,. }
02 = 02 \м>
М'= ( и К(х)}и у
\x£Di жЕМ
После достижения заключительной вершины программа считается завершенной в состоянии ф'.
Определение 6. Фрагментам, МДП назовем некоторое обобщение схемы МДП. В отличие от графа схемы, граф фрагмента .может, содержать
ОО \
им*)}) \Di
свободные дуги (входы и выходы), но они должны быть уникально пронумерованы. Кроме того свободным дугам приписаны конечные множества термов (результаты входа и аргументы выхода соответственно).
Подробно свойства фрагментов описаны в [1. гл. 6|.
3. Свойства модели программ с динамической памятью
Введем несколько определений, которые понадобятся в данном разделе.
Определение 7. Стандартные схемы и во, в базисе операторов Z сигнатуры, Е функционально эквивалентны (5х ~ £2), если для любой интерпретации I сигнатуры, Е программы (61,/) и (б'гД) либо обе зацикливаются либо останавливаются с одинаковым результатом, т.е.
Можно показать, что введённая в разделе 2 МДП является расширением модели, описанной в [1|. Для этого рассмотрим статические программы (без использования динамической памяти и адресов). Тогда в МДП получим не использование оператора пеги и функциональных символов &. *.
Теорема 1 (о консервативном расширении). МДП является консервативным расширением стандартной .модели, схем программ, т.е. в классе статических программ каждой, вычислительной истории схемы, программы из стандартной .модели, схем программ (далее СМ СП) .можно взаимнооднозначно (с точностью до перенумерации адресов переменных) сопоставить вычислительную историю хо, схемы, во, .модели, МДП.
Следствие 1. Функциональная эквивалентноеть статических программ из СМСП верна и для МДП.
Следствие 2. Проблема функциональной, эквивалентноеть схем МДП неразрешима.
Введем понятия значения терма на пути, а также логико-термальной истории. Обозначим за г>/(«>,<) значение терма t на пути ги.
ад,л~П(52,л.
Угу :
г’Цги, &ж)
г>1 {ги, /(*!,...,*„))
/ (г>/(ы;,£ 1),... ,г>1{ги, tn)), если г’1{ги,^) ^ Ли {_!_} _1_. иначе
г’1(го,х), если г>/(гу,£х) = ах г>/(гу, *£х) = ^ г>1(го,*(а)), если г>/(гу,£х) = а _1_, иначе
а(1(1г(£) = аХ1,..., аХп , аЖ; € Л Л ж,; € Уаг асМг(гу.(ж :=£}) = а(1(1г(ги)
й £ Л
ас1с1г(г_о.(пе1о(х))) = а(1(1г(г_о) и {а}, а :
г’/(г, ж) = ж г’/(г, *ж) = _1_
г>1(го.(х :=£},ж) = г>/(гу, £) г>1(го.(х :=£},г/) = г>/(гу, г/)
г>1(го^.2). если г>/(гу, £х) = аж г?/(го, ж), иначе
г>/(гу.(*£х = £2)1 ж) =
1’1(ги.(пеги(ж)}, ж) = а :
([ Е Л
а ^ а(1(1г(ги) 1’1(ги.(пеги(у)),х) = г>1(го, ж).
Для пути гу в некоторой схеме 5 определим логико-термальную историю Щв, го) как слово, которое строится следующим образом:
1. Если путь гу не содержит распознавателей и заключительной вершины, то Й(5, «>) — нустое слово.
2. Если гу = м/г>е, где г» — распознаватель с атомом р^(тх,... ,7^), а е — выходящая из него (5-дуга, (5 (={-0, Д}, то
Н (Б, го) = И(Б,го')р? (г>1(го', тг),..., г’1(го', тк} )) .
3. Если гу = го'гк где V — заключительная вершина с оператором в^ор(жх,... ,жк), то
/£(5, го) = Н(3,го') [г>/(ы/,жх), • • •, г>/(ы/, ж^)] .
Определение 8. Детерминантом (5' — стандартной схемы 5 на-
зовём множество логико-термальных историй всех ее путей, завершающихся з аключительным оператором.
Определение 9. Схемы и называются логико-термально эквивалентными ~ б'г), если с1еЦ81) = с2е£(52).
4. Сети инвариантов
С каждым путём ги, оканчивающимся дугой е фрагмента С можно связать множество равенства термов:
деп{С,ги) = {х = т | 1>1(ги,х) = г>1(ги,т), х ф _1_}
Будем говорить, что множество деп{С,ги) порождается путём го.
Определение 10. Инвариантом дуги, е из С назовём множество равенств:
гпг’аг'(С, е) = [^| деп(С, го)
и)£\¥е
Где \\Те — множество всех путей, начинающихся входами фрагмента С
и, оканчивающихся дугой, е.
Определение 11. Функциональная сеть — это чет,верка в = (С, V, Ф,Г), где:
С — конечное множество сигнатурных элементов.
V — конечное множество вершин. V = {г>}. Вершина V = {с} — конечное множество элементов с € С
Ф — функция означивания. Ф : С —> X и Т и АТ и А
Г — отображение зависимости. Г : С х N —> V. Г(с, г) — обозначает зависимость элемента с : Ф(с) € Т и АР по аргументу г. Количество дуг из элемент,а определяется арностью функционального символа и, обозначается с£(Ф(с)).
Определение 12. Полунравильной сетью назовём сеть, удовлетворяющую следующим условиям:
1. Каждая вершина содержит, не более одного элемент,а с, которому приписан функциональным символ СФ(с) € Т);
2. В сети нет, элементов-дублей,, т. е. не существует, таких различных элементов сх и, с2, для которых:
Ф(сх) = Ф(с2) А V?’ [(1 < г < с/(Ф(сх))) А Г(сх, г) = Г(с2,*)]
Определим далее множества knows (с) и knows(v):
{{д}, если Ф(с) = д Л d(g) = О {fin, ...,тп) | Vi (1 s' г s' п) Ti е knoius (Г(с, г))}, если Ф(с) = / Л d(f) = п > О
knowsiv) = У knowsic)
c£v
Отметим, что множества в общем случае — счетно-бесконечные, так как в сети возможны циклы но элементам из АТ.
Определение 13. Множеством равенств сети s назовём:
asseri-is) = и {п = т2 | (тьт2 € knowsiv)) Л (n € ATiX))}
vEV
Определение 14. Назовём сеть приведенной, если она не содержит:
• забытых вершин, т.е. вершин не содержащих ни одного элемента;
• недоступных вершин, т.е. вершин, входящих в компоненты связности графа сети, которые не содержат, переменных;
• некорректных связей, т.е. цепей по элементам с : Ф(с) € АТ, не оканчивающихся переменными (адресными термами).
Определение 15. Сети s и s' называются равными, если существует, биективное отображение ID :VS —>VS/, а т,акже биективные отображения idv : v —> IDiv),Vv € Vs т,акие, что:
Vv е Vs,Ус е v : Ф3/ iidvic)) = Ф8(с) Л V* Г8/ iidvic), i) = ID {Ts{c,i))
Обозначим через О сеть с Vq = 0
Пусть у нас есть две сети s = (С, V, Ф, Г), s' = (С', V', Ф', Г'}, определим произведение сетей s х s' = (С", V", Ф", Г"}:
• V" = V х V' — декартово произведение множеств вершин.
iv, v') = {(с, с') I с е V, с' е v', Ф(с) = Ф(с')} .
• С” = {с\с € V,v € V"}
. Ф"((с,с')) = Ф(с)
• Г"((с, с'), г) = (Г(с, г), Vid, i)) Vi (1 < г < d($(c)))
Лемма 1 (О приведенной сети). По всякой сет/и в .можно построить приведенную сеть ге(1(я) тлкую, чт,о аз8еН(з) = аз8еН(гес1(8)).
Лемма 2 (О сужении знания вершин). Для любых двух приведенных сетей в = ив' = (С8>,Уа>,'IV,IV) верно, чтоУи е У,\/г/ € У'
кпо1и8Х8/((1>,1>')) = кпоги8(г’) П кпо1и8/(г>').
Лемма 3 (Единственность приведенной сети). Для приведенных сетей в = в' О аз8еН(з) = аз8еН(8')
Определим операцию пересечения двух приведенных сетей:
в П в' = гес1(8 X в')
Лемма 4 (О пересечении приведенный сетей). Для двух приведенных сетей в и в' справедливо следующее утверждение:
аввеН^в П в') = аз8еН(з) П а88еН(з')
Введем понятие веса сети.
Определение 16. Весом сет,и в назовем пару о>(в) = (к\, к^), где:
кг = 2е \ + — Ь — Ь
к‘2 = 1р*
е\ — количество элементов-переменных сети в, елр — количество элементов из АТ сети в, 1р — количество вершин с элементами из Т сети в, 1р* — количество вершин сети в, имеющих элементы — а т,акже элементы из Т и А, Ь — количество вершин сети в, имеющих хотя бы один элемент-переменную, /2 — количество вершин сети в, у которых все элементы — переменные. Порядок весов — обратный лексикографический.
Лемма 5 (О монотонном убывании веса). Для приведенных сетей в и в' верно, чт,о
^ тгп(и}(8),и}(з'))
Теорема 2. Множество приведенных сетей вместе с операцией пересечения образует ограниченную полурешетку.
Обозначим через £ множество приведенных сетей. Дополним его искусственным элементом I. для которого положим но определению \/в € С : вП1 = 1Пв = в. Получаем ограниченную нолурешетку (£, П).
Определим операцию асЫ, которая но сети в и терму т строит сеть ас1с1(8,т), в которой есть вершина, знающая т. Пусть в = I или сеть в уже содержит вершину, знающую терм т. положим тогда а<М{8, т) = в.
В противном случае пусть т = /(п,..., т„), п ;г 0,/ € X и Т и АГ. Построим тогда сети во = в, в,: = асМ(в,:_1, х,;), г = 1, ... п и нолучим аскЦв, т) из сети 8п добавлением новой вершины V с единственным элементом с. для которого мы полагаем ф(с) = /, V* (1 < г < п) Г(с, г) = щ, где щ — вершина, знающая терм 7,.
Замечание 2. Отдельно рассмотрим случай с термами вида &Тх. Если Т\ € X, то в сеть добавляется вершина, знающая терм ах. Это не противоречит определению оператора &. Если т\ имеет вид *72. то рекурсивно переходим к операции асМ(в, т2). В остальных случаях добавляется терм _1_.
Определим операцию эффект присваивания (ЭП). По заданному оператору присваивания (т\ := т2) и сети в строим сеть (т\ := т2)в. Положим (т! := т2)I = I. Для в / I сеть преобразуется в зависимости от т\. Пусть 71 € Х(тх = х). тогда:
1. Сеть «1 получается из сети сиШ(8,т2) добавлением в вершину, знающую 72 элемента с, ФЛ| (с) = где г — переменная, не встречающаяся в ас1с1(8, т2).
2. Сеть 82 строится из сети «1 .удалением элемента с. для которого Ф81(с) = х.
3. Сеть зз выводится из сети 82 заменой функции означивания для элемента с с Ф82(с) = ~ на Ф3з(с) = х.
Пусть теперь т\ =t(тз),t е АТ, тогда:
1. Сеть «1 получается из сети сиШ(8,т2) добавлением в вершину, знающую 72 элемента с, ФЛ| (с) = где г — переменная, не встречающаяся В ас1с1(8, 72 ).
2. Сеть 82 строится ИЗ сети в' = а<М(81,Т1) .удалением элемента с из вершины, знающей т\, для которого Ф8/(с) = t и Г(с, 1) = V, где
V — вершина, знающая терм 73.
3. Сеть зз выводится из сети 82 заменой функции означивания для элемента с с Фв2(с) = г на Фвз (с) = t■ а также добавлением зависимости для элемента с : Г(с, 1) = V, где V — вершина, знающая терм 73.
В обоих случаях сеть (71 := 72}в = гесЦв3).
Определим операцию эффект выделения памяти (ЭВП). По заданному оператору (пеги(т)) и сети в строим сеть (пеги (т)) 8. Положим (пеги(т))1 = I. Для в ф I сеть преобразуется в зависимости от т.
1. Сеть «1 получается из сети 8 добавлением новой вершины г’пеш, с элементом с, Ф(с) = а, а — адресная константа, соответствующая функционированию оператора пеги.
2. Сеть в2 строится из сети ас1с1(81, _1_) добавлением в вершин)', знающую _1_ элемента с, Ф(с) = *, Г(с, 1) = г’пеш.
3. Далее возможны два случая:
(a) т € X, тогда сеть в3 выводится из сети в2 переносом элемента с, для которого Ф(с) = х из его вершины В 1’пеш.
(b) т = *(т'), тогда сеть вз получается из в' = аскЦв2, т) переносом элемента с из вершины, знающей т. для которого ф(с) = * в вершину ипеш.
4. Сеть (пеги(т))8 = гес1(8з)
Лемма 6 (О дистрибутивности операций).
Лемма Т. Пусть в Є С идеп(Є, ги') = аз8еН(з) для пути ги' во фрагменте С. Тогда деп{С,ги) = аззеН((ті := т2),в) для пути ги = її/Ае, где А — оператор присваивания ті := т2.
Лемма 8. Пусть в Є С идеп(Є, їй') = аз8еН(з) для пути ги' во фрагменте С. Тогда деп(Є,ги) = аззеН((пеіи(т)), в) для пути IV = ги'Ае, где А — оператор присваивания пего(т).
Рассмотрим задачу глобального анализа. Подробно задача и методы её решения описаны в [1, гл. 2|. Выделим следующее справедливое утверждение.
Теорема 3. Если в окружении для анализа все преобразования свойств — дистрибутивны, то стационарная разметка цс дает, точное, единственное решение задачи глобального анализа, т.е.:
Теперь можно сформулировать задачу глобального анализа фрагмента
С. В качестве окружения для анализа возьмём (£, П,_Р). где содержит все операции ЭП и ЭВП для соответствующих операторов фрагмента С, а так же функции Цз) = в и І(в) = I.
\/ві,в2 Є £,Ут, ті Є АТ{Х)Ат2 Є Тегпі£ : (пеги(т)) (ві П в2) = ((пеги(т))ві) П ((пеги(т))з2), (п := т2) (ві П в2) = ((п := Т2)«і) П ((п := т2).з2) •
(1)
(2)
\/е Є Е : /хс(е) = Н(е)
Семантик)' /| (функцию перехода вершину между дугами е' и е) определим следующим образом:
{(т\ := 72}в, е' ведёт к оператору т\ := 75, а е выходит из него. (?гегу(г))в, е' ведёт к оператору пеги(т). а е выходит из него. *(в), е ведет к распознавателю, а е выходит из него.
1(в), в остальных случаях.
Для входа е с результатами {хх,... ,хп} строим зе — сеть, содержащую п вершин, каждая из которых содержит один элемент с* € 1Ц, Ф8(,(с*) = ж,;. (1 < * < п). В качестве начальной разметки /*о(е) = зе для входов е фрагмента С и /*0(е) = I для остальных дуг. Тогда из теоремы 2 и лемм 6. 7. 8 следует
Теорема 4. Для стационарной разметки ц, сформулированной задачи глобального анализа, и для всех дуг е фрагмента С
тг’аг(С, е) = аввег^/у^е)).
5. Алгоритм распознавания
логико-термальной эквивалентности
Введем систему преобразований фрагментов Ац.
Т1 Удаление недостижимых. Фрагмент, не имеющий входов, равносилен пустому фрагменту.
Т2 Стягивание тупиков. Фрагмент, без выходов и без заключительных операторов, с номерами входов ах,, ап равносилен нетле со входными дугами — входами ах,..., а„.
ТЗ Склеивание копий, копирование. Возьмем разбиение множества вершин фрагмента С на непустые, ненересекающиеся классы К\,, Кп удовлетворяющие следующим свойствам:
1. каждый класс содержит графически совпадающие операторы:
2. если некоторая выходная дуга вершины класса К< ведет к вершине класса Ку. то соответствующие выходные дуги всех других вершин класса Кг так же ведут к вершинам класса К у,
3. если некоторая выходная дуга вершины класса К< является выходом фрагмента С с номером Ь, то соответствующие выходные дуги всех других вершин класса К\ — также выходы фрагмента С с номером Ь.
Пусть фрагмент С может быть получен из С следующим образом: из каждого класса К{(г = 1,..., п) берется ровно но одной вершине гц, и дуга от нее либо проводится к вершине г>$ (условие 2), либо объявляется выходом С с номером Ь (условие 3). Если в С имеется вход с номером а, ведущий к вершине класса Кг, то к С добавляется вход с номером а, который направляется к вершине гу. При перечисленных условиях С <-> С
Т4 Замена переменных. Пусть переменные х и у фрагмента С не зацеплены. т.е. не существует дуги фрагмента С, чтобы обе эти переменные входили в сеть инвариантов, приписанных этой дуге. А также ни одно из вхождений переменной х не является результатом входа или аргументом выхода. Тогда С <-> С, где С — фрагмент, получающийся из С заменой всех вхождений х в компоненту Г на переменную У■
Т5 Удаление неиспользуемых преобразователей. Пусть {г>*}”=1 — такое подмножество преобразователей фрагмента С, что к вершине гц ведет ровно одна дуга и вершина щ не влияет ни на один из выходов фрагмента С, а так же ни на одну из вершин, отличных от г>1,... ,г»„. Фрагмент С получается из С заменой каждого преобразователя гц(г = 1,..., п) на дугу:
&г
Ъг
Тогда С <-► С'
Тб Удаление неиспользуемого результата входа. Если результат х € ЛТ{Х) входа е фрагмента С не влияет на его вершины и выходы, то в С, где фрагмент С получается исключением х из множества результатов входа е.
ТТ Удаление вырожденной пересылки. Если х Є АТ{Х) П , то
а а
(и)
х := х
Ъ Ъ
Т8 Замена термов. Пусть инварианты всех дуг. ведущих к вершине г> во фрагменте С, содержат равенство ті = т2. Тогда С <-> С', где С получается из С заменой терма Т\ на т2.
Теорема 5. Сі ^ С2 => ~ С2
Определение 17. Фрагмент, С называется приведенным, если для него выполнены следующие условия:
Л,1 Каждая вершина фрагмента С лежит, хотя бы на одном пути, начинающимся входом фрагмента С.
ІІ 2 От каждой вершины фрагмента С (кроме операторов петли) имеется хотя бы один путь к выходу из С или к заключительному оператору.
КЗ К каждому преобразователю, заключительному оператору или оператору петли ведет, ровно одна дуга фрагмента С.
Щ В качестве функциональных подтермов в атомах и заключительных операторах фрагмента С используются только переменные.
Лемма 9. Применением правил Т1 — ТЗ, Т5, Т8 всякий фрагмент, можно преобразовать в приведенный.
Определение 18. Линейным участком (лучом) называется всякий приведенный фрагмент, без распознавателей и ровно с одним входом.
Определение 19. Выходным лучом приведенного фрагмента С называется вхождение в С всякого .максимального луча, кончающегося выходом фрагмента С.
Со всяким приведенным фрагментом С свяжем его логический граф (л-граф) ЬС(С), который получается из С следующим образом:
каждый преобразователь а —>| у |—> Ь заменяется фрагментом-дугой а —> Ь, после чего .удаляются аргументы вершин и выходов, а также результаты входов.
С каждой конечной цепочкой ги в л-графе (путем от входа к выходу или к заключительной вершине) свяжем слово, которое получается последовательным выписыванием номеров свободных дуг. а так же символов. приписанных вершинам цепочки IV. При этом предикатный символ берется со знаком 6(6 € {0,1}). если путь продолжается но (5-дуге некоторого распознавателя. Множество слов, построенных таким образом во но всем конечным цепочкам л-графа, называется языком л-графа. Два л-графа называются автоматно-эквивалентными, если их языки совпадают. Два приведенных фрагмента называются подобными, если их л-графы автоматно-эквивалентны. Из приведенных определений следует, что всякие /^-эквивалентные фрагменты являются подобными. Отношение подобия в точности соответствует эквивалентности одноленточных автоматов. Для распознавания эквивалентности двух л-графов достаточно применить алгоритм Мура распознавания эквивалентности одноленточных автоматов.
Пара приведенных фрагментов С\,Со, называется согласованной, если для нее выполнены следующие условия:
С1 Множества результатов входов с одинаковыми номерами совпадают
С2 Всякий выходной луч в С\ и завершается так называемым выходным вектором пересылок, т.е. лучом
Х2 ■= у2
•— Уп
где {xi,... ,хп} — множество всех аргументов выхода с номером j, а также V*(l < і < п) Уі $ {xi,..., хп}.
СЗ Если некоторая переменная х встречается в каждом из фрагментов нары, то преобразователи с результатом х имеются только внутри выходных векторов пересылок этих фрагментов.
С4 Логические графы фрагментов Gі и Go, совпадают.
Теорема 6. Применением правил из Д<{ всякую пару It-эквивалентных фрагментов можно преобразовать в согласованную пару.
Теорема 7. Система Ац — полная система It-эквивалентных преобразований фрагментов, т.е.
Git п і.
1 02 w *--> 02
Доказательство. С учетом теорем 5 и 6 достаточно показать Gi G-i для фрагментов G\, Go,, G\ ~ Go,, составляющих согласованную пару.
Обозначим через Л:(е) луч, начинающийся 6-дугой е распознавателя или входом е во фрагменте (?<(* = 1,2) и заканчивающийся дугой, ведущей к распознавателю, оператору нетли, заключительному оператору или к первой из пересылок выходного вектора пересылок этого фрагмента: Ы : zakhivan.ov.tex, г>1.42006/12/1315 : 59 : 10StasFonггnExp— взаимно однозначное соответствие входов, заключительных операторов, операторов нетли, распознавателей и их выходных дуг, которое существует благодаря совпадению л-графов Сх и С2.
Преобразуем фрагмент С\ во фрагмент С\, заменяя в нем всякое вхождение луча
Л(е)
Л(е) на луч
М1с1(е))
Ъ Ъ
Это преобразование можно выполнить однократным применением Т5, поскольку в силу условия согласованности СЗ результаты добавляемых преобразований не встречаются в исходном фрагменте , а потому и не могут влиять на распознаватели, заключительные операторы и выходы в .
Пусть теперь V — произвольный распознаватель, заключительный оператор или одна из пересылок выходного вектора пересылок в , х — ее г-й аргумент, а у — г-й аргумент вершины Ы(г’) во фрагменте С2. Покажем, что тогда инварианты всех дуг е, ведущих к V в Сх, содержат равенство х = у. Действительно, предположение {ж = у} £ *т»аг((?1, е) означает существование такого пути IV, начинающегося некоторым входом и кончающегося дугой е в (?1, что г>/(гу,ж) ф цЦго, у). Последнее, в свою очередь, означает, что фрагменты и С2 не являются логико-термально эквивалентными, т.е. мы получили противоречия с исходным предположением.
Итак, применением Т8 г-й аргумент каждой из вершин-раснознава-телей, заключительных операторов и выходных пересылок г> в можно заменить на соответствующий аргумент Ы(г’) из С2. В результате такого преобразования на каждом из лучей
а —> 1\{е) —> МЫ(е)) —> Ь
в С?1 преобразователи из Л(е) становятся неиспользуемыми, и их можно .удалить применением схемы правил Т5. После этого преобразования фрагмент окажется совпадающим с фрагментом С2. □
Следствие 3. Существует алгоритм распознавания Н-эквивалентносгпи для схем МДП (фрагментов).
Доказательство.
Шаг 1: Преобразуем исходные фрагменты и С2 в приведенные фрагменты.
Шаг 2: Распознаем подобие полученных фрагментов. Если они не подобны, то й С2 и алгоритм останавливается с отрицательным ответом. Если же фрагменты подобны, переходим к следующему шагу-
Шаг 3: Строим согласованную пару фрагментов = ш«Й(6?1,6?2) и С2 = ■тиИ(С2,С1) (теорема 6).
Шаг 4: По и С2 строим фрагмент Сх (см. доказательство теоремы 7), а затем его стационарную разметку.
Шаг 5: Если не выполнены условия некоторых из упомянутых в доказательстве теоремы 7 применений схемы правил Т8, то С\ 1Л С2 и алгоритм останавливается с отрицательным ответом, в противном случае ~ С2 и алгоритм останавливается с положительным ответом.
6. Заключение
Описанный в разделе 5 алгоритм распознавания логико-термальной эквивалентности для модели программ с динамической памятью является полиномиальным. Грубо оценить сверху время работы алгоритма можно величиной 0(п8), где п — размер схемы программы.
Достигнутые результаты позволят в дальнейшем решить ряд важных задач: расширить модель операциями над адресами, строить и выяснять эквивалентность систем преобразований программ, обосновывать корректность работы алгоритмов анализа программ и алгоритмов обфускации, обосновывать стойкость алгоритмов обфускации, вводить метрики на программах, позволяющие выражать стойкость алгоритмов обфускации и информативность алгоритмов анализа.
Литература
fl] Котов В.Е., Сабельфельд В.К. Теория схем программ. Москва. «Наука». 2001.
[2] Zamulin A. A State-Based Semantics of a Pascal-like Language. Perspectives of System Informatics. «Эмари». Новосибирск. 2003. p. 47-63.
[3] Collberg €.. Thomborson €.. Low D.. Manufacturing cheap, resilient and stealthy opaque constructs. In Proc. of the Symposium on Principles of Programming Languages. 1998. p. 184-196.
[4] Collberg €.. Thomborson €.. Low D.. A taxonomy of obfuscating transformations. Tech. Report. X 148. Dept, of Computer Science. Univ. of Auckland. 1997.
[5] Wroblewski G.. General Method of Program Code Obfuscation. Wroclaw. 2002.
[6| Horwitz S. Precise Flow-Insensitive May-Alias Analysis is XP-Hard, ACM Transactions on Programming Languages and Systems, V. 19. X 1. 1997. p. 1-6.
[7] Ivanov K. S.. Zakharov V. A. Program obfuscation as obstruction of program static analysis, Труды НСП РАН. Том 6. 2004. с. 137-149.
[8j Andersen L.O. Program Analysis and Specialization for the С Programming Language. DIKU. University of Copenhagen. May 1994.
[9j Steensgaard B. Points-to analysis in almost linear time. In Conference Record of the 23th Annual A CM Symposium, on Principles of Programming Languages (POPL!96), p. 32-41. ACM Press. January 1996.
[101 Shapiro М.. Horwitz S. Fast and accurate flow-insensitive point-to analysis. In 24th Annual ACM SICACT-SICPLAN Symposium, on the Principles of Programming Languages, p. 1-14. January 1997.
[11] Hind М.. Burke М.. Carini P. Jong-Deok Choi. Interprocedural pointer alias analysis. ACM Trans. Programming Languages and Systems. V. 21. X 4. 1999, p.848-894.
[12] Barak B., Goldreich O., Impagliazzo R., Rudich S., Sahai A., Vedhan S., Yang K., On the (Im)possibility of obfuscating programs. CRYPTO'Ol — Advances in Cryptolog)', Lecture Xotes in Computer Science, 2139, p. 1-18, 2001.