Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Antimalware Scan Interface — система, которую в Microsoft создали для защиты от вредоносных сценариев на PowerShell. В этой статье я продемонстрирую, как работает один из методов обхода этого механизма. Мы будем запускать сценарий PowerShell как процесс под отладкой, что откроет некоторые интересные возможности.
На высоком уровне AMSI хукает каждую команду или сценарий во время выполнения и передает их локальному антивирусному ПО для проверки. Причем поддерживаются практически любые антивирусы, это может быть не только стандартный Defender.
AMSI умеет работать:
wscript
и cscript
); Проблема такой реализации в том, что amsi.dll
(в которой реализована вся логика AMSI) находится в адресном пространстве текущего процесса. Как следствие, у атакующих появляется возможность манипулировать этой библиотекой так, как они захотят сами. Уже придумано множество способов обхода, это и amsiInitFailed, и хукинг, и патчинг. Сегодня мы обсудим еще один метод обхода — запуск процесса PowerShell в режиме отладки.
Недавно я обнаружил интересную API-функцию DebugActiveProcess()
, которая позволяет нашему процессу стать дебаггером для другого процесса. Прототип у нее очень простой, ей нужно передать лишь PID процесса, который требуется отлаживать.
BOOL DebugActiveProcess( [in] DWORD dwProcessId);
К сожалению, абы какой процесс отлаживать не получится. Успешный вызов этой функции получится, только если выполняется хотя бы одно из следующих условий:
SeDebugPrivilege
; PROCESS_ALL_ACCESS
. Казалось бы, требования более чем серьезные, но ничто не мешает нам запустить процесс powershell.exe
как дочерний, а на дочерний процесс наш родительский уж точно сможет запросить маску PROCESS_ALL_ACCESS
.
Что же нам даст статус дебаггера? Единственное преимущество — возможность обрабатывать Debug-события, среди которых LOAD_DLL_DEBUG_EVENT
. Событие генерируется сразу же, как только идет попытка загрузки DLL в адресное пространство отлаживаемого процесса. Причем будет заполнена структура LOAD_DLL_DEBUG_INFO
, содержащая базовый адрес подгружаемой библиотеки. А с базовым адресом уже можно наворотить немало дел…
Предлагаю перейти к практике. Во‑первых, мы не можем слепо взять и запустить процесс, а потом непонятно когда прицепиться к нему отладчиком — так есть шанс пропустить момент загрузки amsi.dll
в процесс. Поэтому процесс должен быть запущен с флагом CREATE_SUSPENDED
. Во‑вторых, из‑за того, что мы никак не обрабатываем Debug-события, приложение может упасть. Поэтому после того, как пропатчим AMSI, следует как можно скорее переставать быть дебаггером.
Для создания процесса я написал отдельную функцию StartProcessSuspended()
.
DWORD StartProcessSuspended(LPWSTR ProcName, HANDLE& hThread, HANDLE& hProc) { STARTUPINFO si = { 0 }; PROCESS_INFORMATION pi = { 0 }; si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOWNORMAL; if (!CreateProcess(ProcName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED | CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { DWORD err = GetLastError(); std::cout << h("[-] Cant Create Suspended Process : ") << err << " " << GetWinapiErrorDescription(err) << std::endl; return -1; } hThread = pi.hThread; hProc = pi.hProcess;#ifdef DEBUG std::cout << h("[+] Process Created Successfully") << std::endl;#endif return pi.dwProcessId;}
Здесь дополнительно указан флаг CREATE_NEW_CONSOLE
. Он нужен, чтобы powershell.exe запускалась как новая консоль. Как будто мы ее запустили вручную, дважды кликнув на исполняемый файл. Функция возвращает PID созданного процесса, а также инициализирует хендлы, указывающие на главный поток процесса и на сам процесс.
Источник: xakep.ru