Ни для кого не секрет, что из скомпилированных сборок (exe и dll) для платформы .NET может быть легко восстановлен код на языках высокого уровня (C#, VB.net). Это означает не только то, что если в программе имеется система лицензирования, то она может быть легко снята; но и то, что ваш исходный код могут скопировать, например, нечистые на руку конкуренты. Чтобы обезопасить себя от подобных угроз большинство разработчиков коммерческого софта используют разного рода обфускаторы.
Очевидно, что обфускация как один из этапов защиты актуальна только для коммерческого софта.
Защищать программу, если в ней используется система регистрации по серийному номеру или активация, требуется от «кракеров», которые либо за неимением денег (если программа дорогая), либо из любви к искусству пишут краки. Выяснить, где находится нужный условный переход, или проверка серийника намного тяжелее, если перед вами в лучшем случае «узел» из IL-кода, чем если мы видим легко понятный C#-код. Это, конечно, не панацея, но добавляет n-ное количество минут, необходимое для взлома. (Если n достаточно велико, то пытаться ломать будут только очень упорные индивиды ;)
Так же надо защищать от одной из разновидностей промышленного шпионажа. Тут всё просто: достаточно удалить метаданные и запутать остальные части программы настолько, что конкуренту будет дешевле написать программу с нуля, чем разбирать вашу.
Обычно для просмотра метаданных сборки используется .NET Reflector. Он имеет простой и понятный интерфейс, а так же возможность расширить функциональность плагинами.
Скриншоты и примеры использования новички могут найти на сайте рефлектора.
Также существует несколько коммерческих просмотрщиков сборок и декомпиляторов, возможно я перечислю их потом (триал версии разбирают только половину сборки, а «счастливые обладатели» лицензионных версий сообщают о не очень больших отличиях от рефлектора).
.NET-приложения пытаются защищать двумя основными методиками: непосредственно обфускацией IL-кода (когда на выходе получается почти-валидная* .net-сборка, и её можно выполнять на немодфицированном MS.NET или mono). И упаковкой — модификацией сборки так, что на выходе получается winapi-приложение, содержащее в себе распаковывающий модуль и упакованый IL-код.
* — сборка может содержать невалидные IL-инструкции, которые однако не будут выполняться. И сборка в целом выглядит «нормальной» и может быть запущена на любом поддерживаемом рантайме
С обфускацией вроде всё ясно: подаём на вход .net сборку, получаем на выход .net сборку, всё работает примерно так же. Никаких лишних «спрятанных» данных, всё находится на месте, только запутано и переименовано в что-то бесполезное.
В случае с упаковщиком нас ожидают некоторые проблемы:
Разнообразные «защитники» (protectors) обычно объединяют в себе оба подхода и будут рассмотрены в обеих частях данного обзора.
Первым и самым основным инструментом является рефлектор. Обычно каждый качает к нему плагины на свой вкус. Я порекомендую лишь один: reflexil, он позволяет менять байткод методов, свойства сборки, и содержит удобную утилиту удаления strong-name. С помощью этого плагина очень удобно делать краки ;)
Если сборка подверглась обфускации, то просматривать её в рефлекторе не очень удобно, поэтому перед изменением (или вытаскиванием кода) её надо «деобфусцировать», для этого применяются разнообразные готовые деобфускаторы (коих в интернете можно найти очень много).
Также полезно иметь собственный деобфускатор, который всегда легко «допилить» до нужд определённой задачи.
Если мы будем иметь дело с упаковщиками, то нам понадобятся различные инструменты для native reverse engineering, такие как дебаггер (WinDbg, OllyDbg), дампер (PE tools), редактор PE-файлов (например CFF Explorer). А так же специфичные для .net-распаковки инструменты: Generic .NET Unpacker, .net dumper (KDD), .Net Assembly Rebuilder. С ними мы познакомимся во второй части обзора.
Всё, на этом моё словоблудие заканчивается, следующий пост будет содержать в себе больше подробностей (даже с картинками) ;)
Продолжение →
Примерное содержание следующих постов:
Зачем и от кого защищаемся?
Очевидно, что обфускация как один из этапов защиты актуальна только для коммерческого софта.
Защищать программу, если в ней используется система регистрации по серийному номеру или активация, требуется от «кракеров», которые либо за неимением денег (если программа дорогая), либо из любви к искусству пишут краки. Выяснить, где находится нужный условный переход, или проверка серийника намного тяжелее, если перед вами в лучшем случае «узел» из IL-кода, чем если мы видим легко понятный C#-код. Это, конечно, не панацея, но добавляет n-ное количество минут, необходимое для взлома. (Если n достаточно велико, то пытаться ломать будут только очень упорные индивиды ;)
Так же надо защищать от одной из разновидностей промышленного шпионажа. Тут всё просто: достаточно удалить метаданные и запутать остальные части программы настолько, что конкуренту будет дешевле написать программу с нуля, чем разбирать вашу.
Обычно для просмотра метаданных сборки используется .NET Reflector. Он имеет простой и понятный интерфейс, а так же возможность расширить функциональность плагинами.
Скриншоты и примеры использования новички могут найти на сайте рефлектора.
Также существует несколько коммерческих просмотрщиков сборок и декомпиляторов, возможно я перечислю их потом (триал версии разбирают только половину сборки, а «счастливые обладатели» лицензионных версий сообщают о не очень больших отличиях от рефлектора).
Обфускаторы и упаковщики
.NET-приложения пытаются защищать двумя основными методиками: непосредственно обфускацией IL-кода (когда на выходе получается почти-валидная* .net-сборка, и её можно выполнять на немодфицированном MS.NET или mono). И упаковкой — модификацией сборки так, что на выходе получается winapi-приложение, содержащее в себе распаковывающий модуль и упакованый IL-код.
* — сборка может содержать невалидные IL-инструкции, которые однако не будут выполняться. И сборка в целом выглядит «нормальной» и может быть запущена на любом поддерживаемом рантайме
С обфускацией вроде всё ясно: подаём на вход .net сборку, получаем на выход .net сборку, всё работает примерно так же. Никаких лишних «спрятанных» данных, всё находится на месте, только запутано и переименовано в что-то бесполезное.
В случае с упаковщиком нас ожидают некоторые проблемы:
- Наша сборка будет выполняться теперь только под виндой (либо аккуратно настроенным mono+wine)
- Упаковщик, который передаёт на вход mscoree оригинальную сборку, снимается за 1 минуту, и не имеет смысла для защиты. Упаковщики, которые перехватывают внутренние функции mscoree очень сильно зависят от версии фреймворка, и вызывают у некоторых антивирусов false positive реакции. Перехват внутренних функций вообще дело тонкое и неблагодарное.
- Упаковщики являются native-программами, и не дают скомпилироваться вашему приложению в x86-64 код там, где это доступно (а в некоторых случаях это даёт большой прирост производительности)
- Для нормального выполнения среде .net в любом случае требуется доступ к оригинальному IL-байткоду. И даже preJITted-сборки должны его в себе содержать. А значит и получить этот байткод тоже реально.
- И, на последок, цитата: «if it runs it can be unpacked»
Разнообразные «защитники» (protectors) обычно объединяют в себе оба подхода и будут рассмотрены в обеих частях данного обзора.
Инструменты реверсера
Первым и самым основным инструментом является рефлектор. Обычно каждый качает к нему плагины на свой вкус. Я порекомендую лишь один: reflexil, он позволяет менять байткод методов, свойства сборки, и содержит удобную утилиту удаления strong-name. С помощью этого плагина очень удобно делать краки ;)
Если сборка подверглась обфускации, то просматривать её в рефлекторе не очень удобно, поэтому перед изменением (или вытаскиванием кода) её надо «деобфусцировать», для этого применяются разнообразные готовые деобфускаторы (коих в интернете можно найти очень много).
Также полезно иметь собственный деобфускатор, который всегда легко «допилить» до нужд определённой задачи.
Если мы будем иметь дело с упаковщиками, то нам понадобятся различные инструменты для native reverse engineering, такие как дебаггер (WinDbg, OllyDbg), дампер (PE tools), редактор PE-файлов (например CFF Explorer). А так же специфичные для .net-распаковки инструменты: Generic .NET Unpacker, .net dumper (KDD), .Net Assembly Rebuilder. С ними мы познакомимся во второй части обзора.
Всё, на этом моё словоблудие заканчивается, следующий пост будет содержать в себе больше подробностей (даже с картинками) ;)
Продолжение →
Примерное содержание следующих постов:
- 1. Обфускаторы.
- 1.1. Методики
- 1.2. Обзор обфускаторов
- 1.3. Методики деобфускации
- 1.4. Деобфускаторы
- 2. Упаковщики.
- 3. Использованные источники, и что ещё почитать по теме