Статья NETрогай! Как защитить программу от лишних глаз.

logotype.png

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

План статьи
Перед каждым началом нужно разобраться с тем, как мы будем защищаться. В этом плане я буду использовать четыре программы:
  1. Spices.Net
  2. Smart Assembly
  3. NET Reactor
Каждый из них мы будем тестировать при помощи Detect It Easy и других утилит для реверса, если это потребуется конечно. Но перед этим нужно что-то создать. В этом деле я покажу самую простую программу на C#. С ней мы и будем работать в дальнейшем.

Программа для тестов
Чтобы что-то защищать нужно что-то создать. Я не стал далеко ходить и написал самую простую утилиту с большой, красной кнопкой. При нажатии на нее операционная система выходит из строя. Поэтому если какой-то любопытный пользователь захочет ее вскрыть мы этого не позволим. Открываем Visual Studio и выбираем проект Windows Forms.

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

C#:
[DllImport("ntdll.dll", SetLastError = true)]
private static extern int NtSetInformationProcess(IntPtr hProcess, int processInformationClass, ref int processInformation, int processInformationLength);
private void Click_Button(object sender, EventArgs e) {
    int isCritical = 1;  // 1
    int BreakOnTermination = 0x1D;  // 2

    Process.EnterDebugMode();  // 3

            // 4
    NtSetInformationProcess(Process.GetCurrentProcess().Handle, BreakOnTermination, ref isCritical, sizeof(int));
}

В первом мы создаем критический процесс и присвоим ее значение 1. Ниже задаем значение для флага BreakOnTermination в шестнадцатиричной системе счисления. После делаем запрос отладочных привилегий в строчке 3 и после присваиваем нашему флагу значение один. Все это дело происходит под четвертым комментарием.

Сохраняем результат и собираем проект. Только не думай нажимать на эту кнопку! Иначе придется перезагружать систему, а это сейчас будет лишним действием. Давай загрузим PE-файл в DiE и убедимся, что все работает корректно.

DiE.jpg


Библиотека никуда не пропала как и линковщик. Все строки хорошо просматриваются, а энтропия остается на статусе в 68%. Значит ничего не зашифровано и мы можем спокойно работать с софтом. Если ты до сих пор не понял, где хранится твой PE-файл из проекта, то загляни в папку bin и там же перейди на Debug. Ну а теперь стоит приступить к защите.

Как работает защита
Для начала предлагаю ознакомиться с теоретической частью нашей статьи. Прежде всего существует два типа защиты NET приложений. Это использование обфускаторов и протекторов. Разберем их плюсы и минусы работы.

Протекторы: предоставляют возможность сделать "недоступным" для других. Часто имеют дополнительные функции и позволяют делать защищенные сборки под себя. К этому типу относится наш любимый NET Reactor.
  • Плюсы: ограничение прав сборки в оперативной памяти с последующим сохранением на диске. Достаточно разнообразный набор функций для защиты.
  • Минусы: конфликты с разрядностью системы. Проще говоря ты не можешь создать 64 битную и 32 битную программу одновременно. Яркая и очень хорошо выраженная реакция антивирусов на протекторы. Из-за нее многие пользователи просто боятся использовать такой продукт. К этому добавляется заявление производителей, которые рекомендуют обфуцировать код перед тем, как покрывать его протектором. То есть они сами признают минус своих детищ.
Обфускаторы: запутывают код на основе определенных алгоритмов делая его не читабельным для человека, но рабочим для компьютера. После них обычно не требуется дополнительная настройка или танцы с бубном, чтобы успешно запустить свой код. Есть два варианта обфускации: Stand-alone (не требует в работе сторонних сервисов) и зависимые от MS сервисов (они в свою очередь никак не могут функционировать без доступа к интернету). Примеры, которые мы будем использовать в работе это Smart Assembly и Spices.Net.
  • Плюсы: независимость от каких-либо программ. Простота и надежность в работе, что дает гарантию запуска кода. Также это считается нестандартным подходом к защите софта.
  • Минусы: здесь есть один жирный минус. Заключается он в том, что на родном языке чтение кода почти невозможно, но дизассемблировать программу и узнать ее алгоритм работы по прежнему остается реальным.
