Examiner les journaux d'événements en pratique avec Get-WinEvent — La rapidité du filtrage détermine le temps d'investigation
· Go Komura · PowerShell, Windows, Journaux d'événements, Investigation d'incidents, Amélioration opérationnelle, Systèmes d'information, Audit, Dépannage
« On dirait que le serveur a redémarré tout seul vendredi dernier au milieu de la nuit. » « Sur un poste en particulier, l’application métier plante plusieurs fois par mois. » — le point de départ de ce type d’investigation, c’est presque toujours le journal des événements Windows. Mais si vous faites défiler des centaines de milliers d’entrées dans l’interface graphique de l’Observateur d’événements, votre matinée entière y passe.
Avec Get-WinEvent en PowerShell, ce travail se termine en quelques dizaines de secondes. Mais il y a une condition : effectuer le filtrage au bon endroit. Si vous écrivez Get-WinEvent | Where-Object { ... }, tous les événements sont d’abord chargés puis écartés, ce qui peut même être plus lent que l’interface graphique.
Cet article présente la bonne façon d’utiliser le filtrage de Get-WinEvent, des recettes pour les investigations fréquentes sur le terrain (redémarrages inattendus, ouvertures de session, arrêts anormaux d’applications, arrêts de services), ainsi que la collecte depuis plusieurs machines.
Environnement de référence
| Élément | Contenu |
|---|---|
| Système d’exploitation ciblé | Windows 10/11, Windows Server. Get-WinEvent lit l’infrastructure de journal d’événements introduite à partir de Windows Vista, et peut traiter à la fois les journaux classiques et les journaux ETW1 |
| Version de PowerShell | Utilisable aussi bien avec Windows PowerShell 5.1 qu’avec PowerShell 7 (Get-WinEvent est une applet de commande réservée à Windows ; elle n’est pas disponible avec PowerShell 7 sur Linux/macOS). Le code de cet article est écrit pour fonctionner à la fois avec 5.1 et avec 71 |
| Droits | De nombreux journaux comme System ou Application peuvent être lus par un utilisateur ordinaire, mais la lecture du journal Security nécessite des droits d’administrateur ou l’attribution de droits équivalents. Certains journaux ne peuvent pas être obtenus si vous ne l’exécutez pas en tant qu’administrateur (la procédure d’attribution des droits figure au chapitre 4(2))12 |
| Récupération à distance | Au chapitre 5, la méthode 1 (-ComputerName) ne dépend pas du traitement à distance PowerShell (WinRM). En revanche, il faut avoir autorisé l’accès distant au service de journal d’événements dans le pare-feu de la machine cible. La méthode 2 (Invoke-Command) suppose WinRM1 |
1. Pour commencer, la conclusion
- Utilisez
Get-WinEvent, pasGet-EventLog. Le second est réservé à Windows PowerShell et ne traite que les journaux classiques ; il n’est pas utilisable avec PowerShell 7.1 - Effectuez le filtrage avec
-FilterHashtable. Comme le filtrage a lieu côté journal d’événements, c’est d’un ou plusieurs ordres de grandeur plus rapide qu’un filtrage en aval avecWhere-Object.3 - Les clés de
-FilterHashtablesont fixées d’avance :LogName,ProviderName,ID,Level,StartTime,EndTime,Keywords,Path,UserID, entre autres.3 - Pour des conditions complexes ou un filtrage sur les données d’événement, utilisez XPath (
-FilterXPath). Vous pouvez copier une expression XPath depuis les « Affichages personnalisés » de l’Observateur d’événements.1 Levelest une valeur numérique : 1 = Critique, 2 = Erreur, 3 = Avertissement, 4 = Information, 5 = Détaillé.4- La lecture du journal de sécurité nécessite des droits particuliers. Exécuter en tant qu’administrateur est le plus simple, mais pour la personne chargée de l’investigation, accorder uniquement la lecture via le groupe « Event Log Readers » ou une ACL de canal respecte mieux le principe du moindre privilège.12
- Regardez les données d’événement plutôt que la chaîne de message. En récupérant des données structurées avec
ToXml(), votre script ne dépend plus de la langue du système d’exploitation.1 - Vous pouvez aussi analyser des fichiers
.evtx. En spécifiant-Path, vous pouvez examiner localement un journal collecté sur place.1 - Pour une centralisation permanente, utilisez le Transfert d’événements Windows (WEF). Pour une investigation ponctuelle, une exécution parallèle avec
Invoke-Commandsuffit.5
2. Les deux types de journaux et le choix de l’applet de commande
Les journaux d’événements Windows se répartissent globalement en deux familles.
| Type | Exemple | Applet de commande utilisable |
|---|---|---|
| Journal classique | System / Application / Security | Get-EventLog (5.1 uniquement), Get-WinEvent |
| Journaux des applications et des services | Microsoft-Windows-TaskScheduler/Operational, entre autres |
Get-WinEvent uniquement |
C’est précisément dans cette seconde catégorie que se trouvent les informations utiles à l’investigation. L’historique d’exécution du planificateur de tâches, les journaux de blocs de script PowerShell, l’historique d’application de WindowsUpdate — la plupart des journaux décisifs pour identifier une cause se trouvent de ce côté. C’est pourquoi la bonne approche consiste à s’appuyer uniformément sur Get-WinEvent pour tout nouveau script.1
Commencez par vérifier quels journaux existent.
# Liste des journaux (par nombre d'entrées décroissant). Un journal avec RecordCount à 0 n'est pas alimenté
Get-WinEvent -ListLog * -ErrorAction SilentlyContinue |
Where-Object RecordCount -gt 0 |
Sort-Object RecordCount -Descending |
Select-Object LogName, RecordCount, MaximumSizeInBytes, IsEnabled -First 20
# Rechercher les journaux d'un produit particulier
Get-WinEvent -ListLog *TaskScheduler* | Format-Table LogName, IsEnabled, RecordCount
Get-WinEvent -ListProvider *PowerShell* | Select-Object Name
3. Le filtrage : tout dépend de « où » il est fait
Comparons trois façons d’écrire qui produisent le même résultat.
# [Le pire] Charger tout puis écarter côté PowerShell
Get-WinEvent -LogName System | Where-Object { $_.Id -eq 41 }
# [Recommandé] Filtrer côté journal d'événements (FilterHashtable)
Get-WinEvent -FilterHashtable @{ LogName = 'System'; ID = 41 }
# [Condition complexe] Filtrer avec XPath
Get-WinEvent -LogName System -FilterXPath "*[System[EventID=41]]"
La première convertit d’abord en objets des centaines de milliers d’événements avant de les écarter, si bien que la majeure partie du temps d’attente est gaspillée. Les deuxième et troisième filtrent côté API du journal d’événements, de sorte que seul ce qui est nécessaire est renvoyé.3
Les clés utilisables avec -FilterHashtable sont fixées d’avance.3
| Clé | Ce qu’elle spécifie | Exemple |
|---|---|---|
LogName |
Nom du journal | 'System', 'Microsoft-Windows-TaskScheduler/Operational' |
ProviderName |
Source de l’événement | 'Application Error', 'Service Control Manager' |
ID |
ID d’événement (tableau possible) | 41, @(1000, 1001) |
Level |
Gravité (numérique) | 2 (Erreur), @(1,2) |
StartTime / EndTime |
Période | (Get-Date).AddDays(-7) |
Keywords |
Mots-clés (succès/échec d’audit, etc.) | 9007199254740992 (audit réussi) |
Path |
Fichier .evtx |
'D:\collect\srv01_System.evtx' |
UserID |
SID de l’utilisateur | 'S-1-5-21-...' |
Les valeurs numériques de Level sont les suivantes.4
Valeur (Level) |
Affichage en environnement japonais | Affichage en environnement anglais |
|---|---|---|
| 1 | 重大 | Critical |
| 2 | エラー | Error |
| 3 | 警告 | Warning |
| 4 | 情報 | Information |
| 5 | 詳細 | Verbose |
Les deux colonnes de droite montrent les chaînes qui apparaissent dans la colonne « Niveau » de l’Observateur d’événements et dans la propriété LevelDisplayName des résultats de Get-WinEvent. LevelDisplayName change selon la langue d’affichage du système d’exploitation. Utilisez ce tableau de correspondance quand vous comparez visuellement une sortie, mais pour filtrer dans un script, spécifiez toujours la valeur numérique de Level (juger sur le nom affiché produit un script qui ne fonctionnera pas dans un environnement anglais).
Sous une forme pratique, cela donne ceci.
# Agréger les événements Erreur/Critique des 7 derniers jours, par source (premier geste pour cerner la situation)
$filter = @{
LogName = 'System', 'Application'
Level = 1, 2
StartTime = (Get-Date).AddDays(-7)
}
try {
Get-WinEvent -FilterHashtable $filter -ErrorAction Stop |
Group-Object ProviderName, Id |
Sort-Object Count -Descending |
Select-Object Count, Name -First 15
}
catch {
# Ne laisser passer silencieusement que le cas « aucun événement correspondant ». Indépendant de la locale
# Se baser sur FullyQualifiedErrorId (la chaîne de message ne correspond pas en environnement japonais)
if ($_.FullyQualifiedErrorId -notlike 'NoMatchingEventsFound*') { throw }
}
Comment lire le résultat. La sortie de Group-Object comporte deux colonnes : Count et Name. Comme le regroupement se fait sur plusieurs propriétés (ProviderName, Id), Name affiche source, ID d'événement séparés par une virgule (par exemple : Service Control Manager, 7034). Le tri se fait par nombre décroissant, donc le premier réflexe consiste à vérifier si une source inconnue apparaît en haut de liste et si un pic de nombre correspond à la période où l’incident s’est produit. Une fois une piste identifiée ici, approfondissez les événements individuels avec les recettes du chapitre suivant.
Lorsqu’aucun événement ne correspond, Get-WinEvent renvoie une erreur. Ne mettez pas trop facilement -ErrorAction SilentlyContinue ici. « Aucune correspondance », « pas de droits pour lire ce journal » et « la cible est inaccessible » finissent tous par produire le même « résultat vide ». C’est la pire façon dont cela puisse mal se passer dans une situation d’investigation.
La bonne approche est de capter l’erreur avec -ErrorAction Stop comme ci-dessus, et de ne l’ignorer que lorsque FullyQualifiedErrorId vaut NoMatchingEventsFound. Juger sur la chaîne de message ne fonctionne pas, car elle ne correspond pas en environnement japonais (pour l’approche de la gestion des erreurs, voir « Gestion des erreurs et conception des tentatives dans PowerShell »).
4. Recettes d’investigation fréquentes sur le terrain
(1) Redémarrages et arrêts inattendus
# 41 : redémarré sans arrêt normal (Kernel-Power)
# 6008 : arrêt inattendu (EventLog)
# 1074 : demande d'arrêt par un processus/utilisateur (qui ou quoi a provoqué l'arrêt)
# 6005/6006 : démarrage/arrêt du service de journal d'événements (= repère de démarrage/arrêt)
Get-WinEvent -FilterHashtable @{
LogName = 'System'
ID = 41, 1074, 6005, 6006, 6008
StartTime = (Get-Date).AddDays(-30)
} | Select-Object TimeCreated, Id, ProviderName,
@{ n = 'Message'; e = { ($_.Message -split "`r?`n")[0] } } |
Sort-Object TimeCreated -Descending | Format-Table -AutoSize
Comment lire le résultat. La sortie comporte quatre colonnes — TimeCreated, Id, ProviderName, Message (seulement la première ligne, car c’est long) — triées de la plus récente à la plus ancienne. Ce qu’il faut regarder n’est pas tant le contenu ligne par ligne que quels ID apparaissent dans quel ordre pour chaque redémarrage. Pour un redémarrage planifié, on voit apparaître le triplet 1074 (quelqu’un l’a demandé) → 6006 (arrêt du service de journal d’événements = arrêt normal) → 6005 (démarrage = démarrage terminé).
1074 est un événement important : il révèle qui a demandé le redémarrage. Si WindowsUpdate ou le nom d’un processus particulier y apparaît, la cause est quasiment établie. Si seuls 41 et 6008 apparaissent sans 1074, suspectez un arrêt anormal dû à une coupure d’alimentation ou à un blocage.
(2) Suivi des ouvertures et fermetures de session (journal de sécurité)
# 4624 : connexion réussie / 4625 : échec de connexion / 4634 : déconnexion
# Nécessite des droits de lecture sur le journal de sécurité (exécuter en tant qu'administrateur,
# ou ajouter au préalable le compte d'exécution au groupe Event Log Readers)
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4624, 4625, 4634
StartTime = (Get-Date).AddDays(-1)
} | ForEach-Object {
$xml = [xml]$_.ToXml()
$d = @{}
foreach ($n in $xml.Event.EventData.Data) { $d[$n.Name] = $n.'#text' }
[pscustomobject]@{
Heure = $_.TimeCreated
Type = switch ($_.Id) { 4624 { 'Connexion réussie' } 4625 { 'Échec de connexion' } 4634 { 'Déconnexion' } }
Utilisateur = $d['TargetUserName']
TypeConnexion = $d['LogonType'] # 2=interactive 3=réseau 10=RDP
AdresseSource = $d['IpAddress']
}
} | Where-Object Utilisateur -notlike '*$' | Format-Table -AutoSize
C’est ici l’exemple typique de l’utilisation des données d’événement. Découper Message avec une expression régulière dépend de la langue du système d’exploitation, mais comme l’EventData de ToXml() se référence par nom, le même script fonctionne aussi bien en environnement japonais qu’en environnement anglais.6
Comment lire le résultat. La sortie comporte cinq colonnes : Heure / Type / Utilisateur / TypeConnexion / AdresseSource (comme vous les construisez vous-même avec [pscustomobject], vous décidez aussi bien du nom des colonnes que de leur ordre). En ajoutant à la fin Where-Object Utilisateur -notlike '*$', vous éliminez les comptes d’ordinateur (dont le nom se termine par $), ne laissant que les comptes de personnes. Vérifiez les lignes où TypeConnexion vaut 3 (réseau) ou 10 (RDP) et dont AdresseSource affiche une adresse IP inconnue, ainsi que si le même utilisateur enchaîne plusieurs 4625 (échecs) en peu de temps.
Notez aussi que si l’audit n’est pas activé, l’événement n’est tout simplement pas enregistré. « Aucun résultat » ne signifie pas forcément « rien ne s’est produit » — cela peut vouloir dire « ce n’est pas enregistré ».
Donner « seulement la lecture » à la personne chargée de l’investigation. Il vaut mieux éviter de distribuer des droits d’administrateur juste pour permettre la lecture du journal de sécurité. En ajoutant le compte au groupe intégré Event Log Readers (SID S-1-5-32-573), il devient possible de lire le journal d’événements sans droits d’administrateur.2
# À exécuter sur l'ordinateur cible (droits d'administrateur requis).
# Le nom d'affichage des groupes intégrés peut varier selon la langue du système, donc spécifier le SID est plus sûr
Add-LocalGroupMember -SID 'S-1-5-32-573' -Member 'EXAMPLE\auditeur'
# Vérifier que l'ajout a réussi
Get-LocalGroupMember -SID 'S-1-5-32-573'
Pour le déployer sur plusieurs machines, utilisez la stratégie de groupe « Configuration ordinateur > Stratégies > Paramètres Windows > Paramètres de sécurité > Groupes restreints », ou les préférences de stratégie de groupe « Configuration ordinateur > Préférences > Paramètres du Panneau de configuration > Utilisateurs et groupes locaux », pour distribuer une configuration qui ajoute un groupe du domaine au groupe local Event Log Readers de chaque serveur.
Si vous voulez affiner encore par canal, vérifiez et modifiez les autorisations d’accès de chaque journal (SDDL) avec wevtutil.2
wevtutil gl Security # Afficher la configuration actuelle (channelAccess contient le SDDL)
# wevtutil sl Security /ca:<SDDL> # Modifier. /ca « remplace » le SDDL existant
/ca remplace la valeur, il ne l’ajoute pas. Notez toujours la sortie de wevtutil gl avant de la modifier.
(3) Arrêts anormaux d’applications
# 1000 : Application Error (plantage de l'application)
# 1026 : .NET Runtime (arrêt dû à une exception managée)
# 1001 : Windows Error Reporting (informations de bucket d'incident)
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
ID = 1000, 1001, 1026
StartTime = (Get-Date).AddDays(-14)
} | Select-Object TimeCreated, Id, ProviderName, Message |
Sort-Object TimeCreated -Descending | Format-List
1000 contient le nom du module fautif et l’offset, 1026 contient la pile d’exception .NET. Il est efficace d’identifier une piste ici avant de passer à l’analyse de vidage (« Introduction à la collecte de vidages sur incident Windows », « Lire un vidage sur incident avec WinDbg + SOS »).
(4) Arrêts et redémarrages de services
# 7034 : le service s'est arrêté de manière inattendue / 7031 : action de récupération après l'arrêt / 7045 : un nouveau service a été installé
Get-WinEvent -FilterHashtable @{
LogName = 'System'
ProviderName = 'Service Control Manager'
ID = 7031, 7034, 7045
StartTime = (Get-Date).AddDays(-30)
} | Select-Object TimeCreated, Id, Message | Format-List
7045 (installation d’un nouveau service) est aussi utile pour détecter l’installation non voulue d’un logiciel. Pour la conception opérationnelle des services Windows, consultez « Créer et exploiter des services Windows ».
(5) Historique d’exécution du planificateur de tâches
Cette section utilise XPath, alors commençons par en saisir le squelette. Pour XPath dans les journaux d’événements, il n’y a en réalité que deux formes à retenir.1
| Syntaxe | Ce qu’elle désigne | Exemple |
|---|---|---|
*[System[ ... ]] |
Champs communs à tout événement (ID d’événement, heure, niveau, fournisseur) | *[System[EventID=41]] |
*[EventData[Data[@Name='NomDuChamp']='valeur']] |
Champs propres à cet événement (données d’événement nommées) | *[EventData[Data[@Name='TaskName']='\AgrégationNocturne']] |
Il suffit de relier ces deux formes avec and / or. Comme la comparaison de valeurs utilise des guillemets simples, placer l’expression dans une chaîne ici-document PowerShell (@" … "@) évite de se soucier de l’imbrication des guillemets (le code ci-dessous illustre cette forme).
Plutôt que de la construire vous-même, il est plus rapide et plus sûr de laisser l’Observateur d’événements l’écrire et de la copier. Spécifiez les conditions dans l’interface graphique via « Observateur d’événements > (clic droit sur le journal cible) > Filtrer le journal actuel », puis basculez vers l’onglet « XML » de la boîte de dialogue : la même requête s’affiche sous forme XML. La partie comprise entre <Select Path="..."> et </Select> est directement la chaîne à passer à -FilterXPath.1
# [À éviter] Récupérer tous les événements puis filtrer sur le message affiché (dépendant de la langue)
Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-TaskScheduler/Operational'
StartTime = (Get-Date).AddDays(-3)
} -ErrorAction SilentlyContinue |
Where-Object { $_.Message -like '*AgrégationNocturne*' }
# [Correct] Filtrer côté serveur sur le nom de la tâche (données d'événement). Rapide et indépendant de la langue
$xpath = @"
*[System[TimeCreated[timediff(@SystemTime) <= 259200000]]]
and
*[EventData[Data[@Name='TaskName']='\AgrégationNocturne']]
"@
Get-WinEvent -LogName 'Microsoft-Windows-TaskScheduler/Operational' `
-FilterXPath $xpath -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, LevelDisplayName, Message | Format-List
timediff est une fonction XPath qui indique, en millisecondes, le « temps écoulé depuis maintenant » ; 259200000 correspond à 3 jours. Le nom de la tâche se spécifie avec le chemin complet au moment de l’enregistrement (\NomDeLaTâche si elle est directement sous la racine). Le Message affiché dépend de la langue configurée, et en plus le filtrage se ferait côté client ; conformément à la politique de cet article, filtrez donc sur les données d’événement.
Ce journal peut être désactivé par défaut. La méthode d’activation et le diagnostic lorsqu’une tâche ne s’exécute pas sont détaillés dans « Les tâches du planificateur de tâches ne s’exécutent pas et se terminent avec le code 0x1 ».
5. Examiner les journaux de plusieurs machines
Méthode 1 : lecture directe à distance
Get-WinEvent -ComputerName 'srv01' -FilterHashtable @{ LogName='System'; ID=41 } -MaxEvents 10
Méthode 2 : interroger en parallèle avec Invoke-Command (à privilégier lorsque le nombre de machines est élevé)
$servers = 'srv01', 'srv02', 'srv03'
Invoke-Command -ComputerName $servers -ScriptBlock {
Get-WinEvent -FilterHashtable @{
LogName = 'System'; Level = 1, 2; StartTime = (Get-Date).AddDays(-1)
} -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, ProviderName, LevelDisplayName
} | Sort-Object PSComputerName, TimeCreated
Invoke-Command s’exécute en parallèle sur plusieurs ordinateurs (« Introduction à PowerShell Remoting (WinRM) », « Le traitement parallèle en PowerShell »).
Méthode 3 : collecter les .evtx et les analyser localement
Vous pouvez lire directement un fichier exporté sur place. C’est plus rapide que d’interroger plusieurs fois à travers le réseau, et cela laisse aussi une trace comme preuve.
# Sur place : wevtutil epl System D:\collect\srv01_System.evtx
Get-WinEvent -Path 'D:\collect\srv01_System.evtx' -FilterXPath "*[System[(Level=1 or Level=2)]]" |
Select-Object TimeCreated, Id, ProviderName, Message
Méthode 4 : Transfert d’événements Windows (WEF) — c’est la solution pour une centralisation permanente. C’est une fonctionnalité standard qui transfère les événements de chaque poste vers un serveur de collecte, sans nécessiter l’installation d’un agent supplémentaire.5
6. Taille des journaux et durée de rétention
« Au moment de vouloir enquêter, le journal de cette période avait déjà été écrasé » est un échec extrêmement fréquent. La taille maximale par défaut est plutôt petite, et dans un environnement à forte volumétrie d’événements, elle fait un tour complet en quelques jours.
# Vérifier la configuration de taille actuelle et l'état de la rétention
Get-WinEvent -ListLog 'System', 'Application', 'Security' |
Select-Object LogName, IsEnabled, LogMode,
@{ n='MaxMB'; e={ [math]::Round($_.MaximumSizeInBytes / 1MB, 1) } },
RecordCount, OldestRecordNumber
# Modifier la taille maximale (droits d'administrateur requis. Exemple : porter le journal System à 256 Mo)
wevtutil sl System /ms:268435456
Sur un serveur destiné à être investigué, ou sur un poste où un incident se produit, la pratique établie consiste à élargir d’abord la taille du journal avant d’attendre la reproduction. Pour la gestion des générations de journaux et l’archivage automatique, voir aussi « PowerShell avancé — investigation, archivage et rapport des journaux ».
7. Bonnes pratiques du terrain (tableau de décision)
| Situation | Choix | Remarque |
|---|---|---|
| Nouveau script à écrire | Get-WinEvent |
Get-EventLog est limité à 5.1 et aux journaux classiques uniquement1 |
| Filtrer par nom de journal, ID, période | -FilterHashtable |
Le plus rapide et le plus lisible3 |
| Filtrer sur le contenu des données d’événement | -FilterXPath / -FilterXml |
Peut être copié depuis un affichage personnalisé de l’Observateur d’événements1 |
| Volume élevé, traitement lent | Réduire la période, utiliser -MaxEvents |
Ne pas faire le filtrage côté PowerShell |
| Vouloir extraire des valeurs du message | EventData de ToXml() |
Rend le script indépendant de la langue configurée1 |
| Investigation ponctuelle sur plusieurs machines | Invoke-Command |
S’exécute en parallèle5 |
| Centralisation permanente | Transfert d’événements Windows (WEF) | Fonctionnalité standard sans agent supplémentaire5 |
| Les journaux passés ont disparu | Augmenter la taille du journal | À faire avant d’attendre une reproduction |
8. Conclusion
- Standardisez-vous sur
Get-WinEvent.Get-EventLogn’est pas utilisable avec PowerShell 7 et ne traite qu’un ensemble limité de journaux. - Effectuez le filtrage avec
-FilterHashtableou-FilterXPath. Un filtrage en aval avecWhere-Objectdégrade le temps d’investigation d’un ou plusieurs ordres de grandeur. - Pour l’investigation d’un redémarrage, regardez 1074 (qui l’a demandé) en plus de 41 et 6008. Pour les arrêts anormaux d’application, 1000, 1026 et 1001 sont le point de départ.
- En utilisant les données d’événement de
ToXml()plutôt que la chaîne de message, votre script devient indépendant de la langue configurée. - Pour une investigation ponctuelle sur plusieurs machines, utilisez
Invoke-Command; pour une centralisation permanente, le Transfert d’événements Windows ; et si une preuve est nécessaire, collectez le.evtxpour l’analyser localement. - Si le journal de la période à examiner n’existe plus, rien n’est possible. Revoir la taille des journaux est la priorité absolue dans la préparation à la réponse aux incidents.
Téléchargement du code d’exemple
Le code présenté dans cet article est distribué sous une forme directement exécutable. Il comprend l’historique des redémarrages, l’historique des connexions, les échecs de tâches et la collecte sur plusieurs machines.
Télécharger le code d’exemple (zip)
Les exemples de cet article dépendant de Windows et du locataire, ils n’ont pas été vérifiés par exécution. Une analyse syntaxique et une analyse statique avec PSScriptAnalyzer ont été effectuées sur tous les fichiers, mais vérifiez impérativement le fonctionnement sur votre propre machine de test.
# Analyse syntaxique + analyse statique (exécutable même hors Windows)
./Invoke-SampleTests.ps1
Si vous n’avez pas d’endroit où vous exercer, il n’est pas nécessaire de vous entraîner sur des journaux de production sur un poste de travail métier. Le Bac à sable Windows permet de démarrer un Windows propre en quelques minutes, qui disparaît une fois fermé (« Accélérer la validation d’applications avec Windows Sandbox »). Cependant, comme le bac à sable est un environnement fraîchement démarré, il n’accumule presque aucun journal ; pour tester des journaux qui « s’accumulent avec le temps », comme l’historique des redémarrages ou des connexions, une machine virtuelle d’évaluation est plus adaptée. Il suffit largement de commencer par exécuter les commandes du chapitre 3 sur votre propre poste pour ressentir la différence de rapidité qu’apporte le filtrage.
Les valeurs de configuration (chemins, noms de serveurs, ID de locataire, etc.) sont des exemples. Ne les exécutez pas telles quelles en production : adaptez-les à votre propre environnement.
Articles connexes
- Les tâches du planificateur de tâches ne s’exécutent pas et se terminent avec le code 0x1 — Diagnostic des causes et conception d’une exploitation sûre
- Journal d’événements Windows, ETW et journalisation structurée
- Introduction à la collecte de vidages sur incident Windows - WER/ProcDump/WinDbg
- Introduction à PowerShell Remoting (WinRM) — Gérer plusieurs machines Windows en une fois
- Créer et exploiter des services Windows
- PowerShell avancé — Automatiser en toute sécurité l’investigation, l’archivage et le rapport des journaux
Domaines de conseil associés
合同会社小村ソフト (Komura Software LLC) prend en charge l’investigation d’incidents en environnement Windows, l’analyse de cause des redémarrages et arrêts anormaux d’applications survenant de manière intermittente, ainsi que la mise en place de mécanismes de collecte de journaux et de surveillance.
- Investigation de bugs et analyse de cause
- Conseil technique et revue de conception
- Modification et maintenance de logiciels Windows existants
- Contact
Références
-
Microsoft Learn, Get-WinEvent. Sur la possibilité de récupérer à la fois les journaux classiques et les journaux d’événements à partir de Windows Vista, l’obtention de listes avec -ListLog / -ListProvider, le filtrage avec -FilterHashtable / -FilterXPath / -FilterXml, la lecture de journaux archivés (.evtx) avec -Path, la récupération à distance avec -ComputerName, la limitation du nombre de résultats avec -MaxEvents, le fait que la lecture du journal de sécurité nécessite des droits d’administrateur, et la possibilité d’obtenir la représentation XML de chaque événement avec la méthode ToXml(). ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12 ↩13 ↩14 ↩15
-
Microsoft Learn, Active Directory security groups ─ Event Log Readers. Sur le fait que les membres du groupe intégré « Event Log Readers » peuvent lire le journal d’événements de l’ordinateur local (sans que cela n’accorde de droits d’administrateur). Pour modifier les autorisations d’accès d’un canal individuel, voir aussi sl /ca (accès au canal) de wevtutil. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Creating Get-WinEvent queries with FilterHashtable. Sur les clés spécifiables avec -FilterHashtable (LogName, ProviderName, Path, Keywords, ID, Level, StartTime, EndTime, UserID, Data, entre autres), sur le fait que le filtrage côté serveur est plus efficace qu’un filtrage avec Where-Object, et sur la façon de spécifier les valeurs de mots-clés ou de gravité. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Event Levels. Sur les valeurs standard des niveaux de gravité des événements (1 = Critical, 2 = Error, 3 = Warning, 4 = Informational, 5 = Verbose). ↩ ↩2
-
Microsoft Learn, Windows Event Forwarding. Sur la possibilité de transférer des événements depuis plusieurs machines Windows vers un serveur de collecte sans installation d’agent supplémentaire, et sur la spécification des cibles de collecte via des abonnements. Ainsi que sur l’exécution parallèle sur plusieurs ordinateurs avec Invoke-Command. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, 4624(S): An account was successfully logged on. Sur les éléments contenus dans les données d’événement d’une connexion réussie (TargetUserName, LogonType, IpAddress, entre autres), la signification des valeurs de type de connexion, et le fait que l’enregistrement dépend de la configuration de la stratégie d’audit. ↩
Articles associés
Articles récents partageant les mêmes étiquettes, pour approfondir des sujets proches.
Renforcer la sécurité de PowerShell — journalisation, AMSI, mode de langage, JEA
Ce guide rassemble la pratique pour utiliser PowerShell en toute sécurité sans l'interdire : activation de la journalisation des blocs de...
Automatiser le déploiement de postes avec winget et PowerShell — Rendre le manuel de procédure exécutable
Ce guide explique comment rendre reproductible la configuration des PC des nouveaux employés : installation d'applications et export/impo...
La stratégie de groupe (GPO) en pratique — fonctionnement, vérification de l'application et répartition des rôles avec Intune
Manipulez-vous un environnement AD sans vraiment comprendre ce que signifie « déployé par GPO » ? Cet article explique, avec un regard pr...
Politique d'audit de sécurité Windows et investigation des journaux d'événements — devenir capable de lire un 4625
Un guide pratique pour répondre à la demande « peux-tu vérifier les journaux d'échec de connexion ? ». Il couvre la relation entre la pol...
Guide pratique de Windows LAPS ── En finir avec le mot de passe administrateur local commun à tous les PC
Un mot de passe administrateur local commun à tous les PC est le terreau des attaques Pass-the-Hash, où la compromission d'une seule mach...
Sujets associés
Ces pages replacent le sujet dans un contexte plus large de services et de décisions.
Thèmes techniques Windows
Portail des sujets sur le développement Windows, l'analyse des incidents et la valorisation des actifs existants.
Services liés à ce sujet
Cet article est directement lié aux services suivants.
Développement d'applications Windows
Applications métier, intégration d'équipements et outils de communication, des besoins au développement.
Questions fréquentes
Questions souvent posées lors d’une consultation sur le sujet de cet article.
- Faut-il utiliser Get-EventLog ou Get-WinEvent ?
- Get-WinEvent. Get-EventLog ne fonctionne que dans Windows PowerShell 5.1 et ne peut traiter que les journaux classiques comme System, Application et Security. Les journaux situés sous « Journaux des applications et des services », ajoutés à partir de Windows Vista — par exemple des journaux détaillés comme Microsoft-Windows-TaskScheduler/Operational — ne peuvent être lus qu'avec Get-WinEvent. Comme Get-EventLog lui-même n'est pas disponible dans PowerShell 7, tout nouveau script que vous écrivez devrait s'appuyer uniformément sur Get-WinEvent.
- Get-WinEvent est trop lent, ce n'est pas utilisable pour une investigation.
- Il est probable que vous filtrez avec Where-Object en aval du pipeline. Avec cette façon d'écrire, tous les événements du journal sont d'abord chargés en objets dans PowerShell, puis ceux qui ne sont pas nécessaires sont écartés ensuite. Pour un journal de plusieurs centaines de milliers d'entrées, c'est irréaliste. En utilisant -FilterHashtable ou -FilterXPath, le filtrage s'effectue côté journal d'événements, et seuls les événements nécessaires sont renvoyés, ce qui accélère les choses d'un ou plusieurs ordres de grandeur. Prenez l'habitude de spécifier d'abord le nom du journal, la période et l'ID d'événement via FilterHashtable.
- Lorsque j'essaie de lire le journal de sécurité, l'accès est refusé.
- La lecture du journal de sécurité nécessite par défaut des droits spéciaux. Si c'est seulement pour vérifier localement, il suffit d'exécuter PowerShell « en tant qu'administrateur », mais si vous ne voulez pas donner des droits d'administrateur à la personne chargée de l'investigation, vous pouvez l'ajouter au groupe intégré « Event Log Readers » (lecteurs du journal des événements), ou n'autoriser que la lecture via les autorisations d'accès du canal (ACL). Du point de vue du moindre privilège, la seconde option est recommandée. Notez aussi qu'il se peut que le journal d'audit ne soit tout simplement pas enregistré : l'audit des ouvertures de session, par exemple, dépend de la configuration de la stratégie d'audit, donc si aucun événement n'est trouvé, vérifiez aussi si la stratégie elle-même est activée.
- Je veux extraire uniquement certaines valeurs (nom d'utilisateur, nom de processus) du message d'un événement.
- Plutôt que de découper la propriété Message avec une expression régulière, il est plus fiable d'utiliser Properties ou les données d'événement. Chaque événement peut obtenir sa représentation XML via la méthode ToXml(), qui contient des éléments nommés sous EventData. La chaîne de message affichée change selon la langue du système d'exploitation, mais la structure des données d'événement, elle, ne change pas, ce qui permet d'écrire un script qui fonctionne aussi bien en environnement japonais qu'en environnement anglais.
- Je veux examiner ensemble les journaux d'événements de plusieurs serveurs.
- Si le nombre de machines est faible, le paramètre -ComputerName de Get-WinEvent ou une exécution à distance via Invoke-Command suffit. Invoke-Command s'exécute en parallèle sur les machines indiquées, ce qui reste pratique jusqu'à une dizaine de machines. Si vous voulez centraliser cela de façon permanente, envisagez le Transfert d'événements Windows (WEF) pour les regrouper sur un serveur de collecte. Pour une investigation ponctuelle, exporter le fichier evtx sur chaque serveur puis l'analyser localement avec Get-WinEvent -Path est aussi une méthode efficace.
Profil de l’auteur
Page de présentation de l’auteur de l’article.
Go Komura
Représentant de KomuraSoft LLC
Spécialisé dans le développement de logiciels Windows, le conseil technique et l’analyse de pannes, notamment pour les systèmes existants et les incidents difficiles à reproduire.