УДК 004.056.53

Защита JavaScript кода на основе рекурсивного прохода по АСД: методы и алгоритмы обфускации

Лейман Александр Константинович – магистрант Алтайского государственного технического университета им. И.И. Ползунова

Гребеньков Александр Александрович – кандидат физико-математических наук, доцент Алтайского государственного технического университета им. И.И. Ползунова

Аннотация: В данной статье продемонстрированы методы запутывания кода JavaScript, основанные на преобразовании узлов абстрактного синтаксического дерева исходной программы за один проход по АСД.

Ключевые слова: JavaScript, защита кода от анализа, обфускация, абстрактное синтаксическое дерево.

На сегодняшний день язык программирования JavaScript имеет довольно широкий спектр применения, а главной средой размещения был и является веб-браузер [3, с. 23]. Важной чертой JavaScript является то, что итоговый программный продукт представляется в виде открытых исходных текстов на стороне клиента, что делает его доступным для любого пользователя.

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

Для скриптовых языков с открытым исходным кодом эффективно применять обфускацию на уровне исходных текстов. Основных видов алгоритмов обфускации не так уж много, они подразделяются на [2, с. 60]:

  • лексическую обфускацию;
  • обфускацию данных;
  • обфускацию управления;
  • превентивную обфускацию.

Алгоритм разрабатываемого обфускатора основывается на алгоритме Колберга, который определяет последовательность преобразований, но не то, как реализовывать тот или иной метод обфускации [1, с. 7].

Общий алгоритм обфускации будет начинаться с получения абстрактного синтаксического дерева, в котором корневым узлом будет являться тело программы. Каждый его дочерний узел является каким-то кусочком исходного кода с очень подробным описанием. Пример такого дерева представлен на рисунке 1.

Процесс обфускации будет заключаться в преобразовании данного дерева. Был разработан алгоритм рекурсивного прохода, при котором, в зависимости от того, какой пришел узел, определяем либо какие преобразования можно с ним произвести, либо вызываем данный метод для его дочерних узлов. Так, например, если узел равен «StringLiteral», то будем производить кодировку строки. Если объявление переменной или использование какого-либо идентификатора выполняем преобразование замены имени.

image001

Рисунок 1. Структура АСД программы.

Пример узла цикла представлен ниже (рисунок 2). Для примера рассмотрим цикл for. В узле «ForStatement» четыре основных узла: инициализация переменной счетчика начальным значением (init); сравнение переменной счетчика с условием завершения (test); обновление счетчика на заданное значение (update); тело цикла (body). Тело цикла может содержать различные выражения. Преобразования цикла будет заключаться в добавлении дополнительных узлов выражений в узел «body», замена простых выражений на вызов дополнительных внешних функций, в которые будут вынесены использовавшиеся выражения, а также замена имени счетчика цикла.

image002

Рисунок 2. Структура узла цикла for.

Структура узла строкового литерала представлена на рисунке 3 слева, включает в себя выражение с аргументом строки. А справа на данном рисунке – преобразованный вид, включает в себя операцию сложения и вызовов функции с передачей параметра.

image003

Рисунок 3. Преобразование строкового литерала.

Узел, содержащий в себе конструкцию switch схематично представлен на рисунке 4. В узле test находится значение сравнения. В consequent выполняемые действия в этом case.

image004

Рисунок 4. Структура узла switch.

Данную конструкцию можно заменить на поиск по объектному литералу.

Алгоритм данного преобразования:

  1. Создать новый блок кода, содержащий пустой объект;
  2. Пройти по всем узлам Case;
  3. Добавить в объект свойство в виде пары «ключ: значение», где ключ – значение case, а значение – блок выполнения;
  4. Добавить в объект свойство для выполнения в случае, если ни один из ключей объектного литерала не совпадает с исходным значением;
  5. Заменить узел switch на новый блок кода с поиском по объектному литералу.

Результат преобразования представлен ниже (рисунок 5):

image005

Рисунок 5. Преобразование switch в объектный литерал.

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

Список литературы

  1. Christian Collberg, Clark Thomborson, Douglas Low, A Taxonomy of Obfuscating transformations // Technical Report №148, The University of Auckland, Department of Computer Science, 1997.
  2. Ивченкова Ю. С. Виды и способы обфускации / Ю. С. Ивченкова, М. К. Савкин // Электронный журнал: наука, техника и образование, 2016. – № 2 (6). – С. 60-66.
  3. Флэнаган, Дэвид. Ф73 JavaScript. Полное руководство, 7-е изд.: Пер. с англ.  СПб. : ООО “Диалектика”, 2021. – 720 с . : ил. – Парал. тит. англ.

Интересная статья? Поделись ей с другими: