Как хакеры обходят проверку AMSI защиты

Инструменты хакинга

В последней статье посвященной антивирусам, я рассказал как обойти антивирус с помощью Chimera. В этой статье я покажу, как хакеры обходят проверку AMSI защиты.

Еще по теме: Обход антивируса в Meterpreter

Если вы пользователь Windows, тогда вам знакомо сообщение «Данный сце­нарий содер­жит вре­донос­ное содержимое и был заблокирован антивирусом» Это блокирующий механизма защиты Windows. Давайте разберемся, как его обходят хакеры.

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

AMSI (Anti-Malware Scan Interface) — это тех­нология Microsoft, которую раз­работа­ли для защиты компьютера от вирусов и другой малвари. Впер­вые была внед­рена в Windows 10. AMSI умеет в реаль­ном вре­мени перех­ватыва­ть и анализировать скрип­ты JavaScript, VBScript, VBA и коман­ды PowerShell.

Как это работает AMSI

При запуске скрипта или ини­циали­зации про­цесса PowerShell (или PowerShell_ISE), в про­цесс авто­мати­чес­ки заг­ружа­ется биб­лиоте­ка AMSI.DLL. Она пре­дос­тавля­ет нужный API для вза­имо­дей­ствия с анти­вирусом. Перед выполнением скрипта или коман­ды с помощью RPC подключается Microsoft Defender, он, в свою оче­редь, изучает получен­ные данные и отсы­лает ответ обратно AMSI.DLL. Если была обна­руже­на извес­тная вредоносная сиг­натура, выпол­нение останавливается и появ­ляет­ся сооб­щение о блокировке анти­вирус­ом.

Схема работы AMSI
Схема работы AMSI

На схеме выше обоз­начены две фун­кции — AmsiScanString() и AmsiScanBuffer(), они, в целом, глав­ные в цепоч­ке AmsiInitialize, AmsiOpenSession, AmsiScanString, AmsiScanBuffer и AmsiCloseSession. Если посмотреть Exports для amsi.dll, то можно увидеть это:

Экспорты amsi.dll библиотеки
Экспорты amsi.dll библиотеки

Но большая часть данного спис­ка нам сегод­ня не понадобиться.

Итак, после запуска PowerShell. До того как ввести какие‑нибудь коман­ды, будет заг­ружена AMSI.DLL и про­изой­дет вызов AmsiInitialize().

Здесь исполь­зуют­ся 2 аргу­мен­та: имя при­ложе­ния и ука­затель на струк­туру CONTEXT. Параметр amsiContext будет исполь­зовать­ся в каж­дом пос­леду­ющем вызове AMSI API.

Пос­ле ввода коман­ды и попытки выпол­нить скрипт, про­исхо­дит вызов AmsiOpenSession():

В этот момент переда­ются 2 аргу­мен­та: amsiContext, получен­ный на шаге AmsiInitialize(), и ука­затель на струк­туру SESSION. Параметр amsiSession будет исполь­зовать­ся в каж­дом пос­леду­ющем вызове AMSI API внут­ри данной сес­сии.

После чего в дело всту­пают AmsiScanString() и AmsiScanBuffer(). Вы можете понять по названию, какие именно парамет­ры они переда­ют.

Defender про­веря­ет буфер или стро­ку и воз­вра­щает резуль­тат. Если ответ от Defender — 32768, то вредонос обна­руже­н, еди­нич­ка сиг­нализи­рует, что все чис­то.

Вредонос обна­руже­н AMSI Windows
Вредонос обна­руже­н
Вредонос не обна­ружен AMSI Windows
Вредонос не обна­ружен

Ну и пос­ле всех выше перечис­ленных про­верок текущая сес­сия зак­рыва­ется с исполь­зуя AmsiCloseSession.

Как обойти AMSI защиту

Ме­ханизм AMSI исполь­зует сиг­натур­ное (rule-based) детек­тирова­ние угроз. Зная этот факт, мож­но при­думы­вать раз­ные так­тики и тех­ники. Некото­рые извес­тные спо­собы уже не сра­бота­ют, но, исполь­зуя модифи­кацию кода, обфуска­цию и крип­тование, мож­но добить­ся инте­рес­ных резуль­татов.

Для верифи­кации детек­та я буду исполь­зовать стро­ки AmsiUtils либо Invoke-Mimikatz. Разуме­ется, сами по себе эти сло­ва безобид­ны, но на них сра­баты­вает детект, так как они ловят­ся сиг­натура­ми. Если уж на AmsiUtils нет детек­та, то мож­но сме­ло гру­зить, нап­ример, PowerView и исполь­зовать его воз­можнос­ти по мак­симуму.

Итак, поеха­ли.

PowerShell downgrade

Пер­вый спо­соб, который иног­да сра­баты­вает, три­виален. PowerShell 2.0 уста­рел, но Microsoft не спе­шит уда­лять его из опе­раци­онной сис­темы. У ста­рой вер­сии PowerShell нет таких защит­ных механиз­мов, как AMSI, поэто­му для обхо­да детек­та иног­да дос­таточ­но исполь­зовать коман­ду powershell -version 2.

Обход защиты AMSI PowerShell downgrade

amsiInitFailed

Вто­рой спо­соб пре­дот­вра­тить ска­ниро­вание — это попытать­ся выс­тавить флаг amsiInitFailed для дан­ного про­цес­са. Дела­ется это сле­дующей коман­дой:

Од­нако тут не все так прос­то: что­бы выпол­нить эту коман­ду, при­дет­ся пот­рудить­ся, при­думы­вая спо­собы обфуска­ции PowerShell, так как на нее тоже сра­баты­вает детект.

