Мно­гие вре­донос­ные прог­раммы соп­ротив­ляют­ся отладке: они отсле­жива­ют и бло­киру­ют запуск популяр­ных ути­лит для монито­рин­га фай­ловой сис­темы, про­цес­сов и изме­нений в реес­тре Windows. Что­бы обхитрить такую мал­варь, мы напишем на Python собс­твен­ный инс­тру­мент для иссле­дова­ния образцов вре­донос­ных прог­рамм.

Ста­тичес­кий ана­лиз, как ты зна­ешь, под­разуме­вает иссле­дова­ние исполня­емо­го фай­ла без его запус­ка. Динами­чес­кий куда увле­катель­нее: в этом слу­чае обра­зец запус­кают и отсле­жива­ют все про­исхо­дящие при этом в сис­теме события. Для иссле­дова­теля инте­рес­нее все­го опе­рации с фай­ловыми объ­екта­ми, с реес­тром, а так­же все слу­чаи соз­дания и унич­тожения про­цес­сов. Для получе­ния более пол­ной кар­тины неп­лохо было бы отсле­живать вызовы API-фун­кций ана­лизи­руемой прог­раммой. Разуме­ется, экспе­римен­тировать с вре­доно­сом нуж­но в изо­лиро­ван­ной сре­де с исполь­зовани­ем вир­туаль­ной машины или песоч­ницы — ина­че он может нат­ворить бед.

info

Под­робнее о методи­ке ста­тичес­кого ана­лиза вре­донос­ных фай­лов ты можешь про­читать в статье «Мал­варь на прос­вет. Учим­ся быс­тро искать приз­наки вре­донос­ного кода».

Для отсле­жива­ния жиз­неде­ятель­нос­ти при­ложе­ний сущес­тву­ет целый арсе­нал готовых средств, сре­ди которых самое извес­тное — ути­лита Process Monitor из Sysinternals Suite. Эта тул­за в рек­ламе не нуж­дает­ся, она неп­лохо докумен­тирова­на и поль­зует­ся зас­лужен­ной популяр­ностью. Process Monitor спо­собен отсле­живать все изме­нения в фай­ловой сис­теме Windows, монито­рить опе­рации соз­дания и унич­тожения про­цес­сов и потоков, регис­три­ровать и отоб­ражать про­исхо­дящее в реес­тре, а так­же фик­сировать опе­рации заг­рузки DLL-биб­лиотек и драй­веров устрой­ств.

Process Monitor из состава Sysinternals Suite
Process Monitor из сос­тава Sysinternals Suite

От­сле­живать вызовы API-фун­кций мож­но с помощью ути­литы API Monitor фран­цуз­ской ком­пании Rohitab. Тутори­ал по работе с этой тул­зой мож­но най­ти на сай­те прог­раммы, прав­да на англий­ском язы­ке.

API Monitor
API Monitor

Са­мый глав­ный недос­таток этих ути­лит (как, впро­чем, и дру­гих широко рас­простра­нен­ных прог­рамм такого рода) имен­но в их популяр­ности. Потому что с ними отлично зна­комы не толь­ко ана­лити­ки, но и вирусо­писа­тели. Далеко не любая мал­варь поз­волит исполь­зовать подоб­ные инс­тру­мен­ты и без­наказан­но иссле­довать свое поведе­ние в сис­теме. Наибо­лее прод­винутые тро­яны фик­сиру­ют любые попыт­ки запус­ка анти­виру­сов и средств ана­лиза сос­тояния ОС, а затем либо пыта­ются все­ми прав­дами и неп­равда­ми при­бить соот­ветс­тву­ющий про­цесс, либо прек­раща­ют активные дей­ствия до луч­ших вре­мен.

Тем не менее сущес­тву­ют спо­собы перехит­рить мал­варь. Один из наибо­лее оче­вид­ных — изоб­рести собс­твен­ный инс­тру­мент, который будет уметь (хотя бы час­тично) то же самое, что дела­ют 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 wmi
notify_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.mmmmmmsYYY (более под­робно об этом фор­мате мож­но почитать здесь), поэто­му для вывода вре­мени в более при­выч­ной фор­ме мож­но написать неч­то вро­де фун­кции пре­обра­зова­ния фор­мата вре­мени:

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"). Спи­сок свой­ств про­цес­са может быть рас­ширен (более под­робно о свой­ствах про­цес­сов мож­но почитать здесь).

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

1 комментарий

  1. Аватар

    s00mbre

    25.05.2021 в 08:55

    Полезная статья, спасибо!

Оставить мнение