Что значит объект файл упакован
Привет, хабровчане. В рамках курса "Reverse-Engineering. Basic" Александр Колесников (специалист по комплексной защите объектов информатизации) подготовил авторскую статью.
Также приглашаем всех желающих на открытый вебинар по теме «Эксплуатация уязвимостей в драйвере. Часть 1». Участники вебинара вместе с экспертом разберут уязвимости переполнения в драйверах и особенности разработки эксплойтов в режиме ядра.
Статья расскажет о подходах к анализу запакованных исполняемых файлов с помощью простых средств для обратной разработки. Будут рассмотрены некоторые пакеры, которые применяются для упаковки исполняемых файлов. Все примеры будут проведены в ОС Windows, однако изучаемые подходы можно легко портировать на любую ОС.
Как защититься от подозрительных упаковщиков
Чтобы защититься от подозрительных упаковщиков, следует установить антивирус — программное обеспечение для защиты от вредоносных программ на всех своих устройствах (включая ПК, ноутбуки, компьютеры Mac, смартфоны и планшеты) и своевременно устанавливать обновления. Kaspersky Internet Security для всех устройств обнаруживает самые разнообразные вредоносные и подозрительные программы на ПК Windows, устройствах на базе Mac OS, смартфонах и планшетах Android.
Другие статьи и ссылки, связанные с подозрительными упаковщиками
Инструментарий и настройка ОС
Для тестов будем использовать виртуальную машину под управлением ОС Windows. Инструментарий будет содержать следующие приложения:
установленный по умолчанию плагин x64dbg Scylla;
Самый быстрый и простой способ провести распаковку любого исполняемого файла — применить отладчик. Но так как мы будем также рассматривать язык программирования Python, то может понадобится проект:
uncompile6 проект, который позволяет разобрать байткод виртуальной машины Python;
pyinstallerExtractor инструмент для распаковки архива pyInstaller.
Бесплатные утилиты
Наши бесплатные утилиты помогают обеспечить защиту ваших устройств на базе Windows, Mac и Android.
Что нужно знать о подозрительных упаковщиках
Основные отличительные особенности, классифицирующие поведение подозрительных упаковщиков, — это тип и количество упаковочных алгоритмов, использованных для упаковки. Подозрительные упаковщики классифицируются по следующим типам поведения:
- Подозрительный упаковщик
Объекты, сжатые с помощью упаковщиков, которые предназначены для защиты вредоносного кода от обнаружения антивирусными продуктами. - Многократная упаковка
Файлы, многократно упакованные несколькими упаковщиками. - Редко используемый упаковщик
Файлы, сжатые редко встречающимися упаковщиками, например такие, в которых реализована какая-либо концептуальная идея.
Пробные версии
Попробуйте наши решения. Всего за несколько кликов вы можете скачать бесплатные пробные версии нашего продукта и проверить их в действии.
Python-модуль pefile
Python-модуль pefile позволит обойтись при анализе PE-файлов исключительно интерпретатором Python. С ним практически все операции по базовому статическому анализу можно реализовать путем написания небольших скриптов. Прелесть всего этого в том, что заниматься исследованием PE-файлов можно в Linux.
Модуль присутствует в PyPi, и установить его можно через pip:
Ну и в завершение всего списка весьма популярный и востребованный инструмент, ставший своеобразным стандартом в среде антивирусной индустрии, — проект Yara. Разработчики позиционируют его как инструмент, который помогает исследователям малвари идентифицировать и классифицировать вредоносные сэмплы. Исследователь может создать описания для разного типа малвари в виде так называемых правил, используя текстовые или бинарные паттерны.
О компании
Узнайте больше о том, кто мы, как мы работаем и почему наша главная цель - сделать цифровой мир безопасным для всех.
Основные атаки программ-вымогателей
Решение задания flag
Нажимаем на иконку с подписью flag, и нам говорят, что мы можем скачать исполняемый файл.
Нам не дают исходный ход. Для анализа программы я буду использовать Cutter. Откроем Cutter, укажем путь к исполняемому файлу.
Наблюдаем очень странный граф программы и отсутствие функции main.
Проверим программу в DetectItEasy, который говорит, что наш файл упакован UPX.
Распакуем программу следующей командой.
Теперь, если закинуть программу в Cutter, можно наблюдать функцию main и распакованные строки.
В прошлых двух статьях я рассказал об особенностях форматов данных звуковой подсистемы современных игр. Чтобы не утомлять читателей, перейду к несколько другой теме. Какой бы движок не использовала игра, ей нужно где-то хранить ресурсы и извлекать их оттуда в нужный момент. Иногда ресурсы в архиве имеют как идентификатор, так и читабельное имя файла. Но существует довольно много движков, где имён у файлов нет, а есть только хеш. Как же в таком случае можно что-то разобрать в ресурсах?
Рассмотрим это на примере довольно редкого движка bitsquid. Он простой и компактный, но, тем не менее, имеет все необходимые для современных игр возможности. В прошлом году bitsquid вместе с его разработчиком был куплен компанией Autodesk, и теперь они собираются скрестить его с Maya и сделать свой собственный игровой движок, который, как они обещают, будет чем-то невероятным.
Чтобы любой желающий мог сам посмотреть на процесс, воспользуемся демо-версией игры The showdown Effect, которая к тому же совсем небольшого размера (около 250МБ). Зайдя в папку content, в которой, очевидно, и находятся все ресурсы, обнаруживаем там пару десятков файлов вот с такими замечательными именами:
Должно быть это файлы пакетов/архивов с ресурсами. Откроем один из них и посмотрим, что там внутри. А там на протяжении всего файла не видно ни таблиц, ни текстов, ни каких-то осмысленных чисел — сплошная мешанина байтов:
Это обычно означает, что все данные зашифрованы и/или запакованы. В данном случае почти в самом начале комбинация байт 78 9C (выделены зеленым) однозначно говорит, что данные сжаты zlib. Попробуем для начала распаковать файл «вручную». Для этого применим offzip — утилиту, которая просто пытается распаковать любые последовательности байт внутри файла, как если бы они были упакованы zip или zlib, сколько бы их ни было в файле и в какой последовательности.
Выполняем следующую команду: offzip -a 9e13b2414b41b842 unp 0
Опция -a здесь означает, что надо попытаться найти в файле все сегменты, сжатые zlib, а не рассматривать файл как единственный сжатый блок. «unp» — папка для распаковки (её нужно предварительно создать). «0» — начальное смещение, то есть искать с самого начала файла.
Как видим, 98% содержимого файла распаковалось в кучу сегментов по 64кБ каждый. Проанализировав их содержимое, можно заметить, что они представляли из себя единое целое — один большой файл, который был просто порезан на кусочки по 64кБ и затем сжаты по отдельности zlib-ом. В принципе могло быть и наоборот — каждый исходный ресурс сжат отдельно и потом все они слеплены в один большой файл. Но в нашем случае файл один, поэтому распаковать его можно такой командой:
offzip -a -1 9e13b2414b41b842 unp 0
Опция -1 означает, что все обнаруженные распакованные сегменты нужно соединить. В итоге мы получаем распакованный файл, который опять же надо изучить. Помотав его туда-сюда, можно обнаружить, что внутри имеются и lua-скрипты, и звуки, и текстуры, теперь уже несжатые, но слепленные все вместе.
Наша задача — разделить файл на отдельные ресурсы, притом желательно каким-то образом узнать их названия. Обратимся к началу файла. Здесь у нас что-то непонятное, потом много нулей, и потом видимо начинается какая-то таблица. Похоже что строки в ней имеют длину 16 байт, причем интересно, правая половина всегда разная, а в левой половине наблюдаются повторяющиеся числа (выделены зеленым). Заметим также, что название самого файла иногда повторяется внутри него в одной из строчек.
Далее, оказывается, что последняя строка в таблице почему-то такая же, как первая. К тому же, если посмотреть несколько файлов, похоже, что первое число в них — это как раз число строк таблицы (правда, минус один). Сопоставив все эти данные, можно заключить, что это таблица, где записаны имена ресурсов в виде хеша, отдельно имя ресурса и его тип. А последняя строка — это уже не таблица, а информация о первом ресурсе, где в начале видимо как раз идёт его хеш, а потом должны быть размер, другие параметры, и сам файл. Чтобы убедиться в этом, поищем остальные числа в файле, и, конечно же, они находятся, причём именно в той последовательности, как идут в таблице.
Хорошо, теперь осталось разобрать формат записей и попытаться угадать захешированные названия. В принципе может быть так, что игра обращается к ресурсам уже по хешу, и исходных названий в ней не осталось, в таком случае названий мы не найдём. Но к счастью, чаще всего их можно найти, угадать, или вычислить по коду или скриптам. Кстати, насчет скриптов: мы уже видели, что здесь используется lua, значит, скорее всего, расширение для таких файлов будет «lua». Вид используемого хеша можно определить по наличию в коде известных констант. Например, в FNV используется число 0x811C9DC5. Если же применяется собственный алгоритм, он обычно простой, типа сложения со сдвигом, но найти его в коде будет уже не так просто.
Я уже было собрался искать 0x811C9DC5, но решил для начала погуглить, и оказалось, что разработчик bitsquid у себя в блоге как-то рассказывал о преимуществах хеша murmur64. Как у любого хеша, у murmur есть разные версии, но 64-битный — это как раз 8 байтов, как в нашей таблице. Исходный код нашелся здесь. Скомпилируем его и попробуем посчитать хеш строки «lua». Правда, мы не знаем, чему равен seed, поэтому пока попробуем взять ноль.
Получаем murmur64 от «lua» = A14E8DFA2CD117E2
Это число как раз часто встречается в нашем файле! Поздравляем, теперь мы знаем, как игра считает хеш. Если бы seed не был нулём, пришлось бы опять-таки смотреть или отлаживать код, чтобы это узнать. Это может быть константа, или длина текстовой строки, а вообще это может быть что угодно. Например, первый символ, склеенный с длиной строки.
Ну хорошо, мы знаем одно из расширений, неужели теперь придётся по одному угадывать все остальные? Возможно, бывает и так. Но давайте попробуем поискать где-то их список, так сказать, в открытом виде. Он может быть в одном из lua-скриптов, или прямо в исполняемом файле, как в данном случае:
В середине я выделил строки, которые точно являются типами ресурсов. Но где этот список начинается, и где кончается? Это можно определить экспериментально.
Попробуем для примера murmur64 от «unit» = E0A48D0BE9A7453F
И действительно, такой код есть. Вроде бы очевидное название, но угадать его с первого раза было бы не так просто. А звуковые банки так вообще называются «timpani_bank», вот уж ни за что не угадал бы.
Итак, теперь мы знаем все типы ресурсов (расширения файлов), но как узнать их имена? Они могут быть в ресурсах или в коде. Посмотрим например .ini файл, который лежит рядом с архивами.
Вот и первая зацепка — загрузочный пакет называется «resourse_packages/boot». Посчитаем хеш этой строки — 9E13B2414B41B842, он есть в нашем списке. В нём наряду с другими файлами содержится загрузочный скрипт
В нём внутри ссылки на другие скрипты, например, «scripts/boot/boot_common». В этом коммоне, в свою очередь, есть множество строк, в том числе
Видимо это название пакета, где содержатся основные ресурсы игры. Проверим — действительно есть такой. Так постепенно можно теоретически найти все числа. Естественно, это делается не вручную, а пишутся программы или скрипты, ведь в средней игре несколько десятков или даже сотен тысяч ресурсов. Процесс разгадывания иногда затягивается надолго, и всё равно зачастую в итоге остаются некоторое количество безымянных файлов. Тем не менее, большинство имён обычно удаётся найти, после чего составляется список, который используется при распаковке ресурсов и модификации игры.
Итак, предположим, мы нашли все названия, и теперь ресурсы у нас имеют осмысленные имена и расширения. Вернёмся к формату файла.
После таблицы — списка хешей (выделена желтым) начинаются отдельные записи для всех ресурсов. Как мы уже выяснили, первая строчка (выделена зеленым) — это имя и тип ресурса. Здесь 82645835E6B73232 = «config», правую часть (имя) мы пока не знаем. Попробуем угадать, что же идёт дальше. По всей видимости, тут у нас несколько 32-битных чисел. Сначала единичка, потом два ноля, дальше еще одно число (выделено розовым), похожее на размер, и еще один ноль. Неизвестно, что это, но у всех файлов эти числа именно такие. Потом начинается собственно содержимое ресурса. Проверим его длину. Прибавим размер 045С к смещению, где начинается запись, 0518, получим 0974.
Да, действительно, здесь уже следующий хеш. 9EFE0A916AAE7880 = это «font», далее всё то же самое, что в первой записи и длина фонта — 1838. Далее идёт сам фонт, он начинается большой серией плавающих чисел, их тоже обычно легко видно невооружённым глазом. Например 42000000 — это 32, 41С80000 — это 25, и конечно 3F800000 — самое часто встречающееся в игровых файлах плавающее число — это 1.
Вроде бы формат записей в архиве мы разобрали. Похоже, единственное, что у нас есть для каждого ресурса, это его размер. Странно, что нет смещения, ну, бывает и так. Остальные числа — нули, возможно, они что-то значат, но нам это неизвестно. Проверим на всякий случай последнюю запись, прибавив длину последнего ресурса к адресу его начала. Получаем 4ECFDA0 — это как раз общая длина файла. Похоже, в конце больше ничего нет, значит можно приступать к написанию программы распаковки. Она будет читать файл пакета и разделять его на ресурсы. Если хеш имеется в нашем списке — сохранять файлы с правильным именем, если нет — в качестве имени берётся сам хеш.
Запускаем программу — и она успешно распаковывает кучу файлов из нашего пакета. Проверим их содержимое. Текстуры действительно получились корректными DDS-файлами, звуки проигрываются как обычные OGG, остальные файлы (например, модели юнитов) хотя и имеют какой-то особый формат, тоже выглядят правдоподобно.
Воодушевленные успехом, начинаем распаковку всех остальных файлов. И тут нас ожидает Unhandled Exception. Практически все файлы распаковались, кроме нескольких. Так обычно и бывает. Среди тысяч файлов обязательно найдётся один-два, упакованных как-нибудь нестандартно, или с дополнительными параметрами. Посмотрим, что не так с этими файлами. Оказывается, единичка после хеша была неспроста. В этом файле здесь не единичка, а семёрка. Мало того, при распаковке других игр, сделанных на том же движке, оказалось, что и нули там тоже не всегда нули. Но и это ещё не всё. Есть один файл, структура которого, кажется, вообще нарушена. При попытке найти в нём очередной ресурс оказывается, что оставшегося куска файла не хватает для ресурса такой длины.
Посмотрим запись об этом конкретном ресурсе. Вроде бы всё правильно: хеш, после него единичка, два нуля, потом размер. Как же так? Может быть, файл неправильно распаковался? Ну-ка, попробуем ещё раз. Возможно, в мелькании сотен строк вывода offzip мы что-то не заметили?
Да, действительно, какая-то проблема. Именно в этом файле присутствуют сегменты, которые не распаковались. Кстати, что это за ресурс такой? Посмотрим содержимое файла по смещению 0x028cac59, или чуть раньше.
А это как раз «timpani_bank». Ну конечно! Ведь ogg-поток может содержать настолько хаотичный поток битов, что zlib просто не может его сжать, в итоге из 92-МБ файла несколько 64-кбайтных сегментов после сжатия получились даже больше, чем 64к. Видимо разработчики резонно решили, что в таком случае нет смысла их сжимать, и поместили в архив прямо как было. Поэтому offzip не смог найти там заветные байты 78 9C, и в итоге просто пропустил их при распаковке.
Никакого флага/признака для отличия сжатых и несжатых сегментов в структуре файла нет, значит игра поступает просто: если сегмент имеет размер меньше б4к — значит он упакован, если же ровно 64к — то нет. Однако и тут не всё так просто. Были случаи (в другой игре, на другом движке), когда после упаковки сегмента его длина оставалась точно равной 64к. И вот тут уже никак не определить, сжатый он или нет. Хотя вероятность такого совпадения очень мала, это тоже придётся учитывать.
Вот так, постепенно, сравнивая и анализируя файлы, чаще всего можно разобрать формат данных, даже не прибегая к отладке кода. Не буду вдаваться в подробности, как определить, что это была за семёрка, и что это были за нули, которые не всегда нули, ведь всех особенностей формата на одном примере всё равно не разгадать. А если найдутся другие игры, которые их используют — тогда и будем разбираться.
Представь, что на твоем компьютере возник неизвестный исполняемый файл, но отправлять его на проверку в VirusTotal ты почему-то не хочешь. Например, потому что он может уйти в исследовательскую лабораторию, где его пристально изучат. В этой статье я покажу тебе, как провести такое исследование самостоятельно.
В целом, если говорить про анализ исполняемых файлов, можно выделить два подхода — это статический анализ и динамический анализ.
Виды анализа исполняемых файлов
Статический анализ предполагает анализ файла без его запуска на выполнение. Он может быть базовым — в этом случае мы не анализируем непосредственно инструкции процессора в файле, а производим поиск нетипичных для обычных файлов артефактов (например, таких как строки или названия и последовательности API-функций), либо расширенным — в этом случае файл дизассемблируется и производится исследование инструкций, поиск их характерных для вредоносных программ последовательностей и определение того, что именно делала программа.
Динамический анализ заключается в исследовании файла с его запуском в системе. Он тоже может быть базовым и расширенным. Базовый динамический анализ — это исследование файла с его запуском без использования средств отладки, он заключается в отслеживании событий, связанных с этим файлом (например, обращение к реестру, дисковые операции, взаимодействие с сетью и т. п.). Расширенный динамический анализ заключается в исследовании поведения запущенного файла с применением средств отладки.
В этой статье я расскажу о базовых техниках статического анализа. Его преимущества:
- позволяет получить результат достаточно быстро;
- безопасен для системы при соблюдении минимальных мер предосторожности;
- не требует подготовки специальной среды.
Основной недостаток базового статического анализа — это его низкая эффективность при анализе и распознавании сложных вредоносных программ, например упакованных неизвестным упаковщиком или использующих полное либо частичное шифрование файла с применением продвинутых алгоритмов.
Связаться с нами
Наша главная цель - обеспечить вашу безопасность. Мы всегда готовы ответить на ваши вопросы и оказать техническую поддержку.
Риски безопасности и конфиденциальности в виртуальной и дополненной реальности
Меры предосторожности
Чтобы обезопасить систему при проведении базового статического анализа подозрительных файлов, необходимо:
- установить запрет на операцию чтения и выполнения анализируемого файла (вкладка «Безопасность» в контекстном меню «Свойства»);
- сменить разрешение файла с .exe на какое-нибудь другое (или вообще убрать расширение анализируемого файла);
- не пытаться открыть файл текстовыми процессорами и браузерами.
Можно обойтись этими мерами и не использовать виртуальную среду, хотя для полной безопасности можешь установить, например, Virtual Box и проводить анализ в нем (тем более что при динамическом анализе без виртуалки, как правило, не обойтись).
Специализированные утилиты для исследования исполняемых файлов Windows
Программа CFF Explorer из пакета Explorer Suite — это настоящий швейцарский нож для исследователя PE-файлов. Позволяет получить огромное количество разнообразной информации обо всех компонентах структуры PE-файла и, помимо прочего, может служить HEX-редактором.
Так что настоятельно рекомендую CFF Explorer, тем более что программа бесплатная.
Инструментарий и настройка ОС
Для тестов будем использовать виртуальную машину под управлением ОС Windows. Инструментарий будет содержать следующие приложения:
установленный по умолчанию плагин x64dbg Scylla;
Самый быстрый и простой способ провести распаковку любого исполняемого файла — применить отладчик. Но так как мы будем также рассматривать язык программирования Python, то может понадобится проект:
uncompile6 проект, который позволяет разобрать байткод виртуальной машины Python;
pyinstallerExtractor инструмент для распаковки архива pyInstaller.
Упаковка исполняемых файлов
Упакованные файлы – это файлы, которые скрывают свой исходный код с помощью сжатия или шифрования. По мере выполнения, такой файл расшифровывает свой исходный код и копирует в другую секцию. Упаковщики обычно изменяют таблицу адресов импорта (IAT — Import Address Table) или таблицу просмотра импорта(ILUT — Import LookUp Table), а также заголовок.
Упаковка применяется по следующим причинам:
- упакованный файл занимает меньше места;
- для предотвращения обратной разработки программы;
- упаковка с шифрованием может использоваться и злонамеренно при создании вирусов, чтобы зашифровать и видоизменить код вируса для затруднения его обнаружения системами, основанными на сигнатурах.
Проводить анализ, упакована программа или нет, можно при помощи PEid или DetectItEasy. Для распаковки используются соответствующие программы или универсальные распаковщики, к примеру, Quick Unpack.
Детекторы упаковщиков
Если есть подозрение, что файл упакован, то с помощью детектора упаковщиков можно попытаться определить, какой упаковщик при этом использовался, и попробовать распаковать исследуемый файл. Долгое время безусловным лидером здесь была программа PEiD, и в принципе можно пользоваться и ей, однако поддержка давно прекращена и новых сигнатур для определения типов упаковщика уже никто не выпускает. Альтернатива — Exeinfo PE.
Эта программа, помимо детекта упаковщиков, имеет еще много других функций для анализа исполняемых файлов Windows, и во многих случаях можно обойтись ей одной.
TrickBot – многоцелевой ботнет
Продолжение доступно только участникам
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Продукты для дома
Наши передовые решения помогают защитить то, что для вас ценно. Узнайте больше о нашей удостоенной наград защите.
Пример UPX
Попробуем с помощью отладчика найти оригинальную точку входа для приложения. Запечатлим оригинальную точку входа до упаковки UPX:
Как та же точка входа выглядит после упаковки:
Запустим отладчик и попробуем найти место сохранения контекста:
Ждем первого использования ESP — в отладчике при этом значение регистра подсветится красным цветом. Затем устанавливаем точку останова на адрес и просто запускаем приложение:
В результате попадаем на оригинальную точку входа:
Вот так просто, теперь используя плагин Scylla Hide можно сохранить результирующий файл на жесткий диск и продолжить его анализ.
Подобный метод можно применять для любого упаковщика, который сохраняет контекст на стек.
Что такое глубокий и теневой интернет?
Сувенирный портал Lab Shop
Здесь вы можете приобрести сувенирные продукты с корпоративной символикой «Лаборатории Касперского».
В данной статье разберем: как и для чего применяется упаковка исполняемых файлов, как их обнаружить и распаковать, и решим 4-е задание с сайта pwnable.kr.
Специально для тех, кто хочет узнавать что-то новое и развиваться в любой из сфер информационной и компьютерной безопасности, я буду писать и рассказывать о следующих категориях:
- PWN;
- криптография (Crypto);
- cетевые технологии (Network);
- реверс (Reverse Engineering);
- стеганография (Stegano);
- поиск и эксплуатация WEB-уязвимостей.
Пример PyInstaller
Не всегда подобный подход работает для приложений, которые используют более сложную структуру исполняемого файла. Рассмотрим файл, который был создан с помощью PyInstaller — пакет, который позволяет преобразовать Python скрипт в исполняемый файл. При генерации исполняемого файла создается архив, который содержит виртуальную машину Python и все необходимые библиотеки. Сам исходный код приложения при этом преобразуется в байт код и его нельзя дезассемблировать.
Попробуем все же получить что-то читаемое. Создадим простое приложение на Python и упакуем с помощью PyInstaller. Исходный код приложения:
Установим пакет pyInstaller и создадим exe файл:
Итак, проведем сбор информации о том, что в итоге получилось. У нас есть архив, который должен запустить виртуальную машину, и код, который мы записали в виде скрипта. Попробуем восстановить исходник и просто его прочесть даже без запуска.
После выполнения команд выше, у вас должна создаться директория ./dist/test.exe . Откроем последовательно файл с помощью pyinstallerextractor и uncompile3 :
Наш скрипт находится в директории, которая создается в результате распаковки. Наименование файла должно соответствовать названию exe файла. В нашем случае это test.pyc . Откроем его в hiew :
Декомпиляция стандартными средствами невозможна, так как инструменты просто не умеют работать с байткодом Python. Применим специализированный инструмент — uncompile6 .
Чтобы предотвратить реконструкцию вредоносных программ и затруднить анализ поведения программ, разработчики вредоносного ПО могут сжимать (или упаковывать) свои вредоносные программы различными способами, сочетая это с шифрованием файлов. Антивирусные программы обнаруживают результат работы подозрительных упаковщиков, т.е. упакованные объекты.
Инструментарий
Общие методы снятия паковки
Разберемся, что же такое паковка. В большинстве случаев исполняемые файлы современных языков программирования имеют довольно большой размер при минимальном наборе функций. Чтобы оптимизировать данную величину, можно применить паковку или сжатие. Наиболее распространенный на сегодняшний день пакер — UPX. Ниже приведен пример того, как пакер проводит сжатие исполняемого файла.
На картинке может показаться, что файл стал по размеру больше, однако это не всегда так. Большинство файлов за счет такой модификации могут уменьшить свой размер до 1.5 раз от исходного объема.
Что же от этого реверс-инженеру? Почему надо знать и уметь определять, что файл упакован? Приведу наглядный пример. Ниже приведен снимок файла, который не запакован:
И файл, который был пропущен через алгоритм UPX:
Изменения коснулись в этом случае двух основных точек исполняемого файла:
Точка входа — в случае с упакованным файлом это начало алгоритма распаковки, настоящий алгоритм программы будет работать только после того, как будет распакован оригинальный файл;
Код оригинального файла: теперь не найти паттернов, которые можно сразу разбирать как команды.
Итак, чтобы снова анализировать оригинальный файл, нужно найти настоящую или оригинальную точку входа. Для этого нужно разбить алгоритм на основные этапы:
Этап подготовки исполнения файла — загрузчик ОС настраивает окружение, загружает файл в оперативную память;
Сохранение контекста — упаковщик сохраняет контекст исполнения файла (набор значений регистров общего назначения, которые были установлены загрузчиком ОС);
Распаковка оригинального файла;
Передача управления оригинальному файлу.
Все описанные выше этапы можно легко отследить в отладчике. Особенно может выделяться процедура сохранения контекста. Для нее в разных архитектурах могут быть использованы команды pushad/popad или множественное использование команды push . Поэтому всегда приложение трассируют до первого изменения регистра ESP/RSP, и ставят "Hardware Breakpoint" на адрес, который был помещен в регистр в первый раз. Второе обращение этому адресу будет в момент восстановления контекста, который заполнил загрузчик ОС. Без него приложение завершится с ошибкой.
Как защитить детей в интернете во время коронавируса
HEX-редакторы
Один из основных инструментов статического базового анализа — это HEX-редактор. Их много, но в первую очередь необходимо отметить Hiew. Это безусловный лидер и бестселлер. Помимо непосредственно функций HEX-редактора, в нем реализовано еще много дополнительных возможностей, связанных с анализом файла: это и дизассемблер, и просмотрщик секций импорта и экспорта, и анализатор заголовка исполняемых файлов. Главный недостаток — все это не бесплатно (хотя и весьма недорого — от 555 рублей).
HEX-редактор Hiew
Если не хочется тратить деньги, то можно обратить внимание, например, на Hex Editor Neo (есть бесплатный вариант) или на HxD Hex Editor.
Подозрительные упаковщики и шифровальщики
Чтобы предотвратить реконструкцию вредоносных программ, разработчики ПО могут "упаковывать" свои вредоносные программы, сочетая это с шифрованием файлов.
Избранные статьи
Определение типа файла
Я думаю, тебе известно, что признак PE-файла в Windows — это не только расширение .exe, .dll, .drv или .sys. Внутри него содержатся и другие отличительные черты. Первая из них — это сигнатура из байт вида MZ (или 0x4d, 0x5a в шестнадцатеричном представлении) в самом начале файла. Вторая — сигнатура также из двух байт PE и двух нулевых байтов следом (или 0x50, 0x45, 0x00, 0x00 в шестнадцатеричном представлении).
Смещение этой сигнатуры относительно начала файла записано в так называемом DOS-заголовке в поле e_lfanew , которое находится по смещению 0x3c от начала файла.
По большому счету наличие этих двух сигнатур в файле и подходящее расширение свидетельствует о том, что перед нами именно PE-файл, однако при желании можно посмотреть еще значение поля Magic опционального заголовка (Optional Header). Это значение находится по смещению 0x18 относительно начала сигнатуры PE . Значение этого поля определяет разрядность исполняемого файла:
- значение 0x010b говорит о том, что файл 32-разрядный (помни, что в памяти числа располагаются с обратной последовательностью байтов, сначала младший байт и далее старшие байты, то есть число 0x010b будет представлено последовательностью 0x0b, 0x01);
- значение 0x020b говорит о том, что файл 64-разрядный.
Посмотреть это все можно несколькими способами. Первый — с помощью HEX-редактора.
Признаки PE-файла в HEX-редакторе Hiew
Второй — используя CFF Explorer или Exeinfo PE. Они наглядно показывают значения указанных сигнатур.
Третий способ — использовать возможности Python, запустив такой скрипт:
Или можешь использовать вот такое правило для Yara:
Поиск в VirusTotal по хешу
Думаю, как узнать хеш файла, ты прекрасно знаешь. В крайнем случае можно написать небольшой скрипт на Python:
Результат подсчета хеша шлем на VirusTotal либо применяем мои рекомендации из статьи «Тотальная проверка. Используем API VirusTotal в своих проектах» и автоматизируем этот процесс с помощью небольшого скрипта на Python.
Как видишь, скрипт получает значение хеша, переданного в виде аргумента командной строки, формирует все нужные запросы для VirusTotal и выводит результаты анализа.
Если VirusTotal выдал в ответ какие-нибудь результаты анализа, это значит, что исследуемый файл уже кто-то загружал для анализа и его можно загрузить туда повторно и получить более актуальные результаты, на чем анализ можно и завершать. Но вот если VirusTotal не найдет файла в базах, тогда есть смысл идти дальше.
Читайте также: