Содержание статьи
Статический анализ, как ты знаешь, подразумевает исследование исполняемого файла без его запуска. Динамический куда увлекательнее: в этом случае образец запускают и отслеживают все происходящие при этом в системе события. Для исследователя интереснее всего операции с файловыми объектами, с реестром, а также все случаи создания и уничтожения процессов. Для получения более полной картины неплохо было бы отслеживать вызовы API-функций анализируемой программой. Разумеется, экспериментировать с вредоносом нужно в изолированной среде с использованием виртуальной машины или песочницы — иначе он может натворить бед.
info
Подробнее о методике статического анализа вредоносных файлов ты можешь прочитать в статье «Малварь на просвет. Учимся быстро искать признаки вредоносного кода».
Для отслеживания жизнедеятельности приложений существует целый арсенал готовых средств, среди которых самое известное — утилита Process Monitor из Sysinternals Suite. Эта тулза в рекламе не нуждается, она неплохо документирована и пользуется заслуженной популярностью. Process Monitor способен отслеживать все изменения в файловой системе Windows, мониторить операции создания и уничтожения процессов и потоков, регистрировать и отображать происходящее в реестре, а также фиксировать операции загрузки DLL-библиотек и драйверов устройств.
Отслеживать вызовы API-функций можно с помощью утилиты API Monitor французской компании Rohitab. Туториал по работе с этой тулзой можно найти на сайте программы, правда на английском языке.
Самый главный недостаток этих утилит (как, впрочем, и других широко распространенных программ такого рода) именно в их популярности. Потому что с ними отлично знакомы не только аналитики, но и вирусописатели. Далеко не любая малварь позволит использовать подобные инструменты и безнаказанно исследовать свое поведение в системе. Наиболее продвинутые трояны фиксируют любые попытки запуска антивирусов и средств анализа состояния ОС, а затем либо пытаются всеми правдами и неправдами прибить соответствующий процесс, либо прекращают активные действия до лучших времен.
Тем не менее существуют способы перехитрить малварь. Один из наиболее очевидных — изобрести собственный инструмент, который будет уметь (хотя бы частично) то же самое, что делают Process Monitor, API Monitor и им подобные программы. Чем мы, благословясь, и займемся.
Для работы мы будем использовать Python (не зря же он считается одним из самых хакерских языков программирования). Отслеживать интересующие нас события, связанные с реестром, файловой системой или процессами, можно двумя путями: используя специализированные API-функции Windows и при помощи механизмов WMI (Windows Management Instrumentation, или инструментарий управления Windows).
То есть, помимо Python, нам понадобятся модуль pywin32 и модуль WMI. Установить их очень просто (на самом деле достаточно поставить только пакет WMI, а он уже самостоятельно подгрузит pywin32):
pip install pywin32
pip install wmi
Чтобы отследить вызовы API-функций, понадобится модуль WinAppDbg. Этот модуль работает только со второй версией Python (если говорить точнее, то потребуется 2.5, 2.6 или 2.7), поэтому старый Python рано окончательно списывать в утиль. Тем более что автор WinAppDbg пока не планирует переписывать модуль под третью версию в связи с необходимостью рефакторинга большого объема кода, о чем прямо говорит в документации. Установить модуль можно через pip:
pip install winappdbg
Cкачав и установив все необходимые модули, приступим к таинству написания собственного инструмента для динамического анализа малвари.
Отслеживаем процессы
Отслеживать процессы будем с помощью механизма WMI. Это делается достаточно просто:
import wminotify_filter = "creation"process_watcher = wmi.WMI().Win32_Process.watch_for(notify_filter)while True: new_process = process_watcher() print(new_process.Caption) print(new_process.CreationDate)
Здесь notify_filter
может принимать следующие значения:
-
"operation"
— реагируем на все возможные операции с процессами; -
"creation"
— реагируем только на создание (запуск) процесса; -
"deletion"
— реагируем только на завершение (уничтожение) процесса; -
"modification"
— реагируем только на изменения в процессе.
Далее (в третьей строке) мы создаем объект‑наблюдатель process_watcher
, который будет срабатывать каждый раз, когда наступает событие с процессами, определенное в notify_filter
(в нашем случае при его запуске). После чего мы в бесконечном цикле выводим имя вновь запущенного процесса и время его запуска. Время представлено в виде строки в формате yyyymmddHHMMSS.
(более подробно об этом формате можно почитать здесь), поэтому для вывода времени в более привычной форме можно написать нечто вроде функции преобразования формата времени:
def date_time_format(date_time): year = date_time[:4] month = date_time[4:6] day = date_time[6:8] hour = date_time[8:10] minutes = date_time[10:12] seconds = date_time[12:14] return '{0}/{1}/{2} {3}:{4}:{5}'.format(day, month, year, hour, minutes, seconds)
Вообще, делать такие вещи просто в бесконечном цикле не очень хорошо, поэтому мы оформим все это в виде класса, чтобы потом запускать его в отдельном потоке. Таким образом мы получим возможность отслеживать в одном потоке, например, моменты создания процессов, а в другом — их уничтожения. Итак, класс ProcessMonitor
:
class ProcessMonitor(): def __init__(self, notify_filter='operation'): self._process_property = { 'Caption': None, 'CreationDate': None, 'ProcessID': None, } self._process_watcher = wmi.WMI().Win32_Process.watch_for( notify_filter ) def update(self): process = self._process_watcher() self._process_property['EventType'] = process.event_type self._process_property['Caption'] = process.Caption self._process_property['CreationDate'] = process.CreationDate self._process_property['ProcessID'] = process.ProcessID @property def event_type(self): return self._process_property['EventType'] @property def caption(self): return self._process_property['Caption'] @property def creation_date(self): return date_time_format(self._process_property['CreationDate']) @property def process_id(self): return self._process_property['ProcessID']
При инициализации класса мы создаем список свойств процесса _process_property
в виде словаря и определяем объект наблюдателя за процессами (при этом значение notify_filter
может быть определено в момент инициализации класса и по умолчанию задано как "operation"
). Список свойств процесса может быть расширен (более подробно о свойствах процессов можно почитать здесь).
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»