Теперь, после того, как мы разобрались с базовыми понятиями можно приступать к тестированию.

Spices.Net


spices.net.jpg


Spices.Net - инструментальное средство следующего поколения для .Net разработчиков, которое содержит функции защиты .NET кода и множество других возможностей. Программа состоит из ядра системы и 2-х внешних модулей Spices.Obfuscator и Spices.Decompiler. Spices.Decompiler содержит функции декомпилирования для 6 языков IL, C#, C++, VB.Net, J#. В ближайшем будущем в программе появятся новые дополнения, Spices.Investigator (.Net PE metadata browser) и Spices.Informer. Как ты понимаешь по мимо защиты он умеет и декомпилировать некоторые программы. Но наша задача защитить исходный код, чтобы до него не мог добраться пользователь. Поэтому чтобы это сделать открываем нашу программу во вкладке File и далее переходим на Tools, кликаем по кнопке Obfuscate! и ждем результата. В итоге у тебя должен появиться файл и папка Output, где лежит готовая работа.

Теперь давай посмотрим, что у нас получилось. Первым делом заливаем все это в наш любимый DiE.

DiE_OBF1.jpg


Как ты видишь понятие протектора или обфускатора в логах у нас не висит, а это уже хороший плюс в копилку. Глянем вкладку строк и посмотрим, что там изменилось. Изменения появились, хоть и не сильно заметные, но расположение строк явно говорят о наличие какой-то внешней защиты. В энтропии у нас все по стандарту, цифры не поменялись и стабильно держат планку на 63%. Давай копнем чуть глубже и посмотрим результат в dotPeek, он точно должен определить подвох.

А его тут нету. Весь код спокойно читается и никакой обфускации не произошло. В строках DiE мы видели все те же строки, но в другом формате. И выходит, что Spices.Net только на словах защищает код. А вот кстати та самая функция, которая вызывает синий экран смерти путем создания критического процесса. При декомпиляции она выглядит таким образом:

C#:
[DllImport("ntdll.dll", EntryPoint = "NtSetInformationProcess", SetLastError = true)]
private static extern int \u0030(IntPtr _param0, int _param1, ref int _param2, int _param3);

private void \u0030(object _param1, EventArgs _param2) {
    int num1 = 1;
    int num2 = 29;
    Process.EnterDebugMode();
    MainWindow.\u0030(Process.GetCurrentProcess().Handle, num2, ref num1, 4);
}

Поэтому здесь мы разобрались с тем, что не весь софт умеет адекватно выполнять свою работу. Сразу занесем название утилиты в черный список, чтобы в дальнейшем не натыкаться на нее. Это кстати объясняет почему при статическом анализе из скриншота не было видно строчки протектора.

Smart Assembly


smartassembly.jpg


SmartAssembly – это программное обеспечения представляет собой NET-обфускатор и систему составления автоматических отчетов об обнаруженных ошибках и использовании возможностей приложений. С помощью этого решения NET-разработчики могут создавать высококачественные и свободные от багов продукты. Из особенностей могу отметить наличие множества функций для настройки обфускации, ну а из минусов то, что программа является платной и имеет только пробную версию. Поэтому некоторые функции будут для нас закрыты.

Первым делом нас встречает окно с просьбой загрузить исполняемый файл. Берем в руки нашу программу и выгружаем ее в приложение. Далее настраиваем обфускацию из предложенных функций. Нам доступно создание отчетов, создание сложного ключа, автоматическая отправка ошибок, удаление ненужных строк, настройка уровня обфускации и настройка динамического прокси. Ставим все по хардкору и компилируем наш софт, попутно молясь, что все сработает. Ну а если ты хочешь знать, что конкретно я использовал, то выставляй в настройках следующие функции: Obfuscation (3 level), Compression and Encryption, Strings Encoding, MSIL Disassembelr Protection. Ждем несколько минут и радуемся успешной сборке. Переходим в DiE и смотрим изменения.

DiE_OBF2.jpg


Строки зашифрованы, а энтропия подскочила до 77%. Поэтому сказать, что нет изменений очевидно нельзя. Вместо обфускатора у нас в колонке отображается протектор, хотя на самом деле это не так. В скором времени ты поймешь почему. Теперь давай откроем dotPeek и взглянем на то, как выглядит наш код. А он очень сильно изменился.