Обход защиты AMSI amsiInitFailed
Увы, на нашу команду сработал детект

Нап­ример, обфусци­ровать эту коман­ду мож­но так:

При­мер обфусци­рован­ной коман­ды для amsiInitFailed
При­мер обфусци­рован­ной коман­ды для amsiInitFailed

Во вре­мя обфуска­ции мож­но про­явить фан­тазию. Нап­ример, так:

Или даже так:

Будет полезно ознакомиться с ресурсом amsi.fail.

Хукинг

Function hooking — метод, поз­воля­ющий нам получить управле­ние над фун­кци­ей до ее вызова. В дан­ном слу­чае полез­но будет переза­писать аргу­мен­ты, которые фун­кция AmsiScanBuffer() (или AmsiScanString()) будет переда­вать на про­вер­ку.

Тут все прос­то: инжектим DLL, которая пой­мает AmsiScanBuffer() и передаст на про­вер­ку что‑нибудь безобид­ное. Исполь­зовать мож­но, нап­ример, AmsiHook.dll, инжектор мож­но взять там же.

Обойти AMSI Хукинг
Ре­зуль­тат инжекта AmsiHook.dll

Патчинг памяти

Ис­поль­зующих дан­ный метод инс­тру­мен­тов мно­го, мож­но выб­рать любой рабочий. Прин­цип оди­наков: про­пат­чить AmsiScanBuffer(), что­бы всег­да воз­вра­щалось зна­чение «Про­вер­ка прой­дена успешно». Вот нес­коль­ко таких средств:

Для при­мера поп­робу­ем выпол­нить Memory Patching с помощью my-am-bypass.ps1.

Обойти AMSI Патчинг памяти
Ис­поль­зуем my-am-bypass.ps1

Вызов ошибки

Вспо­миная опи­сание прин­ципа работы AMSI, мож­но заметить, что во всех фун­кци­ях при­сутс­тву­ет струк­тура amsiContext. Идея спо­соба — выз­вать ошиб­ку в этой струк­туре и сло­мать весь цикл про­вер­ки. Слож­ности добав­ляет тот факт, что Microsoft никак не докумен­тиру­ет эту струк­туру, да и в целом мало и неохот­но пишет докумен­тацию для AMSI.

Рас­смот­рим этот спо­соб, исполь­зуя Frida (что­бы най­ти адрес) и дебаг­гер (что­бы пос­мотреть, что там про­исхо­дит).

Ис­сле­дуем amsiContext
Ис­сле­дуем amsiContext

Вве­дем что‑нибудь и пос­мотрим на вывод «Фри­ды».

Вы­вод «Фри­ды»
Вы­вод «Фри­ды»

Те­перь откро­ем про­цесс PowerShell в дебаг­гере и пос­мотрим, что же находит­ся по это­му адре­су. Раз­мера этой струк­туры мы не зна­ем, но пер­вые 4 бай­та — это AMSI.

Прос­мотр про­цесса PowerShell в отладчи­ке

 

Прос­мотр про­цесса PowerShell в отладчи­ке
Прос­мотр про­цесса PowerShell в отладчи­ке

Ис­сле­дуя про­исхо­дящее даль­ше, замеча­ем, что регистр rcx (в котором дол­жен лежать пер­вый аргу­мент фун­кции) срав­нива­ется с нашими четырь­мя бай­тами и, если эти зна­чения не рав­ны, выпол­няет­ся переход на amsi!AmsiOpenSession+0x4c.

amsi bypass

Мы видим, что фун­кция вер­нет нам то, что лежит в регис­тре eax. А в докумен­тации ука­зано, что воз­вра­щает­ся зна­чение с типом HRESULT.

На сай­те Microsoft мы находим нуж­ную информа­цию:

Ес­ли пер­вые четыре бай­та струк­туры кон­тек­ста не сов­падут с AMSI, AmsiOpenSession вер­нет ошиб­ку. Глав­ный воп­рос — к чему при­ведет эта ошиб­ка и что слу­чит­ся, если бай­ты все‑таки не сов­падут.

Единс­твен­ный спо­соб про­верить это — выз­вать ошиб­ку и пос­мотреть, что будет. Для это­го пос­тавим точ­ку оста­нова (breakpoint) на AmsiOpenSession, а затем поменя­ем 4 бай­та на зна­чение 0000. Убе­дим­ся, что в регис­тре rcx находит­ся зна­чение 49534d41 (dc rcx L1), изме­ним его на 0 (ed rcx 0), про­верим, что выпол­нение прош­ло успешно и в регис­тре rcx сей­час 00000000 (еще раз dc rcx L1).

Пат­чим AmsiOpenSession
Пат­чим AmsiOpenSession

Те­перь, если заг­лянуть в frida-trace, мы уви­дим завет­ное AmsiScanBuffer() Exit. При­вела ли эта ошиб­ка к наруше­нию цик­ла про­вер­ки AMSI? Про­верим эту теорию, выпол­нив что‑то «злов­редное».

Обход AMSI
Обход AMSI

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

Выводы

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

AMSI может сыг­рать важ­ную роль в защите сис­тем Windows 10 и Windows Server от ком­про­мета­ции. Но AMSI не панацея. И хотя Microsoft Windows Defender обес­печива­ет некото­рую защиту от обхо­да AMSI, зло­умыш­ленни­ки пос­тоян­но находят спо­собы скрыть вре­донос­ный кон­тент от обна­руже­ния.

Еще по теме: Внедрение кода в чужое приложение

Дима (Kozhuh)

Эксперт в кибербезопасности. Работал в ведущих компаниях занимающихся аналитикой компьютерных угроз. Анонсы новых статей в Телеграме.

Добавить комментарий