Об одном методе маскировки программ


Общее описание метода маскировки


Метод ММ применяется к функциям маскируемой программы по отдельности, при этом структура маскируемой программы в целом не изменяется. Для изменения структуры маскируемой программы могут применяться стандартные методы открытой вставки и выноса функции, рассмотренные в [8], которые, однако, не являются частью предлагаемого метода маскировки.

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

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

Мы предполагаем, что перед маскировкой были выполнены все стандартные шаги анализа программы: лексический, синтаксический, семантический, анализ потока управления (построение графа потока управления и деревьев доминирования и постдоминирования) и консервативный глобальный анализ потоков данных (достигающие определения и доступные выражения с учётом возможных алиасов). Дополнительно может быть выполнено профилирование дуг, результаты которого учитываются в преобразованиях клонирования дуг и развёртки циклов.

Общая идея метода может быть охарактеризована следующим образом.

  • Во-первых, значительно увеличить сложность графа потока управления, но так, чтобы все дуги графа потока управления, внесённые при маскировке, проходились при выполнении программы.
    Это позволяет преодолеть основную слабость "непрозрачных" предикатов.



  • Во-вторых, увеличить сложность потоков данных маскируемой функции, "наложив" на неё программу, которая заведомо не влияет на окружение маскируемой функции и, как следствие, не изменяет работы программы. "Холостая" функция строится как из фрагментов маскируемой функции, семантические свойства которых заведомо известны, так и из фрагментов, взятых из библиотеки маскирующего транслятора. Чтобы затруднить задачу выявления холостой части замаскированной функции используются языковые конструкции, трудно поддающиеся анализу (указатели) и математические тождества.


Маскировку можно разбить на несколько этапов:

  • Увеличение размера графа потока управления функции. На этом этапе выполняются различные преобразования, которые изменяют структуру циклов в теле функции, а также клонирование базовых блоков.
  • Разрушение структуры графа потока управления функции. На этом этапе в граф потока управления вносится значительное количество новых дуг. При этом существовавшие базовые блоки могут оказаться разбитыми на несколько меньших базовых блоков. В графе потока управления могут появиться новые пока пустые базовые блоки. Цель этого этапа - подготовить место, на которое в дальнейшем будет внесён несущественный код.
  • Генерация несущественного кода. На этом этапе пустые базовые блоки графа потока управления заполняется инструкциями, не оказывающими влияния на результат, вырабатываемый программой. Несущественная, "холостая" часть пока никак не соприкасается с основной, функциональной частью программы.
  • "Зацепление" холостой и основной программы. Для этого используются как трудноанализируемые свойства программ (например, указатели), так и разнообразные математические тождества и неравенства.


    Содержание раздела