УДК 004.056.53
Защита JavaScript кода на основе рекурсивного прохода по АСД: методы и алгоритмы обфускации
Лейман Александр Константинович – магистрант Алтайского государственного технического университета им. И.И. Ползунова
Гребеньков Александр Александрович – кандидат физико-математических наук, доцент Алтайского государственного технического университета им. И.И. Ползунова
Аннотация: В данной статье продемонстрированы методы запутывания кода JavaScript, основанные на преобразовании узлов абстрактного синтаксического дерева исходной программы за один проход по АСД.
Ключевые слова: JavaScript, защита кода от анализа, обфускация, абстрактное синтаксическое дерево.
На сегодняшний день язык программирования JavaScript имеет довольно широкий спектр применения, а главной средой размещения был и является веб-браузер [3, с. 23]. Важной чертой JavaScript является то, что итоговый программный продукт представляется в виде открытых исходных текстов на стороне клиента, что делает его доступным для любого пользователя.
В целях защиты авторского ПО написанного на JavaScript от анализа и редактирования на данный момент наиболее актуальными являются методы обфускации, которые основаны на преобразовании программного кода к трудночитаемому виду без потери его функциональности. Так как они позволяют усложнить процесс реверсивной инженерии кода защищаемого программного продукта.
Для скриптовых языков с открытым исходным кодом эффективно применять обфускацию на уровне исходных текстов. Основных видов алгоритмов обфускации не так уж много, они подразделяются на [2, с. 60]:
- лексическую обфускацию;
- обфускацию данных;
- обфускацию управления;
- превентивную обфускацию.
Алгоритм разрабатываемого обфускатора основывается на алгоритме Колберга, который определяет последовательность преобразований, но не то, как реализовывать тот или иной метод обфускации [1, с. 7].
Общий алгоритм обфускации будет начинаться с получения абстрактного синтаксического дерева, в котором корневым узлом будет являться тело программы. Каждый его дочерний узел является каким-то кусочком исходного кода с очень подробным описанием. Пример такого дерева представлен на рисунке 1.
Процесс обфускации будет заключаться в преобразовании данного дерева. Был разработан алгоритм рекурсивного прохода, при котором, в зависимости от того, какой пришел узел, определяем либо какие преобразования можно с ним произвести, либо вызываем данный метод для его дочерних узлов. Так, например, если узел равен «StringLiteral», то будем производить кодировку строки. Если объявление переменной или использование какого-либо идентификатора выполняем преобразование замены имени.
Рисунок 1. Структура АСД программы.
Пример узла цикла представлен ниже (рисунок 2). Для примера рассмотрим цикл for. В узле «ForStatement» четыре основных узла: инициализация переменной счетчика начальным значением (init); сравнение переменной счетчика с условием завершения (test); обновление счетчика на заданное значение (update); тело цикла (body). Тело цикла может содержать различные выражения. Преобразования цикла будет заключаться в добавлении дополнительных узлов выражений в узел «body», замена простых выражений на вызов дополнительных внешних функций, в которые будут вынесены использовавшиеся выражения, а также замена имени счетчика цикла.
Рисунок 2. Структура узла цикла for.
Структура узла строкового литерала представлена на рисунке 3 слева, включает в себя выражение с аргументом строки. А справа на данном рисунке – преобразованный вид, включает в себя операцию сложения и вызовов функции с передачей параметра.
Рисунок 3. Преобразование строкового литерала.
Узел, содержащий в себе конструкцию switch схематично представлен на рисунке 4. В узле test находится значение сравнения. В consequent выполняемые действия в этом case.
Рисунок 4. Структура узла switch.
Данную конструкцию можно заменить на поиск по объектному литералу.
Алгоритм данного преобразования:
- Создать новый блок кода, содержащий пустой объект;
- Пройти по всем узлам Case;
- Добавить в объект свойство в виде пары «ключ: значение», где ключ – значение case, а значение – блок выполнения;
- Добавить в объект свойство для выполнения в случае, если ни один из ключей объектного литерала не совпадает с исходным значением;
- Заменить узел switch на новый блок кода с поиском по объектному литералу.
Результат преобразования представлен ниже (рисунок 5):
Рисунок 5. Преобразование switch в объектный литерал.
Главным достоинством подхода применения преобразований в рекурсивном методе прохода заключается в том, что, независимо от количества применяемых преобразований, их можно произвести всего лишь за один проход, что определенно положительно повлияет на производительность обфускации.
Список литературы
- Christian Collberg, Clark Thomborson, Douglas Low, A Taxonomy of Obfuscating transformations // Technical Report №148, The University of Auckland, Department of Computer Science, 1997.
- Ивченкова Ю. С. Виды и способы обфускации / Ю. С. Ивченкова, М. К. Савкин // Электронный журнал: наука, техника и образование, 2016. – № 2 (6). – С. 60-66.
- Флэнаган, Дэвид. Ф73 JavaScript. Полное руководство, 7-е изд.: Пер. с англ. – СПб. : ООО “Диалектика”, 2021. – 720 с . : ил. – Парал. тит. англ.