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

Как работает Reverse engineering

Определение для этой области знаний можно найти на Wiki. Мы будем говорить о варианте, который относится к программному обеспечению.

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

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

Списки ресурсов можно найти достаточно просто, для примера можно изучить вот этот.

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

Для успешного разбора нужно обладать начальными данными:

  1. На каком языке программирования написано приложение.

  2. После идентификации языка программирования желательно бегло ознакомиться с его синтаксисом.

  3. Какие форматы файлов использует приложение.

  4. Какая исполняемая среда используется для приложения.

  5. Где располагается документация для пункта 1, 3 и 4.

  6. Знание принципов работы сетевого взаимодействия среды исполнения приложения.

Следующий пункт может быть опциональным:

  1. Специализированные приложения для работы с языком программирования:

    • отладчики;

    • анализаторы формата файлов;

    • профилировщики среды исполнения;

    • анализаторы сетевого взаимодействия.

Почему 7-й пункт опционален? Потому что некоторые среды исполнения могут не предоставлять все инструменты для изучения приложения и придется либо самостоятельно создавать инструмент для анализа, либо изучать приложение частично, опуская, возможно огромные куски алгоритма.

Какое приложение будем исследовать

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

  • Из чего состоит веб-приложение?

  • Какие наименования обработчиков есть в приложении?

  • Где находится код, который обрабатывает запросы?

В качестве примера попробуем разобраться с вот этим проектом. И сразу приступим к исследованию.

На каком языке программирования написано приложение?

При изучении программного кода, который был уже скомпилирован ответ на этот вопрос достаточно прост. Там скорее всего будет только 1 язык. В случае с веб-приложениями это может быть несколько сложнее.

Начнем с простого. Так как проект располагается на github, то по тегам можно определить какой язык программирования. Найти эти данные можно справа от описания репозитория. Для нашего проекта эти метки выглядят вот так:

Похоже, что тут придется иметь дело не с одним языком. Почему так? На просторах сети нашлась достаточно интересная картинка, которая должна внести немного ясности:

На картинке изображена схема того как веб-приложение может быть имплементировано. Существует несколько частей:

  • Backend - часть, которая работает на сервере.

  • Frontend - часть, которая должна работать в пользовательском приложении, чаще всего в браузере.

Для каждого из этих двух элементов существуют свои языки программирования. И так как в веб-приложениях все языки делятся по признаку выполняемых задач и окружения где запускается алгоритм. Поэтому их может быть несколько.

И так разбиение в случае нашего проекта такое:

  • FrontEnd:

    • SCSS

    • HTML

    • JavaScript

    • CSS

  • Backend:

    • C#

    • XML

Почему именно так? 2-3 минуты поиска в сети аббревиатур каждого языка и чтение wiki. Поиск данных по языкам программирования завершен. Перейдем в следующему этапу.

Синтаксис языков программирования

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

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

  1. Переменная.

  2. Логическое выражение.

  3. Арифметическое выражение.

  4. Условные операторы.

  5. Циклы.

  6. Функции.

  7. Классы.

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

Какие форматы файлов использует приложение

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

  • Языки Frontend интерпретируемые, поэтому данные будут храниться в текстовом виде, с некоторыми исключениями (ресурсы и использование WebAssembly)

  • языки Backend могут быть компилируемыми и интерпретируемыми. В первом случае будут приложения в нативном представлении для выбранной в качестве среды выполнения операционной системы, во втором случае это будут текстовые файлы или промежуточный код, который будет обрабатываться своей виртуальной машиной

Для анализа языков, которые будут храниться в текстовом виде хорошо подходит IDE, которая позволяет работать с языками из проекта. Так как у нас в проект включен язык программирования C#, то выбор среды изучения исходного кода предопределен - Visual Studio и пакет SDK для платформы .Net.

В случае, если бы мы получили уже собранный проект, то для разбора файлов скомпилированных из C#, мы бы изучали их череp dnspy или аналогичный проект.

Алгоритм приложения

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

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

В веб-приложениях это определение так же остается актуальным. Поэтому для упрощения поиска именно алгоритма приложения обратимся к вот такой документации. Документация содержит в себе так называемый Life Cycle приложения, то есть определяет границы существования приложения и границы работы рантайма. С помощью таких описаний можно найти инструкцию к любому языку программирования и набору библиотек, который используется для создаваемого приложения. В нашем случае это ASP.NET. Если подытожить, то вот эта картинка из документации дает нам все необходимые знания:

В итоге:

  1. Запрос от пользователя приходит в веб сервер.

  2. Запрос обрабатывается ISAPI ASP.NET.

  3. Запрос заполняется в объект HTTPContext.

  4. Запрос обрабатывается алгоритмом, который написал программист и может генерировать ответы в зависимости от решений.

Тоесть в IDE уже можно собрать классы и методы, которые используют HTTPContext и начинать подробное исследование алгоритма.

Вот так выглядит часть проекта открытого в IDE:

Из документации можно так же вынести, что весь код, который был написан, будет выноситься в обработчики, которые должны быть зарегистрированы о одном общем файле. В нашем проекте это файл Web.config. Кусок файла представлен ниже:

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

Выводы

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

Статью подготовил мой коллега, преподаватель OTUS - Александр Колесников. В преддверии старта курса Reverse Engineering хочу пригласить всех желающих на бесплатный интенсив в рамках которого мы разберём работу mbr руткита, Проанализируем его ключевые этапы и стадии развёртывания. Регистрация доступна по ссылке.

Комментарии (2)


  1. raven19
    31.03.2022 18:57
    +1

    При изучении программного кода, который был уже скомпилирован ответ на этот вопрос достаточно прост. Там скорее всего будет только 1 язык. В случае с веб-приложениями это может быть несколько сложнее.

    Очень неквалифицированное утверждение. Даже если Вы изучаете программный код "Hello Wold", то вряд ли там будет десяток языков, но уж парочку, скорей всего точно найдёте (среда, и run-time) скорей всего будут изготовлены на отличном от того языка, на котором Вы "развлекаетесь". А уж в серьёзных приложениях ...


  1. demimurych
    01.04.2022 07:13

    Позвольте мне, человеку с 30 летним опытом в области Reverse engineering, высказать ряд замечаний к этому материалу.

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

    То есть я настаиваю на том, что знания языка программирования вообще не нужно. Нужно только умение использовать подходящий инструмент и способность выделять абстракции. Способность эта некоторым доступна от рождения, другие же ее могут легко натренировать.

    Это легко понять на примере анекдота: с чего начинается любая инструкция по эксплуатации, написанная для "условных славян": ну что дурашка сломал?

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

    Это и есть типичный реверс.

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

    Так что я с большим скепсисом отношусь к тому курсу что будет читать автор. Очевидно что он не обладает достаточным опытом для преподавания таких навыков.

    Безусловно я могу ошибаться.