Введение
Со времен появления первых программ и компьютеров, людям не раз приходилось сталкиваться со множеством проблем. Одна из них появилась еще в период создания коммерческого ПО. Мало кто горит желанием платить за использование софта. В связи с этим сейчас нам очень знакомо слово — пиратство.
Хакеры каждый день вскрывают множество утилит и выпускают их крякнутые версии в открытый доступ. Поэтому сегодня я расскажу тебе, как с этим бороться.
- Spices.Net
- Smart Assembly
- NET Reactor
Программа для тестов
Чтобы что-то защищать нужно что-то создать. Я не стал далеко ходить и написал самую простую утилиту с большой, красной кнопкой. При нажатии на нее операционная система выходит из строя. Поэтому если какой-то любопытный пользователь захочет ее вскрыть мы этого не позволим. Открываем Visual Studio и выбираем проект Windows Forms.
Возможность создать интерфейс я предоставляю тебе. Дай волю фантазии и создай свой графический интерфейс с одной единственной красной кнопкой. Далее тебе потребуется открыть скрипт основного окна и записать туда такой короткий код:
Как защитить свой код
[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 и убедимся, что все работает корректно.
Библиотека никуда не пропала как и линковщик. Все строки хорошо просматриваются, а энтропия остается на статусе в 68%. Значит ничего не зашифровано и мы можем спокойно работать с софтом. Если ты до сих пор не понял, где хранится твой PE-файл из проекта, то загляни в папку bin и там же перейди на Debug. Ну а теперь стоит приступить к защите.
Как работает защита
Для начала предлагаю ознакомиться с теоретической частью нашей статьи. Прежде всего существует два типа защиты NET приложений. Это использование обфускаторов и протекторов. Разберем их плюсы и минусы работы.
- Плюсы: ограничение прав сборки в оперативной памяти с последующим сохранением на диске. Достаточно разнообразный набор функций для защиты.
- Минусы: конфликты с разрядностью системы. Проще говоря ты не можешь создать 64 битную и 32 битную программу одновременно. Яркая и очень хорошо выраженная реакция антивирусов на протекторы. Из-за нее многие пользователи просто боятся использовать такой продукт. К этому добавляется заявление производителей, которые рекомендуют обфуцировать код перед тем, как покрывать его протектором. То есть они сами признают минус своих детищ.
- Плюсы: независимость от каких-либо программ. Простота и надежность в работе, что дает гарантию запуска кода. Также это считается нестандартным подходом к защите софта.
- Минусы: здесь есть один жирный минус. Заключается он в том, что на родном языке чтение кода почти невозможно, но дизассемблировать программу и узнать ее алгоритм работы по прежнему остается реальным.
Spices.Net
Защитите свой код на Python от взлома — PYARMOR Обфускация
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.
Как ты видишь понятие протектора или обфускатора в логах у нас не висит, а это уже хороший плюс в копилку. Глянем вкладку строк и посмотрим, что там изменилось. Изменения появились, хоть и не сильно заметные, но расположение строк явно говорят о наличие какой-то внешней защиты. В энтропии у нас все по стандарту, цифры не поменялись и стабильно держат планку на 63%. Давай копнем чуть глубже и посмотрим результат в dotPeek, он точно должен определить подвох.
А его тут нету. Весь код спокойно читается и никакой обфускации не произошло. В строках DiE мы видели все те же строки, но в другом формате. И выходит, что Spices.Net только на словах защищает код. А вот кстати та самая функция, которая вызывает синий экран смерти путем создания критического процесса. При декомпиляции она выглядит таким образом:
[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)
Поэтому здесь мы разобрались с тем, что не весь софт умеет адекватно выполнять свою работу. Сразу занесем название утилиты в черный список, чтобы в дальнейшем не натыкаться на нее. Это кстати объясняет почему при статическом анализе из скриншота не было видно строчки протектора.
Smart Assembly
SmartAssembly – это программное обеспечения представляет собой NET-обфускатор и систему составления автоматических отчетов об обнаруженных ошибках и использовании возможностей приложений. С помощью этого решения NET-разработчики могут создавать высококачественные и свободные от багов продукты. Из особенностей могу отметить наличие множества функций для настройки обфускации, ну а из минусов то, что программа является платной и имеет только пробную версию. Поэтому некоторые функции будут для нас закрыты.
Первым делом нас встречает окно с просьбой загрузить исполняемый файл. Берем в руки нашу программу и выгружаем ее в приложение. Далее настраиваем обфускацию из предложенных функций. Нам доступно создание отчетов, создание сложного ключа, автоматическая отправка ошибок, удаление ненужных строк, настройка уровня обфускации и настройка динамического прокси.
Ставим все по хардкору и компилируем наш софт, попутно молясь, что все сработает. Ну а если ты хочешь знать, что конкретно я использовал, то выставляй в настройках следующие функции: Obfuscation (3 level), Compression and Encryption, Strings Encoding, MSIL Disassembelr Protection. Ждем несколько минут и радуемся успешной сборке. Переходим в DiE и смотрим изменения.
Строки зашифрованы, а энтропия подскочила до 77%. Поэтому сказать, что нет изменений очевидно нельзя. Вместо обфускатора у нас в колонке отображается протектор, хотя на самом деле это не так. В скором времени ты поймешь почему. Теперь давай откроем dotPeek и взглянем на то, как выглядит наш код.
А он очень сильно изменился.
Переходим в тот же файл MainWindow.cs и смотрим нашу часть кода, которая отвечает за главное действие программы. Теперь все это дело выглядит так:
[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)
Теперь как ты понимаешь разобрать название переменных и большую часть кода стало невозможно. К этому добавляется несколько пустых функций в начале нашего файла.
Есть также дополнительные модули, которые помогают запутать код и сбить с пути реверсера. Как я говорил ранее, если в dotPeek это прочитать невозможно, то в дизассемблерах все легко читается и понять как работает программа вполне возможно. Возьми тот же x64dbg и попробуй залить бинарник с обфускацией. Разница конечно будет, но не такая яркая как в нашем случаи. Поэтому давай теперь попробуем запутать в принципе все, что только можно и покроем нашу программу протектором.
NET Reactor
NET Reactor — это мощная система защиты и лицензирования NET-кода, которая помогает разработчикам в защите своего NET программного обеспечения простым и безопасным способом. Работать мы будем на крякнутой версии этого протектора. У тебя скорее всего возник вопрос, а почему бы не использовать официальную версию? Здесь все очень просто.
В отличие от предыдущих программ, которые яростно требуют чтобы их купили реактор просто при каждой компиляции добавляет диалоговое окно в код с названием протектора. То есть перед запуском самой программы у тебя вылезет маленькое рекламное окошко с названием NET Reactor. Гениальный как по мне ход.
Запускаем наш протектор и выбираем создание нового проекта. Далее заливаем туда файл и выбираем нужные функции, их ты можешь увидеть на скриншоте. Чтобы не устраивать танцы с бубном я отметил тот тип защиты, который применяется наиболее чаще в защите. Так мы создаем гарантию того, что итоговый проект запустится.
После всех манипуляций кликаешь на кнопочку Protect и терпеливо ждешь результата. Дождался? Заливаем все это дело в DiE и смотрим, что получилось в итоге.
В столбце наш протектор никак не отображается. Неужели ничего не поменялось? Заглянем в энтропию и посмотрим на статус. 71%, а это значит, что файл чем-то покрыт. Открывай строки, здесь посмотри внимательно на некоторые команды, увидел? Некоторые из них просто зашифрованы. А это значит, что пора смотреть, что под капотом.
На удивление та же ситуация. Все функции имеют непонятный вид, а наша команда вызова синего экрана смерти вообще как-то странно выглядит:
[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)
Можно только сказать, что протектор справился на ура! Теперь наш код полностью защищен от пиратов, жаждущих вечно что-то сломать и вскрыть. По мимо этого все функции не отображаются в правильном названии и имеют совершенно другой вид.
Поэтому кому-то другому будет очень тяжело ориентироваться в этой паутине. Задача выполнена, поэтому можем спокойно переходить к итогам статьи.
Подводим итоги
Итак, сегодня я рассказал тебе о трех утилитах, которые помогут тебе скрыть свой код от пользователей. К сожалению одна из них отказалась работать и от обфускации осталось лишь одно слово. Но это только подтверждает факт того, что не любая программа способна защитить софт. Что лучше использовать в работе решать тебе.
Лично я отдаю свой голос в пользу NET Reactor, так как в работе это незаменимый софт. Но не стоит забывать про его конкурента Smart Assembly, ведь он тоже имеет место быть. Хоть и есть в нем минус, который выражается в отсутствии адекватной бесплатной версии.
Источник: codeby.net
Защита приложения. Часть 2. Обфускация
Обфускация — следующий уровень защиты приложения. Недостаточно защитить данные паролями и привязкой к железу: такую защиту легко обойти, пронанализировав код. Мы писали об этом в предыдущей статье — «Защита приложения. Часть 1». Чтобы код нельзя было так просто просмотреть и понять — запутывайте его.
Для этого и была придумана обфускация, набор методов, которые превращают понятный код в непонятную кашу.
Обфускация имеет под собой серьёзные теоретические основания. Важно не только выполнить основную задачу — запутать код, но и при этом не нанести серьёзного урона как скорости, так и функциональности приложения.
Наибольшую популярность в деле обфускации получил метод Колберга. Пусть ваша программа — А, тогда задача сводится к созданию выходного кода A’ с использованием преобразований T1, T2…Tn, опирающихся на использование библиотек L1, L2…Ln. Эффективность процессов оценивается функциями E1, E2…En. Множественность возникает из-за разбиения кода на разные по важности фрагменты, оцениваемые функциями I1, I2…ln. Так мы обеспечим максимальную защиту важнейшим участкам, при этом постараясь не проиграть в быстродействии.
Виды обфускации
Преобразования бывают четырех видов:
- лексическая обфускация;
- преобразование данных;
- преобразование управления;
- профилактическая обфускация.
Лексическая обфускация — замена названий переменных и функций. Например, понятная раннее final_cost[positions] превращается в бездушную f5rq[zlp]. Или вот ещё сравните:
int counter; bool alarm; for (counter = 0; counter < 100; counter++) < if (counter == 99) < alarm = true; >>
int plf5ojvb; bool jht4hnv; for(plf5ojvb=0; plf5ojvb
А если переменных не две, а полтора десятка? Читать и понимать такое сложно. Этот вид обфускации простой для быстрого применения, но малоэффективный: меняются только названия методов, а общая схема работы остается неизменной.
Современные IDE умеют искать использования методов в коде, это очень упрощает анализ обфусцированного кода. Обход такой обфускации вопрос времени.
Преобразование данных более сложная и эффективная операция. Она включает в себя изменение и создание новых типов данных и применение к ним комбинаторики. Например, число 9 можно представить, как 10000000001 (количество нулей), 210019 (двоичное число между идентификаторами начала и конца), 32 (3 2 ) и ещё огромным количеством способов. Или замена выражения i=1 для простого цикла перечисления на i0=21 c последующим представлением через другие константы — i=i0/i1-i2, где i1=7, i2=2. Что касается типов данных, то в простейшем случае можно представлять 32-битные числовые данные перемножением 16-битным на некоторую переменную со значением 16.
Преобразование управления — нарушение естественного хода программы, для чего используются непрозрачные предикаты. То есть это случай, когда результат исполняемых действий трудно предугадать в ходе заданной процедуры. В простейшем случае это создание дополнительных блоков кода: в одном выполняются вычисления, в другом происходит наследование, а в каком-то общем — несколько ложных операций, лишь одна из которых действительная. В более сложных ситуациях создаётся комплексная карта замещений и трансформаций, до неузнаваемости меняющих общую структуру кода.
Профилактическая обфускация защищает ваш код от деобфускации специальными программами-деобфускаторами. Они основываются на обнаружении неиспользуемых кусков кода, нахождении наиболее сложных структур (фрагментов максимальной важности) и анализе статистических и динамических данных. Именно борьба с этими операциями — наиболее сложный и эффективный процесс обфускации. Здесь необходимо максимально точно подойти к анализу исходных данных, задействовать максимум предоставленных ресурсов, учесть подходы потенциальных оппонентов.
Без опыта ручной обфускации создать непроходимый лабиринт не получится, требуется помощь специалистов. В сети можно отыскать массу бесплатных, платных и взломанных обфускаторов. Последний вид наиболее бесполезен: программа защиты, не способная защитить себя — сомнительный выбор.
Бесплатные обфускаторы неплохи, но в силу своего распространения имеют универсальный и не самый сложный подход. Плюс, надежность процедуры запутывания также можно поставить под вопрос — если программа легко доступна, то ее алгоритмы несложно проанализировать и найти обратный алгоритм. Поэтому, если вы действительно собрались хорошо заработать на своем коде — не пожалейте денег на организацию грамотной обфускации.
Хорошо запутанная программа, закрытая надёжным паролем — уже головная боль для потенциального взломщика. Но и обфускация еще не финальный оплот защиты.
В следующей части — защита от отладчиков, протекторы, лицензии и программы слежения.
А тем, кто определился с тем, что хочет стать программистом, рекомендуем профессию «Веб-разработчик».
Источник: gb.ru
Что такое обфускация кода
Ситуация: вы написали уникальный алгоритм обработки текста, который подсказывает пользователю, как грамотно что-то написать (например, письмо клиенту или коммерческое предложение). Этот код исполняется прямо на клиенте, в виде JS-библиотеки. Вы хотите продавать доступ к этому сервису.
Проблемы:
Как только один пользователь получил доступ к этому коду, он может заглянуть в него, понять принцип действия и создать такой же сервис самостоятельно.
Если прятать код на сервер и давать пользователю только сделать запрос и получить ответ, то нужно существенно повышать стоимость сервиса: нужно ведь платить за аренду сервера. И быстродействие кода снизится.
Решение — использовать обфускацию кода. Звучит сложно, сейчас поясним.
Что такое обфускация кода
Обфускация — это когда мы берём понятный код и делаем из него непонятный, но работающий точно так же. Смысл обфускации в том, чтобы глядя на ваш код никто не разобрался, как именно он работает. Вы, кстати, тоже не разберётесь — если нужно будет что-то поправить в программе, то это нужно будет делать в исходном, а не обфусцированном коде.
Зачем это нужно
Причин для обфускации может быть несколько:
- защитить идею от копирования — как в нашем примере с текстовым редактором;
- сделать так, чтобы никто кроме вас не мог поддерживать этот код — а вы могли и получали за это деньги;
- скрыть какие-то значения или действия — например, если в программу встроена проверка пароля или бэкдор;
- защитить алгоритм от взлома — злоумышленник может проанализировать код программы, выяснить, какая часть отвечает за лицензию, и обойти её, в итоге он будет пользоваться программой бесплатно.
В любом случае цель обфускации — скрыть логику работы исходного кода.
Как работает обфускатор
Задача обфускатора — используя возможности того же языка программирования (или машинного кода) поменять исходный код на что-то другое, но работающее точно так же. Например, в проекте про тетрис на JavaScript у нас есть такой фрагмент кода:
// поворачиваем матрицу на 90 градусов function rotate(matrix) < const N = matrix.length — 1; const result = matrix.map((row, i) =>row.map((val, j) => matrix[N — j][i]) ); // на входе матрица, и на выходе тоже отдаём матрицу return result; >
После обфускации он может выглядеть так:
function ks8s(fk93f) u5tlo2.k5hvf8((js893llq,grehg7dk)=>fk93f[plq89b-grehg7dk][gts74h2]));return q0lj34;>
Этот код делает всё то же самое — поворачивает матрицу на 90 градусов, только в нём очень сложно разобраться. Вот что мы для этого сделали:
- заменили понятные имена переменных на названия вроде k5hvf8;
- убрали все пробелы, комментарии и переносы строк;
- заменили простые конструкции типа i − 1 на —i — работает точно так же, а выглядит уже сложнее
Это самая простая обфускация кода, которая может сработать для новичков, но опытных программистов она не запутает. Чтобы сделать код сложнее, используют ещё другие приёмы.
Изменение данных. Число 16 в программе можно записать как 10000 — это 16 в двоичной системе счисления, или как 0010 в шестнадцатеричной. Можно добавить перед ним 8 нулей и получить 0000000016, потом добавить перед ним единицу, а как понадобится исходное число — убрать единицу и все нули из начала. Можно даже поменять тип данных, чтобы компьютер выделил другой диапазон памяти, но такое работает не всегда.
Дополнительные блоки кода и запутанное управление. В программу можно добавить сколько угодно дополнительных функций, которые будут ссылаться друг на друга и вызывать в разных местах тот код, который нам нужен. В итоге другой программист просто не сможет понять, в какой последовательности выполняются команды и какая вообще там логика.
Ручная и машинная обфускация
Раньше обфускацией занимались вручную или с помощью скриптов: меняли названия переменных, добавляли ложные точки вызова функций и использовали сложную работу с памятью в Ассемблере. Это отнимало много времени, но и дешифровать этот код обратно было крайне сложно.
Сейчас почти весь код меняется с помощью программ-обфускаторов. Для каждого языка есть свои программы и настройки, поэтому сейчас запутать свой код стало проще, чем раньше. С другой стороны, появились программы, которые анализируют финальный код и пытаются распутать эти сложные команды во что-то попроще — так работают дизассемблеры. Поэтому чаще всего программисты обфусцируют исходный код, компилируют его, а потом обфусцируют ещё и машинный код.
В любом случае обфускация сильно усложняет обратную разработку, но не делает её невозможной — при должном желании можно распутать почти любой код или хотя бы понять логику его работы.
Минусы обфускации
У обфускации есть два больших минуса, из-за которых большинство программистов ей не пользуются или делают это редко:
❌ Программа работает медленнее — иногда при усложнении кода одна команда заменяется на 3–5 других команд. В итоге количество команд в программе увеличивается, и компьютеру нужно больше времени, чтобы их обработать.
❌ Обфусцированный код почти невозможно править без доступа к исходному коду. Если разработчик после преобразования случайно удалит исходник программы, ему проще будет написать её заново, чем пытаться разобраться в результате.
JSFuck как обфускатор для JavaScript
Напоследок расскажем об интересном проекте — JSFuck. Ребята вдохновились тем, как устроен язык Brainfuck, в котором всего 8 команд:
Они использовали особенности работы с памятью, данными и выражениями в JavaScript, чтобы преобразовать любую команду JS в подобный код из скобок, плюсиков и восклицательных знаков. Это тоже можно использовать как обфускатор, хотя изначально у ребят была идея просто поглумиться над кодом.
Выполните этот код в консоли браузера, чтобы увидеть пасхалку, которую мы вам приготовили с помощью JSFuck:
Читаете «Код»? Зарабатывайте на коде
Сфера ИТ и разработки постоянно растёт и требует новых кадров. Компании готовы щедро платить даже начинающим разработчикам, а опытных вообще отрывают с руками. Обучиться на разработчика можно в «Яндекс Практикуме».
Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Источник: thecode.media