Реверс-инжиниринг NET-приложений. Часть первая: Введение

Реверс-инжиниринг NET-приложений. Часть первая: Введение

Данный цикл публикаций представляет собой нечто вроде «саги», где мы в основном будем обсуждать исследование NET-приложений.

Автор: Суфиан Тахири (Soufiane Tahiri)

Предупреждение

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

Все техники, которые будут показаны в этом цикле статей, предназначены только демонстрации на практике описанных концепций и методов. Цель этих публикаций, также как и других статей, написанных мной (Суфианом Тахири) - поделиться знаниями и улучшить методы реверс-инжиниринга.

Пожалуйста, помните о том, что дизассемблирование / исследование приложений запрещено почти всеми международными законами. Если вам понравилась какая-либо программа – КУПИТЕ ЕЕ.

Введение

Данный цикл публикаций представляет собой нечто вроде «саги», где мы в основном будем обсуждать исследование NET-приложений. Последняя стабильная версия Microsoft .NET Frameworks для Visual Studio 2012 - 4.5 (4.5.50709) от 15 августа 2012 года. Также эта версия распространяется с Windows 8 и Windows Server 2012. Однако, несмотря на столь широкое распространение платформы, существует недостаток статей по исследованию приложений разработанных с использованием NET-технологии.

Я постараюсь восполнить этот недостаток и в первой статье расскажу об основах архитектуры NET в целях прояснения некоторых моментов для реверс-инженеров.

Перед началом чтива я настоятельно рекомендую вам потратить несколько часов на изучение как минимум одного языка, который используется при разработке NET-приложений (Visual Basic .NET или С#). Некоторые считают, что исследование NET-программ проще, чем исследование «традиционных» приложений, однако, с моей точки зрения, это ошибочное мнение.

Концепцию платформы NET можно сравнить с концепцией JAVA и виртуальной машины JAVA (по крайней мере, когда речь заходит о компиляции приложения). В отличие от традиционных языков программирования (например, C/C++), где происходит компиляция в исполняемый машинный код, приложения, разработанные на платформе NET frameworks, компилируются в промежуточный язык Common Intermediate Language (CIL или Microsoft Common Intermediate Language MSIL), который можно сравнить с байткодом Java-программ. Преобразование в машинный код производится средой Common Language Runtime (CLR) во время выполнения программы.

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

Рисунок 1. Наглядное представление спецификации общеязыковой инфраструктуры (Common Language Infrastructure, CLI) / Wikipedia

Что же это дает реверс-инженеру?

По существу, каждое скомпилированное NET-приложение является не более чем представлением языка Common Intermediate Language, в котором сохранены все имена из исходного текста программы.

Строго говоря, зная язык CIL, мы можем идентифицировать высокоуровневые языковые инструкции и структуру программы. Все это означает, что мы можем из CIL-версии восстановить первоначальный исходный код и даже выбрать язык исходного текста (однако это весьма утомительное занятие).

Когда речь заходит о NET-приложениях мы говорим о «рефлексии» (reflection), а не «декомпиляции». Техника «рефлексии» позволяет получить информацию о классах (или сборке) во время выполнения программы. Мы можем получить все свойства, методы, функции и т. д. с параметрами и аргументами, также можно получить все интерфейсы, структуры и т. д.

Существует огромная масса инструментов, которые могут «отразить» исходный текст скомпилированного исполняемого NET-файла; утилита Reflector прекрасно подходит для решения этой задачи. При помощи нее вы можете просматривать информацию о классах, декомпилировать и анализировать NET-программы и компоненты. Reflector позволяет просматривать и искать CIL-инструкции, ресурсы и XML-документацию, которая содержится в NET-сборке. Однако Reflector не единственная утилита, которая пригодится нам при исследовании NET-приложений. О других инструментах я буду рассказывать по мере их использования.

О чем вы узнаете из первой статьи?

В первой статье вы научитесь использовать Reflector для исследования, созданного мной, простейшего Crack-Me. Здесь не преследуется цель изложить актуальные методы защиты приложений (об этом будет рассказано в следующих статьях).

Практика

Наш Crack-ME представляет собой простейшую форму, которая запрашивает пароль. Я создал ее, чтобы показать вам основы исследования NET-приложений. Обычно мы начинаем с постановки задачи и изучения поведения объекта. Такой подход позволяет определить, что мы будем искать внутри исходника.

После ввода неверного пароля появляется сообщение об ошибке:

Посмотрим, почему этот кусок скомпилированного кода выдает сообщение «Invalid password». После открытия Reflector на главной панели мы можем выбрать язык исходного текста. Я выберу Visual Basic, но решение, конечно, за вами.

Рисунок 2. Выбор основного языка

Загрузим Crack-ME в программу (File > Open menu) и начнем поиск интересующих нас участков кода.

Технически, Crack-ME анализируется и помещается в древовидную структуру. Мы развернем те узлы, которые нас интересуют:

Рисунок 3. Загруженный Crack-ME

Вы можете развернуть узел, если кликните на «+»:

Продолжая углубляться внутрь дерева, вы увидите «внутренности» Crack-ME:

Как видно из рисунка Crack-ME состоит из Ссылок, Кода и Ресурсов.

  1. Код: содержит всякие интересности, все, что нам нужно в данный момент находится внутри ветки InfoSecInstitute_dotNET_Reversing (это Namespace).
  2. Ссылки: по сути «импорты» и «заголовочные файлы» используемые в других PE-файлах.
  3. Ресурсы: сейчас этот раздел для нас не важен, но он схож с ресурсами в других Windows-программах.

Раскрыв ветку с кодом, мы увидим следующее дерево:

Reflector нашел только одну форму внутри нашего Crack-ME с именем Form1 (со всеми переменными, процедурами, функциями и графическими элементами). Как говорилось ранее, все имена элементов соответствуют оригинальным именам, которые используются в исходном тексте приложения, что позволяет легко определить назначение каждого элемента. К примеру, функция btn_Chk_Click(Object, EventArgs), скорее всего, выполняется при нажатии на кнопку «bnt_Chk», а функция btn_About_Click(Object, EventArgs) вероятно выполняется при нажатии на кнопку «btn_About».

Поскольку приложение учебное, в нем только одна форма и несколько функции, и это упрощает нашу задачу; в данный момент нас интересует, что происходит по нажатию кнопки «Check» (кнопка btn_Chk) и алгоритм работы функции btn_Chk_Click (), логика работы которой будет отображена на языке, выбранном при запуске Reflector (см. рисунок 2).

Для просмотра исходного текста функции дважды щелкните на имя функции. Reflector покажет декомпилированный исходный код:

Теперь мы полностью понимаем предназначение этой функции. Даже тот, кто знаком лишь с основами программирования проймет, что процедура сравнивает введенный пароль с выражением «p@55w0rd!». Введя комбинацию «p@55w0rd!», получим следующий результат:

Все оказалось очень просто! В одной из следующих статей мы рассмотрим более продвинутые техники (например, изменение Crack-ME так, чтобы был доступен ввод любых паролей).

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

Ссылки

Ваш провайдер знает о вас больше, чем ваша девушка?

Присоединяйтесь и узнайте, как это остановить!