Переходим в тот же файл MainWindow.cs и смотрим нашу часть кода, которая отвечает за главное действие программы. Теперь все это дело выглядит так:

C#:
[DllImport("ntdll.dll", SetLastError = true)]
private static extern int NtSetInformationProcess(
    IntPtr hProcess,
    int processInformationClass,
    ref int processInformation,
    int processInformationLength);

private void Click_Button(object sender, EventArgs e) {
    int processInformation = 1;
    int processInformationClass = 29;
    Process.EnterDebugMode();
    MainWindow.NtSetInformationProcess(Process.GetCurrentProcess().Handle, processInformationClass, ref processInformation, 4);
}

Теперь как ты понимаешь разобрать название переменных и большую часть кода стало невозможно. К этому добавляется несколько пустых функций в начале нашего файла. Есть также дополнительные модули, которые помогают запутать код и сбить с пути реверсера. Как я говорил ранее, если в dotPeek это прочитать невозможно, то в дизассемблерах все легко читается и понять как работает программа вполне возможно. Возьми тот же x64dbg и попробуй залить бинарник с обфускацией. Разница конечно будет, но не такая яркая как в нашем случаи. Поэтому давай теперь попробуем запутать в принципе все, что только можно и покроем нашу программу протектором.

NET Reactor


netreactor.jpg


NET Reactor - это мощная система защиты и лицензирования NET-кода, которая помогает разработчикам в защите своего NET программного обеспечения простым и безопасным способом. Работать мы будем на крякнутой версии этого протектора. У тебя скорее всего возник вопрос, а почему бы не использовать официальную версию? Здесь все очень просто. В отличие от предыдущих программ, которые яростно требуют чтобы их купили реактор просто при каждой компиляции добавляет диалоговое окно в код с названием протектора. То есть перед запуском самой программы у тебя вылезет маленькое рекламное окошко с названием NET Reactor. Гениальный как по мне ход.

Запускаем наш протектор и выбираем создание нового проекта. Далее заливаем туда файл и выбираем нужные функции, их ты можешь увидеть на скриншоте. Чтобы не устраивать танцы с бубном я отметил тот тип защиты, который применяется наиболее чаще в защите. Так мы создаем гарантию того, что итоговый проект запустится. После всех манипуляций кликаешь на кнопочку Protect и терпеливо ждешь результата. Дождался? Заливаем все это дело в DiE и смотрим, что получилось в итоге.

DiE_OBF3.jpg


В столбце наш протектор никак не отображается. Неужели ничего не поменялось? Заглянем в энтропию и посмотрим на статус. 71%, а это значит, что файл чем-то покрыт. Открывай строки, здесь посмотри внимательно на некоторые команды, увидел? Некоторые из них просто зашифрованы. А это значит, что пора смотреть, что под капотом. На удивление та же ситуация. Все функции имеют непонятный вид, а наша команда вызова синего экрана смерти вообще как-то странно выглядит:

C++:
[DllImport("ntdll.dll", EntryPoint = "NtSetInformationProcess", SetLastError = true)]
private static extern int v5LKivyS4(IntPtr _param0, int _param1, ref int _param2, int _param3);

private void txK5sHCkH(object _param1, EventArgs _param2) {
    int num1 = 1;
    int num2 = 29;
    Process.EnterDebugMode();
    MainWindow.v5LKivyS4(Process.GetCurrentProcess().Handle, num2, ref num1, 4);
}

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

Подводим итоги
Итак, сегодня я рассказал тебе о трех утилитах, которые помогут тебе скрыть свой код от пользователей. К сожалению одна из них отказалась работать и от обфускации осталось лишь одно слово. Но это только подтверждает факт того, что не любая программа способна защитить софт. Что лучше использовать в работе решать тебе. Лично я отдаю свой голос в пользу NET Reactor, так как в работе это незаменимый софт. Но не стоит забывать про его конкурента Smart Assembly, ведь он тоже имеет место быть. Хоть и есть в нем минус, который выражается в отсутствии адекватной бесплатной версии.
 
Последнее редактирование модератором:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!