Интересная статья с хакера, посвященная статическому анализу:
В целом, если говорить про анализ исполняемых файлов, можно выделить два подхода — это статический анализ и динамический анализ.
Виды анализа исполняемых файлов
Статический анализ предполагает анализ файла без его запуска на выполнение. Он может быть базовым — в этом случае мы не анализируем непосредственно инструкции процессора в файле, а производим поиск нетипичных для обычных файлов артефактов (например, таких как строки или названия и последовательности API-функций), либо расширенным — в этом случае файл дизассемблируется и производится исследование инструкций, поиск их характерных для вредоносных программ последовательностей и определение того, что именно делала программа.
Динамический анализ заключается в исследовании файла с его запуском в системе. Он тоже может быть базовым и расширенным. Базовый динамический анализ — это исследование файла с его запуском без использования средств отладки, он заключается в отслеживании событий, связанных с этим файлом (например, обращение к реестру, дисковые операции, взаимодействие с сетью и т. п.). Расширенный динамический анализ заключается в исследовании поведения запущенного файла с применением средств отладки.
В этой статье я расскажу о базовых техниках статического анализа. Его преимущества:
Инструментарий
HEX-редакторы
Один из основных инструментов статического базового анализа — это HEX-редактор. Их много, но в первую очередь необходимо отметить
HEX-редактор Hiew
Если не хочется тратить деньги, то можно обратить внимание, например, на
Детекторы упаковщиков
Если есть подозрение, что файл упакован, то с помощью детектора упаковщиков можно попытаться определить, какой упаковщик при этом использовался, и попробовать распаковать исследуемый файл. Долгое время безусловным лидером здесь была программа
Exeinfo PE
Эта программа, помимо детекта упаковщиков, имеет еще много других функций для анализа исполняемых файлов Windows, и во многих случаях можно обойтись ей одной.
Специализированные утилиты для исследования исполняемых файлов Windows
Программа
CFF Explorer
Так что настоятельно рекомендую CFF Explorer, тем более что программа бесплатная.
Python-модуль pefile
Python-модуль
Модуль присутствует в
Yara
Ну и в завершение всего списка весьма популярный и востребованный инструмент, ставший своеобразным стандартом в среде антивирусной индустрии, — проект
WWW
Чтобы обезопасить систему при проведении базового статического анализа подозрительных файлов, необходимо:
Определение типа файла
Я думаю тебе известно, что признак PE-файла в Windows — это не только расширение .exe, .dll, .drv или .sys. Внутри него содержатся и другие отличительные черты. Первая из них — это сигнатура из байт вида "MZ" (или 0x4d, 0x5a в шестнадцатеричном представлении) в самом начале файла. Вторая — сигнатура также из двух байт PE и двух нулевых байтов следом (или 0x50, 0x45, 0x00, 0x00 в шестнадцатеричном представлении).
Смещение этой сигнатуры относительно начала файла записано в так называемом DOS-заголовке в поле e_lfanew, которое находится по смещению 0x3c от начала файла.
По большому счету наличие этих двух сигнатур в файле и подходящее расширение свидетельствует о том, что перед нами именно PE-файл, однако при желании можно посмотреть еще значение поля Magic опционального заголовка (Optional Header). Это значение находится по смещению 0x18 относительно начала сигнатуры PE. Значение этого поля определяет разрядность исполняемого файла:
Признаки PE-файла в HEX-редакторе Hiew
Второй — используя CFF Explorer или Exeinfo PE. Они наглядно показывают значения указанных сигнатур.
Третий способ — использовать возможности Python, запустив такой скрипт:
Или можешь использовать вот такое правило для Yara:
Поиск в VirusTotal по хешу
Отправить на VirusTotal для проверки можно не только сам файл, но и его хеш (md5, sha1 или sha256). В этом случае, если такой же файл уже анализировался, VirusTotal покажет результаты этого анализа, при этом сам файл на VirusTotal мы не засветим.
Думаю, как узнать хеш файла, ты прекрасно знаешь. В крайнем случае можно написать небольшой скрипт на Python:
Результат подсчета хеша шлем на VirusTotal либо применяем мои рекомендации из статьи «
Как видишь, скрипт получает значение хеша, переданного в виде аргумента командной строки, формирует все нужные запросы для VirusTotal и выводит результаты анализа.
Если VirusTotal выдал в ответ какие-нибудь результаты анализа, это значит, что исследуемый файл уже кто-то загружал для анализа и его можно загрузить туда повторно и получить более актуальные результаты, на чем анализ можно и завершать. Но вот если VirusTotal не найдет файла в базах, тогда есть смысл идти дальше.
Поиск и анализ строк
Некоторые строки внутри файла могут явно свидетельствовать о его злонамеренности, а иногда по ним даже понятно, что конкретно он делает. Например, URL или IP-адреса внутри файла подскажут, что она взаимодействует с какими-то серверами (их, кстати, тоже можно пробить через VirusTotal на вредоносность).
Могут попадаться и строки с ключами реестра. Например, вот такие пути будут явно указывать на желание файла закрепиться в системе надолго:
Скорее всего, вместе с такими строками в секции импорта найдутся и запросы к функциям API, которые манипулируют ключами реестра.
Строки можно напрямую поискать с помощью HEX-редактора, а можно использовать консольную утилиту Strings из состава
Кроме URL, IP и ключей реестра стоит обратить внимание на следующие разновидности текстовых данных.
Создатели некоторых вредоносов специально шифруют строки, но серьезные алгоритмы шифрования в таких случаях — это редкость. Так что шифровки можно поискать консольной утилитой
WWW
Часто вирусописатели не заморачиваются и шифруют строки при помощи XOR. Такие строки легко найти при помощи правила для Yara.
Такое правило будет искать в файле строку с ключом реестра, поксоренную производным байтом. К сожалению, с регулярными выражениями модификатор xor применить нельзя.
INFO
Еще одна удобная программа для поиска строк — это
Анализ информации PE-заголовка
При компиляции PE-файла в него включается заголовок (PE-header), который описывает структуру файла. При выполнении файла загрузчик ОС читает информацию из этого заголовка, а затем копирует содержимое файла в память и передает ему исполнение.
Заголовок PE содержит в себе много информации, например по какому адресу PE-файл должен быть загружен в память, адрес запуска (он же — точка входа), списки библиотек, функций и ресурсов, которые файл будет использовать. Так что изучение заголовка дает при исследовании очень многое.
Анализ таблицы импорта
Большинство программ, в том числе вредоносных, используют API-функции, которые предоставляет операционная система. Их код содержится в разных DLL, откуда их и импортирует исполняемый файл. Собственно, перечень этих функций, содержащийся в заголовке, — это один из самых полезных фрагментов информации при исследовании. Стоит на него взглянуть, и уже примерно понимаешь, что делает программа.
Все это можно посмотреть в так называемой таблице импорта. Например, при помощи CFF Explorer.
Таблица импорта в CFF Explorer
Или можно использовать Hiew.
Таблица импорта в Hiew
Как вариант, здесь во всей красе может показать себя Python-модуль pefile. Для вывода секции импорта можно использовать такой скрипт:
Вывод таблицы импорта с помощью скрипта на Python
Вот наиболее популярные DLL, которые встречаются в любых программах:
В первую очередь — на наличие библиотек ntdll.dll, wsock32.dll и ws2_32.dll. Эти библиотеки редко встречаются в обычных программах, поскольку содержат в себе низкоуровневые API-функции.
Наличие этой же библиотеки вкупе с вызовом функций работы с реестром (типа RegCreateKeyEx, RegEnumKeyEx, RegDeleteKeyExA и т. п.) говорит о манипуляциях с реестром и возможной записи в автозагрузку. Подтверждает это наличие строк с соответствующими ключами реестра.
Также стоит обратить внимание на слишком маленький импорт или его отсутствие. Это крайне нетипично для обычных программ. Также не совсем типично присутствие в импорте связки API-функций LoadLibrary и GetProcAddress (либо LdrLoadDll и LdrGetProcAddress). Это однозначно говорит о реализации так называемого импорта времени выполнения (в отличие от динамического импорта, когда все импортируемые функции перечислены в секции импорта) и свидетельствует о попытке скрыть настоящее назначение файла. Либо это может говорить о том, что файл упакован.
INFO
Как правило при использовании связки LoadLibrary (или LoadLibraryEx) и GetProcAddress (или LdrLoadDll + LdrGetProcAddress) необходимы имена функций, которые будут импортироваться во время выполнения программы, поэтому если нашел эти API в импорте, есть смысл поискать строки с именами импортируемых во время выполнения API-функций. При этом стоит помнить, что они могут быть зашифрованы или обфусцированы.
Следующие API или их связки также требуют особого внимания. Их наличие в исследуемом файле — повод насторожиться.
Или так (с использованием Yara-модуля pe):
А вот правило для Yara для распознавания связки из LoadLibrary (или LoadLibraryEx) и GetProcAddress и строк с импортируемой во время выполнения связкой OpenProcess, VirtualAllocEx, WriteProcessMemory и CreateRemoteThread, которые могут быть закрыты побайтовым XOR:
Для сравнения секций импорта разных файлов можно использовать хеш импорта, так называемый imphash. Это хеш md5 от секции импорта после некоторой нормализации. Подробнее о нем можешь почитать
В Yara imphash можно определить с помощью функции imphash() модуля pe:
На Python можно написать вот так:
Используя значение imphash, вычисленное для одного файла, с помощью написанного выше правила Yara можно искать файлы с одинаковой таблицей импорта (и с большой вероятностью с похожим предназначением).
INFO
Утилита
Анализ таблицы экспорта
Вредоносные файлы с экспортируемыми функциями — редкое явление, однако иногда на просторах вирусных полей они встречаются. Бывают в том числе и вредоносные DLL.
Таблицу экспорта, в которой перечислены экспортируемые функции, можно так же, как и таблицу импорта, посмотреть в CFF Explorer или Hiew.
Таблица экспорта в CFF Explorer
Здесь нужно обратить внимание на говорящие сами за себя названия экспортируемых функций, либо на названия функций в виде беспорядочного набора символов, либо на отсутствие названий функций при наличии только ординалов (номеров) функций (такое тоже может быть, ведь функции можно экспортировать не только по имени, но и по ординалу).
На Python можно сделать следующий скрипт для просмотра таблицы экспорта:
Анализ таблицы секций
Фактически все содержимое PE-файла разбито на секции. Каждая секция хранит в себе либо код, который будет исполнен при запуске файла, либо данные, необходимые для выполнения, либо ресурсы, используемые файлом. У каждой секции есть имя, однако операционная система определяет назначение секции не по имени, а по атрибуту Characteristics, а имена используются только для наглядности.
Помимо назначения секции атрибут Characteristics определяет операции, которые можно проводить с данными секции (чтение, выполнение, запись и т. д.). Более подробно о секции в целом и об этом атрибуте можно почитать
Увидеть это все легко можно с помощью, например, CFF Explorer.
На что нужно обратить внимание при анализе таблицы секций?
Во-первых, на необычные названия секций. Например, в виде беспорядочного набора символов.
Во-вторых, на несоответствие атрибута Characteristics назначению и содержимому секции. Например, может быть так, что у секции .text, в которой содержится исполняемый код, помимо прочего еще добавлено IMAGE_SCN_MEM_WRITE, то есть в секцию с кодом можно писать данные. Это явный признак самомодифицирующегося кода, и в обычных программах такое почти не встречается. То же можно сказать и про секцию с данными (.data или DATA): если в атрибуте Characteristics помимо прочего присутствует IMAGE_SCN_MEM_EXECUTE, то это очень серьезный повод для подозрения.
В-третьих, наличие секций вроде UPX0, UPX1 или .aspack красноречиво свидетельствует о применении соответствующих упаковщиков.
Также о применении упаковщиков может свидетельствовать высокое значение (близкое к 8)
Скрипт выводит имена всех секций PE-файла, значение атрибута Characteristics, md5-хеш и энтропию каждой секции.
Значение энтропии одной из секций свидетельствует о возможном наличии упаковки
В Yara энтропию можно определить с помощью функции entropy() модуля
Временная метка компиляции
Информация о времени компиляции анализируемого файла может быть полезна при построении графа атаки и его анализе. Время создания (и, соответственно, компиляции PE-файла) хранится в PE-заголовке в виде четырехбайтового числа, содержащего количество секунд, прошедших с 0 часов 0 минут 1 января 1970 года.
Время компиляции файла в CFF Explorer
В удобоваримом виде значение этого времени можно посмотреть с помощью такого скрипта:
Для Delphi (а вредоносные файлы, написанные на Delphi, встречаются и по сей день) это значение всегда равно 0x2a425e19, что значит 0 часов 0 минут 19 июня 1992 года. В этом случае реальную дату компиляции можно попытаться определить из отметки времени секции .rsrc (в файлах, создаваемых Delphi, она всегда присутствует). Временная метка находится по смещению 4 от начала секции .rsrc и представляет собой четырехбайтовое число в формате
Посмотреть это значение в пристойном виде можно следующим скриптом:
Если PE-файл компилировался Visual Studio и при компиляции в файл была включена отладочная информация (а это можно определить по наличию таблицы Debug Directory в PE-файле), то дата компиляции (помимо заголовка PE-файла) также содержится и в этой таблице:
Таблица Debug Directory в PE-файле и отметка о времени компиляции
Посмотреть временную метку компиляции из Debug Directory в «нормальном» виде можно следующим скриптом:
При анализе временной метки компиляции под подозрением должны быть:
У некоторых компонентов Windows поле TimeDateStamp в PE-заголовке может иметь интересные значения — либо из будущего (к примеру, у меня для «Блокнота» это 8 сентября 2028 года), либо из прошлого (встречаются компоненты, датированные 1980 годом).
Анализ ресурсов исполняемого файла
Ресурсы, необходимые для работы exe-файла (такие как иконки, диалоговые окна, меню, изображения, информация о версии, конфигурационные данные), хранятся в секции .rsrc. Просмотреть можно при помощи все того же CFF Explorer.
Содержимое секции .rsrc в CFF Explorer
Но все же для просмотра ресурсов в PE-файлах лучше использовать
Просмотр информации о версии программы в секции ресурсов Resource Hacker
Поскольку в секции ресурсов могут хранится любые данные, туда могут быть помещены либо вредоносная нагрузка, либо драйвер (например, перехватывающий системные функции), либо еще что-нибудь не очень хорошее. Поэтому стоит призадуматься, если найдешь здесь что-то совсем не похожее на иконки, картинки, диалоги, окна, информацию о версии и прочие безобидные вещи.
Rich-сигнатура
В статье я не упомянул такую примечательную структуру PE-файла, как Rich-сигнатура. На нее тоже стоит обратить внимание при анализе подозрительных файлов. Почитать о ней на английском можно здесь:
Заключение
С помощью нескольких относительно простых инструментов мы можем быстро проанализировать подозрительный исполняемый файл, частично (а иной раз и достаточно полно) понять, что он собой представляет, и вынести вердикт о возможной вредоносности. Однако при анализе сложных файлов, подвергнутых упаковке, шифрованию и обфускации, этого может оказаться недостаточно. Тогда без более детального статического и динамического анализа не обойтись. Об этом мы и поговорим в следующий раз.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
В целом, если говорить про анализ исполняемых файлов, можно выделить два подхода — это статический анализ и динамический анализ.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Виды анализа исполняемых файлов
Статический анализ предполагает анализ файла без его запуска на выполнение. Он может быть базовым — в этом случае мы не анализируем непосредственно инструкции процессора в файле, а производим поиск нетипичных для обычных файлов артефактов (например, таких как строки или названия и последовательности API-функций), либо расширенным — в этом случае файл дизассемблируется и производится исследование инструкций, поиск их характерных для вредоносных программ последовательностей и определение того, что именно делала программа.
Динамический анализ заключается в исследовании файла с его запуском в системе. Он тоже может быть базовым и расширенным. Базовый динамический анализ — это исследование файла с его запуском без использования средств отладки, он заключается в отслеживании событий, связанных с этим файлом (например, обращение к реестру, дисковые операции, взаимодействие с сетью и т. п.). Расширенный динамический анализ заключается в исследовании поведения запущенного файла с применением средств отладки.
В этой статье я расскажу о базовых техниках статического анализа. Его преимущества:
- позволяет получить результат достаточно быстро;
- безопасен для системы при соблюдении минимальных мер предосторожности;
- не требует подготовки специальной среды.
Инструментарий
HEX-редакторы
Один из основных инструментов статического базового анализа — это HEX-редактор. Их много, но в первую очередь необходимо отметить
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
. Это безусловный лидер и бестселлер. Помимо непосредственно функций HEX-редактора, в нем реализовано еще много дополнительных возможностей, связанных с анализом файла: это и дизассемблер, и просмотрщик секций импорта и экспорта, и анализатор заголовка исполняемых файлов. Главный недостаток — все это не бесплатно (хотя и весьма недорого — от 555 рублей).
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
HEX-редактор Hiew
Если не хочется тратить деньги, то можно обратить внимание, например, на
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
(есть бесплатный вариант) или на
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
.Детекторы упаковщиков
Если есть подозрение, что файл упакован, то с помощью детектора упаковщиков можно попытаться определить, какой упаковщик при этом использовался, и попробовать распаковать исследуемый файл. Долгое время безусловным лидером здесь была программа
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
, и в принципе можно пользоваться и ей, однако поддержка давно прекращена и новых сигнатур для определения типов упаковщика уже никто не выпускает. Альтернатива —
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Exeinfo PE
Эта программа, помимо детекта упаковщиков, имеет еще много других функций для анализа исполняемых файлов Windows, и во многих случаях можно обойтись ей одной.
Специализированные утилиты для исследования исполняемых файлов Windows
Программа
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
из пакета Explorer Suite — это настоящий швейцарский нож для исследователя PE-файлов. Позволяет получить огромное количество разнообразной информации обо всех компонентах структуры PE-файла и, помимо прочего, может служить HEX-редактором.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
CFF Explorer
Так что настоятельно рекомендую CFF Explorer, тем более что программа бесплатная.
Python-модуль pefile
Python-модуль
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
позволит обойтись при анализе PE-файлов исключительно интерпретатором Python. С ним практически все операции по базовому статическому анализу можно реализовать путем написания небольших скриптов. Прелесть всего этого в том, что заниматься исследованием PE-файлов можно в Linux.Модуль присутствует в
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
, и установить его можно через pip:
Код:
pip install pefile
Yara
Ну и в завершение всего списка весьма популярный и востребованный инструмент, ставший своеобразным стандартом в среде антивирусной индустрии, — проект
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
. Разработчики позиционируют его как инструмент, который помогает исследователям малвари идентифицировать и классифицировать вредоносные сэмплы. Исследователь может создать описания для разного типа малвари в виде так называемых правил, используя текстовые или бинарные паттерны.WWW
-
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
-
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
-
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки(обрати внимание — он слегка устарел)
Чтобы обезопасить систему при проведении базового статического анализа подозрительных файлов, необходимо:
- установить запрет на операцию чтения и выполнения анализируемого файла (вкладка «Безопасность» в контекстном меню «Свойства»);
- сменить разрешение файла с .exe на какое-нибудь другое (или вообще убрать расширение анализируемого файла);
- не пытаться открыть файл текстовыми процессорами и браузерами.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
и проводить анализ в нем (тем более что для динамического анализа без виртуалки, как правило, не обойтись).Определение типа файла
Я думаю тебе известно, что признак 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-разрядный.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Признаки PE-файла в HEX-редакторе Hiew
Второй — используя CFF Explorer или Exeinfo PE. Они наглядно показывают значения указанных сигнатур.
Третий способ — использовать возможности Python, запустив такой скрипт:
Python:
with open(<путь к файлу>, 'rb') as file:
# прочитаем первые 1000 байт файла (больше и не надо)
buffer = file.read(1000)
e_ifanew = int.from_bytes(buffer[0x3c:0x40], byteorder='little')
mz_signature = buffer[0x0:0x2]
pe_signature = buffer[e_ifanew:e_ifanew + 0x4]
magic = buffer[e_ifanew + 0x18:e_ifanew + 0x1a]
if mz_signature == b'MZ' and pe_signature == b'PE\x00\x00':
if magic == b'\x0b\x01':
print('Файл', sys.argv[1], 'является исполнимым PE32 файлом Windows.')
elif magic == b'\x0b\x02':
print('Файл', sys.argv[1], 'является исполнимым PE64 файлом Windows.')
else:
print('Файл', sys.argv[1],'не является PE файлом Windows.')
Или можешь использовать вот такое правило для Yara:
Код:
import "pe" //импортируем Yara-модуль pe
rule is_pe_file
{
strings:
$MZ_signature = "MZ"
condition:
($MZ_signature at 0) and (pe.is_32bit() or pe.is_64bit())
}
Поиск в VirusTotal по хешу
Отправить на VirusTotal для проверки можно не только сам файл, но и его хеш (md5, sha1 или sha256). В этом случае, если такой же файл уже анализировался, VirusTotal покажет результаты этого анализа, при этом сам файл на VirusTotal мы не засветим.
Думаю, как узнать хеш файла, ты прекрасно знаешь. В крайнем случае можно написать небольшой скрипт на Python:
Python:
import hashlib
with open(<путь к файлу>, 'rb') as file:
buffer = file.read()
print('md5 =', hashlib.md5(buffer).hexdigest())
print('sha1 =', hashlib.sha1(buffer).hexdigest())
print('sha256 =', hashlib.sha256(buffer).hexdigest())
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
» и автоматизируем этот процесс с помощью небольшого скрипта на Python.
Python:
import sys
import requests
## будем использовать 2-ю версию API VirusTotal
api_url = 'https://www.virustotal.com/vtapi/v2/file/report'
## не забудь про ключ доступа к функциям VirusTotal
params = dict(apikey=<ключ доступа к API VirusTotal>, resource=str(sys.argv[1]))
response = requests.get(api_url, params=params)
if response.status_code == 200:
result = response.json()
if result['response_code'] == 1:
print('Обнаружено:', result['positives'], '/', result['total'])
print('Результаты сканирования:')
for key in result['scans']:
print('\t' + key, '==>', result['scans'][key]['result'])
elif result['response_code'] == -2:
print('Запрашиваемый объект находится в очереди на анализ.')
elif result['response_code'] == 0:
print('Запрашиваемый объект отсутствует в базе VirusTotal.')
else:
print('Ошибка ответа VirusTotal.')
else:
print('Ошибка ответа VirusTotal.')
Если VirusTotal выдал в ответ какие-нибудь результаты анализа, это значит, что исследуемый файл уже кто-то загружал для анализа и его можно загрузить туда повторно и получить более актуальные результаты, на чем анализ можно и завершать. Но вот если VirusTotal не найдет файла в базах, тогда есть смысл идти дальше.
Поиск и анализ строк
Некоторые строки внутри файла могут явно свидетельствовать о его злонамеренности, а иногда по ним даже понятно, что конкретно он делает. Например, URL или IP-адреса внутри файла подскажут, что она взаимодействует с какими-то серверами (их, кстати, тоже можно пробить через VirusTotal на вредоносность).
Могут попадаться и строки с ключами реестра. Например, вот такие пути будут явно указывать на желание файла закрепиться в системе надолго:
Код:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run
Строки можно напрямую поискать с помощью HEX-редактора, а можно использовать консольную утилиту Strings из состава
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
, которая выводит весь текст, что найдет в файле. Строкой утилита считает любую последовательность из трех и более символов ASCII или Unicode, которая завершается нулевым символом.Кроме URL, IP и ключей реестра стоит обратить внимание на следующие разновидности текстовых данных.
- Строки с именами процессов антивирусных программ и различных утилит исследования системы (например, avp.exe для Касперского, ekrn.exe для ESET, drweb32.exe для DrWeb или procexp.exe для Process Explorer из состава Sysinternals Suite). Они могут свидетельствовать о том, что программа ищет эти процессы и собирается их завершить.
- Строки с именами процессов средств виртуализации (например, VBoxTray.exe или VBoxService.exe для Virtual Box, prl_cc.exe или prl_tools.exe для Parallels, vmsrvc.exe или vmusrvc.exe для Virtual PC) могут означать, что программа пытается определить, что ее запускают в виртуальной машине.
- Строки с именами процессов браузеров (iexplore.exe, firefox.exe, chrome.exe и т. п.) — возможно, признак внедрения кода в эти браузеры. Это может понадобиться для перехвата трафика или вводимой информации. Как вариант, программа может пытаться загрузить расширение или даже использовать целевой эксплоит для браузера.
- Строки с именами системных процессов (explorer.exe, svchost.exe и т. д.) могут быть признаком попыток внедрения вредоносного кода в эти процессы либо признаком запуска вредоносных процессов под видом системных. Иногда для поиска и манипуляций с процессом explorer.exe используют имя его окна — progman. Стоит поискать и его.
- Строки подозрительного содержания. Например, что-нибудь типа keylogger.txt или Portscanner startip.
Код:
rule URL
{
strings:
$url = /(https?:\/\/)?([\w\.]+)\.([a-z]{2,6}\.?)(\/[\w\.]*)*\/?/ wide ascii
condition:
$url
}
rule IP
{
strings:
$ip = /([0-9]{1,3}\.){3}[0-9]{1,3}/ wide ascii
condition:
$ip
}
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
(FireEye Labs Obfuscated String Solver). Как и Strings, она ищет строки в файле, но иногда позволяет найти обфусцированные или зашифрованные варианты.WWW
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Часто вирусописатели не заморачиваются и шифруют строки при помощи XOR. Такие строки легко найти при помощи правила для Yara.
Код:
rule xor_string
{
strings:
$string = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" xor
condition:
$string
}
INFO
Еще одна удобная программа для поиска строк — это
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
. Она отмечает все подозрительные строки, на которые стоит обратить внимание.Анализ информации PE-заголовка
При компиляции PE-файла в него включается заголовок (PE-header), который описывает структуру файла. При выполнении файла загрузчик ОС читает информацию из этого заголовка, а затем копирует содержимое файла в память и передает ему исполнение.
Заголовок PE содержит в себе много информации, например по какому адресу PE-файл должен быть загружен в память, адрес запуска (он же — точка входа), списки библиотек, функций и ресурсов, которые файл будет использовать. Так что изучение заголовка дает при исследовании очень многое.
Анализ таблицы импорта
Большинство программ, в том числе вредоносных, используют API-функции, которые предоставляет операционная система. Их код содержится в разных DLL, откуда их и импортирует исполняемый файл. Собственно, перечень этих функций, содержащийся в заголовке, — это один из самых полезных фрагментов информации при исследовании. Стоит на него взглянуть, и уже примерно понимаешь, что делает программа.
Все это можно посмотреть в так называемой таблице импорта. Например, при помощи CFF Explorer.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Таблица импорта в CFF Explorer
Или можно использовать Hiew.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Таблица импорта в Hiew
Как вариант, здесь во всей красе может показать себя Python-модуль pefile. Для вывода секции импорта можно использовать такой скрипт:
Python:
import pefile
## не забудь указать реальный путь к исследуемому файлу
pe = pefile.PE(<путь к файлу>)
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
for dll_entry in pe.DIRECTORY_ENTRY_IMPORT:
print(dll_entry.dll.decode('utf-8'))
for api_entry in dll_entry.imports:
print('\t' + api_entry.name.decode('utf-8'))
else:
print('Файл не содержит секцию импорта.')
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Вывод таблицы импорта с помощью скрипта на Python
Вот наиболее популярные DLL, которые встречаются в любых программах:
- kernel32.dll — содержит базовые функции: доступ и управление памятью, работа с файлами и устройствами;
- advapi32.dll — обеспечивает доступ к ключевым компонентам Windows (диспетчер служб, реестр), а также содержит API-функции криптографической подсистемы Windows;
- user32.dll — содержит компоненты графического интерфейса;
- gdi32.dll — содержит функции графических операций;
- winnet.dll — содержит высокоуровневые сетевые API-функции, реализующие такие протоколы, как FTP, HTTP и NTP.
В первую очередь — на наличие библиотек ntdll.dll, wsock32.dll и ws2_32.dll. Эти библиотеки редко встречаются в обычных программах, поскольку содержат в себе низкоуровневые API-функции.
- ntdll.dll содержит функции доступа к компонентам системы. Если встретишь импорт API из этого DLL, это может означать, что программа пытается перехватить системные функции, реализует разные антиотладочные приемы, манипулирует процессами, противодействует антивирусам и т. п.
- wsock32.dll и ws2_32.dll содержат низкоуровневые API-функции для работы с сокетами. Они обычно используются в узкоспециализированном ПО — и если встретятся при анализе обычной программы, это должно насторожить.
Наличие этой же библиотеки вкупе с вызовом функций работы с реестром (типа RegCreateKeyEx, RegEnumKeyEx, RegDeleteKeyExA и т. п.) говорит о манипуляциях с реестром и возможной записи в автозагрузку. Подтверждает это наличие строк с соответствующими ключами реестра.
Также стоит обратить внимание на слишком маленький импорт или его отсутствие. Это крайне нетипично для обычных программ. Также не совсем типично присутствие в импорте связки API-функций LoadLibrary и GetProcAddress (либо LdrLoadDll и LdrGetProcAddress). Это однозначно говорит о реализации так называемого импорта времени выполнения (в отличие от динамического импорта, когда все импортируемые функции перечислены в секции импорта) и свидетельствует о попытке скрыть настоящее назначение файла. Либо это может говорить о том, что файл упакован.
INFO
Как правило при использовании связки LoadLibrary (или LoadLibraryEx) и GetProcAddress (или LdrLoadDll + LdrGetProcAddress) необходимы имена функций, которые будут импортироваться во время выполнения программы, поэтому если нашел эти API в импорте, есть смысл поискать строки с именами импортируемых во время выполнения API-функций. При этом стоит помнить, что они могут быть зашифрованы или обфусцированы.
Следующие API или их связки также требуют особого внимания. Их наличие в исследуемом файле — повод насторожиться.
- Связка из VirtualAlloc и VirtualProtect или HeapAlloc и VirtualProtect может свидетельствовать о распаковке рабочей нагрузки вредоносного файла.
- API-функции CreateProcess или ShellExecute могут свидетельствовать о создании дочерних процессов, например чтобы отслеживать наличие в системе основного процесса и восстанавливать его в случае остановки (это один из распространенных и простейших способов создания так называемого «неубиваемого процесса»).
- Связка из OpenProcess, VirtualAlloc (или VirtualAllocEx), WriteProcessMemory и CreateRemoteThread — весьма красноречивый признак попытки внедрения кода в какой-либо процесс (особенно вкупе с наличием в файле строки с именем какого-либо процесса).
- SetWindowsHookEx свидетельствует об установке перехватов других API-функций. Очень часто это делается вовсе не во благо ничего не подозревающего пользователя.
- Функция RegisterHotKey — признак кейлоггера, она может использоваться для перехвата нажатий на клавиши;
- Связка из OpenSCManager, CreateService и StartService свидетельствует о создании системного сервиса. Она тоже может использоваться во вред, в частности для создания «неубиваемого процесса».
- Связка из URLDownloadToFile и ShellExecute — весьма вероятный признак трояна-даунлоадера;
- Функция TerminateProcess совместно со строками имен процессов антивирусных программ в одном файле практически однозначно свидетельствует о желании исследуемого файла обезопасить себя, грохнув процесс антивируса;
- Функции IsDebuggerPresent, CheckRemoteDebuggerPresent или OutputDebugString могут говорить о применении простейших антиотладочных приемов. В обычных программах они встречаются редко.
Код:
rule api_bandle
{
strings:
$str_api_1 = "OpenProcess"
$str_api_2 = "VirtualAllocEx"
$str_api_3 = "WriteProcessMemory"
$str_api_4 = "CreateRemoteThread"
condition:
$str_api_1 and $str_api_2 and $str_api_3 and $str_api_4
}
Код:
import "pe" //импортируем Yara-модуль pe
rule api_bandle
{
condition:
pe.imports("kernel32.dll", "OpenProcess") and pe.imports("kernel32.dll", "VirtualAllocEx") and pe.imports("kernel32.dll", "WriteProcessMemory") and pe.imports("kernel32.dll", "CreateRemoteThread")
}
Python:
import "pe" //импортируем Yara-модуль pe
rule api_bandle
{
strings:
$str_api_1 = "OpenProcess" xor
$str_api_2 = "VirtualAllocEx" xor
$str_api_3 = "WriteProcessMemory" xor
$str_api_4 = "CreateRemoteThread" xor
condition:
$str_api_1 and $str_api_2 and $str_api_3 and $str_api_4 and (pe.imports("kernel32.dll", "LoadLibrary") or pe.imports("kernel32.dll", "LoadLibraryEx")) and pe.imports("kernel32.dll", "GetProcAddress")
}
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
.В Yara imphash можно определить с помощью функции imphash() модуля pe:
Python:
import "pe"
rule imphash
{
condition:
pe.imphash() == "8a25c84dc57052979d26f561d4f12335"
}
Python:
import pefile
## не забудь указать реальный путь к исследуемому файлу
pe = pefile.PE(<путь к файлу>)
print('Imphash =', pe.get_imphash())
INFO
Утилита
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
тоже позволяет анализировать секцию импорта, причем она не только показывает импортируемые API-функции, но и отмечает те, что часто встречаются в малвари, и показывает возможный вектор атаки по классификации
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
.Анализ таблицы экспорта
Вредоносные файлы с экспортируемыми функциями — редкое явление, однако иногда на просторах вирусных полей они встречаются. Бывают в том числе и вредоносные DLL.
Таблицу экспорта, в которой перечислены экспортируемые функции, можно так же, как и таблицу импорта, посмотреть в CFF Explorer или Hiew.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Таблица экспорта в CFF Explorer
Здесь нужно обратить внимание на говорящие сами за себя названия экспортируемых функций, либо на названия функций в виде беспорядочного набора символов, либо на отсутствие названий функций при наличии только ординалов (номеров) функций (такое тоже может быть, ведь функции можно экспортировать не только по имени, но и по ординалу).
На Python можно сделать следующий скрипт для просмотра таблицы экспорта:
Python:
import pefile
## не забудь указать реальный путь к исследуемому файлу
pe = pefile.PE(<путь к файлу>)
if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
for export_entry in pe.DIRECTORY_ENTRY_EXPORT.symbols:
print('\t' + export_entry.name.decode('utf-8'))
print('\t\tОрдинал:', str(hex(export_entry.ordinal)))
print('\t\tRVA функции:', str(hex(export_entry.address)))
else:
print('Файл не содержит секцию экспорта.')
Анализ таблицы секций
Фактически все содержимое PE-файла разбито на секции. Каждая секция хранит в себе либо код, который будет исполнен при запуске файла, либо данные, необходимые для выполнения, либо ресурсы, используемые файлом. У каждой секции есть имя, однако операционная система определяет назначение секции не по имени, а по атрибуту Characteristics, а имена используются только для наглядности.
Помимо назначения секции атрибут Characteristics определяет операции, которые можно проводить с данными секции (чтение, выполнение, запись и т. д.). Более подробно о секции в целом и об этом атрибуте можно почитать
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
. Наиболее часто используемые названия секций:- .text или CODE — как правило, содержит исполняемый код (название секции CODE характерно для программ, написанных на Delphi), в большинстве случаев имеет значение атрибута Characteristics, равное 0x60000020 (IMAGE_SCN_CNT_CODE & IMAGE_SCN_MEM_EXECUTE & IMAGE_SCN_MEM_READ);
- .data или DATA — обычно здесь лежат данные для чтения или записи (название секции DATA также характерно для программ, написанных на Delphi), Characteristics чаще всего равен 0xс0000040 (IMAGE_SCN_CNT_INITIALIZED_DATA & IMAGE_SCN_MEM_READ & IMAGE_SCN_MEM_WRITE);
- .rdata — данные только для чтения, иногда здесь лежат таблицы импорта и экспорта, Characteristics равен 0x40000040 (IMAGE_SCN_CNT_INITIALIZED_DATA & IMAGE_SCN_MEM_READ) или 0x50000040 (IMAGE_SCN_CNT_INITIALIZED_DATA & IMAGE_SCN_MEM_READ & IMAGE_SCN_MEM_SHARED);
- .idata — информация об импорте (если секция отсутствует, то импорт содержится в секции .rdata), Characteristics чаще всего равен 0xс0000040 (такое же, как и у секции .data);
- .edata — информация об экспорте (если секция отсутствует, то экспорт содержится в секции .rdata), Characteristics обычно равен 0xс0000040 (такое же, как и у секции .data);
- .rsrc — ресурсы, используемые PE-файлом (иконки, диалоговые окна, меню, строки и т. д.), Characteristics равен 0x50000040 либо 0x40000040.
Увидеть это все легко можно с помощью, например, CFF Explorer.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Таблица секций в CFF ExplorerНа что нужно обратить внимание при анализе таблицы секций?
Во-первых, на необычные названия секций. Например, в виде беспорядочного набора символов.
Во-вторых, на несоответствие атрибута Characteristics назначению и содержимому секции. Например, может быть так, что у секции .text, в которой содержится исполняемый код, помимо прочего еще добавлено IMAGE_SCN_MEM_WRITE, то есть в секцию с кодом можно писать данные. Это явный признак самомодифицирующегося кода, и в обычных программах такое почти не встречается. То же можно сказать и про секцию с данными (.data или DATA): если в атрибуте Characteristics помимо прочего присутствует IMAGE_SCN_MEM_EXECUTE, то это очень серьезный повод для подозрения.
В-третьих, наличие секций вроде UPX0, UPX1 или .aspack красноречиво свидетельствует о применении соответствующих упаковщиков.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Секции UPX0 и UPX1 в запакованном файлеТакже о применении упаковщиков может свидетельствовать высокое значение (близкое к 8)
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
какой-либо секции. Посчитать энтропию секций PE-файла можно с помощью вот такого скрипта на Python:
Python:
import pefile
## не забудь указать реальный путь к исследуемому файлу
pe = pefile.PE(<путь к файлу>)
for section_entry in pe.sections:
print(section_entry.Name.decode('utf-8'))
print('\tCharacteristics:', hex(section_entry.Characteristics))
print('\tMD5 хэш секции:', section_entry.get_hash_md5())
print('\tЭнтропия секции:', section_entry.get_entropy())
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Значение энтропии одной из секций свидетельствует о возможном наличии упаковки
В Yara энтропию можно определить с помощью функции entropy() модуля
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
.Временная метка компиляции
Информация о времени компиляции анализируемого файла может быть полезна при построении графа атаки и его анализе. Время создания (и, соответственно, компиляции PE-файла) хранится в PE-заголовке в виде четырехбайтового числа, содержащего количество секунд, прошедших с 0 часов 0 минут 1 января 1970 года.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Время компиляции файла в CFF Explorer
В удобоваримом виде значение этого времени можно посмотреть с помощью такого скрипта:
Python:
import pefile
## не забудь указать реальный путь к исследуемому файлу
pe = pefile.PE(<путь к файлу>)
print('Дата и время компиляции:', time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(pe.FILE_HEADER.TimeDateStamp)))
Для Delphi (а вредоносные файлы, написанные на Delphi, встречаются и по сей день) это значение всегда равно 0x2a425e19, что значит 0 часов 0 минут 19 июня 1992 года. В этом случае реальную дату компиляции можно попытаться определить из отметки времени секции .rsrc (в файлах, создаваемых Delphi, она всегда присутствует). Временная метка находится по смещению 4 от начала секции .rsrc и представляет собой четырехбайтовое число в формате
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
.Посмотреть это значение в пристойном виде можно следующим скриптом:
Python:
import pefile
## не забудь указать реальный путь к исследуемому файлу
pe = pefile.PE(<путь к файлу>)
time_stamp_dos = pe.DIRECTORY_ENTRY_RESOURCE.struct.TimeDateStamp
## преобразуем время из MS DOS формата в «нормальный» вид
day = time_stamp_dos >> 16 & 0x1f
month = time_stamp_dos >> 21 & 0x7
year = (time_stamp_dos >> 25 & 0xff) + 1980
second = (time_stamp_dos & 0x1f) * 2
minute = time_stamp_dos >> 5 & 0x3f
hour = time_stamp_dos >> 11 & 0x1f
print('Дата и время компиляции: {}-{}-{} {:02d}:{:02d}:{:02d}'.format(day, month, year, hour, minute, second))
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Таблица Debug Directory в PE-файле и отметка о времени компиляции
Посмотреть временную метку компиляции из Debug Directory в «нормальном» виде можно следующим скриптом:
Python:
import pefile
## не забудь указать реальный путь к исследуемому файлу
pe = pefile.PE(<путь к файлу>)
time_stamp = pe.DIRECTORY_ENTRY_DEBUG[0].struct.TimeDateStamp
print('Дата и время компиляции:', time.strftime('%d-%m-%Y %H:%M:%S', time.gmtime(time_stamp)))
При анализе временной метки компиляции под подозрением должны быть:
- недавняя дата компиляции программы (или нереальные ее значения, например еще не наступившая дата);
- несовпадение даты компиляции и версии компилятора (согласись, странно видеть дату компиляции, например, 20 июня 2005 года для экзешника, откомпилированного Visual Studio 19 версии);
- значение даты компиляции равно нулю (велика вероятность, что создатель программы это сделал намеренно, соответственно возникает вопрос — зачем);
- для файлов, которые по всем признакам откомпилированы в Delphi, дата не соответствует значению 0x2a425e19, а дата, полученная из секции .rsrc, равна нулю или меньше, чем дата в PE-заголовке;
- дата компиляции из заголовка анализируемого файла не совпадает с датой, указанной в Debug Directory (весьма вероятно, что эти значения были зачем-то скорректированы).
У некоторых компонентов Windows поле TimeDateStamp в PE-заголовке может иметь интересные значения — либо из будущего (к примеру, у меня для «Блокнота» это 8 сентября 2028 года), либо из прошлого (встречаются компоненты, датированные 1980 годом).
Анализ ресурсов исполняемого файла
Ресурсы, необходимые для работы exe-файла (такие как иконки, диалоговые окна, меню, изображения, информация о версии, конфигурационные данные), хранятся в секции .rsrc. Просмотреть можно при помощи все того же CFF Explorer.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Содержимое секции .rsrc в CFF Explorer
Но все же для просмотра ресурсов в PE-файлах лучше использовать
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
.
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Просмотр информации о версии программы в секции ресурсов Resource Hacker
Поскольку в секции ресурсов могут хранится любые данные, туда могут быть помещены либо вредоносная нагрузка, либо драйвер (например, перехватывающий системные функции), либо еще что-нибудь не очень хорошее. Поэтому стоит призадуматься, если найдешь здесь что-то совсем не похожее на иконки, картинки, диалоги, окна, информацию о версии и прочие безобидные вещи.
Rich-сигнатура
В статье я не упомянул такую примечательную структуру PE-файла, как Rich-сигнатура. На нее тоже стоит обратить внимание при анализе подозрительных файлов. Почитать о ней на английском можно здесь:
- Rich Headers: Leveraging this Mysterious Artifact of the PE Format (
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки)
-
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки(NTCore)
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
.Заключение
С помощью нескольких относительно простых инструментов мы можем быстро проанализировать подозрительный исполняемый файл, частично (а иной раз и достаточно полно) понять, что он собой представляет, и вынести вердикт о возможной вредоносности. Однако при анализе сложных файлов, подвергнутых упаковке, шифрованию и обфускации, этого может оказаться недостаточно. Тогда без более детального статического и динамического анализа не обойтись. Об этом мы и поговорим в следующий раз.
Последнее редактирование: