Comment suivre les événements de sécurité importants de Windows avec PowerShell


De nombreuses organisations comptent sur les technologies Microsoft pour accomplir leur travail. En même temps, les acteurs de la menace peuvent exploiter des systèmes d’exploitation comme Windows. Heureusement, Windows enregistre les événements de sécurité du système d’exploitation pour vous aider à retracer ce comportement.

Les événements de sécurité produits par Windows sont une ressource critique dans le processus de gestion des incidents. Des outils tels que l’Observateur d’événements de Windows de Microsoft fournissent l’accès nécessaire pour examiner les événements capturés, mais détecter les anomalies en faisant défiler manuellement un journal encombré est irréaliste.

Dans ce post, vous apprendrez comment retrouver les atteintes potentielles à la sécurité dans Windows en apprenant les politiques d’audit, les journaux d’événements Windows et en analysant les événements de sécurité avec PowerShell.

Prérequis

Cet article vise à transmettre des informations qui vous apprennent à analyser les événements de sécurité Windows avec PowerShell. Si vous souhaitez suivre l’une des démonstrations, vous aurez besoin de :

  • A Windows 10+ PC – This PC will be used to generate and track down potential security events in the event log. This tutorial will be using Windows PowerShell 5.1.
  • Droits d’administrateur sur le PC Windows
  • A PowerShell code editor such PowerShell ISE or Visual Studio (VS) Code.

Où Windows Stocke les Événements de Sécurité

Lorsqu’une action est entreprise sur un système d’exploitation Windows, Windows enregistre l’action comme un événement dans un ou plusieurs journaux d’événements. Les journaux d’événements deWindows sont stockés sur le système de fichiers, par défaut, dans le répertoire %SystemRoot%\system32\winevt\logs. Cette localisation peut être modifiée en modifiant la sous-clé de registre EventLog de l’événement correspondant.

Si vous souhaitez savoir où sont stockés les journaux d’événements les plus importants (Application, Sécurité et Système) sur votre système, copiez et collez le code ci-dessous dans une console PowerShell ou enregistrez-le en tant que script.

Pour accéder à l’emplacement de stockage du fichier journal de sécurité, vous devez exécuter le code en tant qu’administrateur.

# Présentez les journaux d'application, de sécurité et de système dans un tableau.
 $arrLogs = @(
     "Application"
     "Security"
     "System"
 )
 # Utilisez la cmdlet ForEach-Object pour cibler chaque journal respectif avec la cmdlet Get-ItemProperty.
 $arrLogs | ForEach-Object {
     # Utilisez la cmdlet Get-ItemProperty pour lister le chemin de fichier configuré pour le journal d'application, de sécurité et de système.
     Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\$_ -Name File | Select-Object PSChildName,File
 }

La capture d’écran suivante montre la sortie attendue du code, affichant le nom du journal et l’emplacement de stockage pour les fichiers journaux Application, Sécurité et Système.

Application, Security, and System audit log location

Politiques d’audit : Définir les événements à enregistrer

Par défaut, Windows ne capture pas tous les événements de sécurité qui pourraient être nécessaires pour détecter ou enquêter sur une intrusion. Pour contrôler ce que Windows enregistre ou non, vous devez définir et appliquer des stratégies d’audit. Une stratégie d’audit est un ensemble d’instructions transmises à Windows qui lui indiquent quels événements enregistrer.

Il existe plusieurs façons d’attribuer et de travailler avec des stratégies d’audit, telles que la stratégie de groupe. La stratégie de groupe fonctionne bien si vous devez mettre en œuvre des stratégies d’audit sur plusieurs machines. Mais dans cet article, vous allez vous concentrer sur un seul appareil, vous utiliserez donc l’outil auditpol. L’outil auditpol est installé avec Windows et vous permet de trouver et de définir des stratégies d’audit sur un système Windows.

Recherche des stratégies d’audit

Par exemple, pour trouver l’état de toutes les stratégies d’audit sur votre système Windows, utilisez le paramètre /get comme indiqué ci-dessous. En utilisant le paramètre /category suivi d’un joker, auditpol recherche l’état de toutes les stratégies d’audit, pas seulement celles correspondant à une catégorie ou sous-catégorie spécifique.

#Obtenez la configuration de la politique d'audit du système.
auditpol /get /category:*

La capture d’écran suivante montre une version tronquée de la sortie attendue du code, affichant la catégorie de politique d’audit Gestion des comptes, les sous-catégories et l’état (Paramétrage).

Audit policy category, subcategory, and configuration

A Setting that is configured as No Auditing means that all events associated with that audit policy subcategory will not be logged.

Paramétrage des politiques d’audit

L’outil auditpol peut faire plus que simplement afficher les paramètres de la politique d’audit. Il peut également les modifier en utilisant la commande auditpol /set. Pour démontrer les futures sections de ce tutoriel, ouvrez une console PowerShell en tant qu’administrateur et exécutez la commande ci-dessous. Cette commande commence à enregistrer tous les événements (réussis et échoués) qui font partie de la sous-catégorie de connexion.

La configuration de la sous-catégorie de connexion force votre système à enregistrer les événements suivants:

#Définir les événements de connexion pour capturer l'activité réussie/échouée.
auditpol /set /subcategory:"Logon" /success:enable /failure:enable

Il existe de nombreuses ressources disponibles pour vous aider à configurer une politique d’audit conforme aux meilleures pratiques, notamment les Normes du Center for Internet Security (CIS), les Guides d’implémentation technique de sécurité (STIG) de l’Agence des systèmes d’information de la Défense (DISA), et les conseils publiés par Microsoft.

Génération de journaux d’échec de connexion pour l’analyse

Cet article sera un tutoriel et s’attendra à ce que vous suiviez attentivement. Si vous avez configuré Windows pour auditer les événements de connexion, générons maintenant quelques événements de sécurité pour une analyse ultérieure. Plus précisément, générons 35 tentatives de connexion échouées qui seront enregistrées dans le journal de sécurité de votre système pour imiter une activité de force brute.

1. Ouvrez votre éditeur de code préféré.

2. Copiez le code suivant et collez-le dans l’éditeur de code. Cet extrait de code tente d’ouvrir le processus PowerShell.exe en utilisant la commande Start-Process en utilisant des noms d’utilisateur et des mots de passe fictifs.

#Définir 5 noms d'utilisateur à enregistrer comme échecs de connexion.
 $arrUsers = @(
     "AtaBlogUser1"
     "AtaBlogUser2"
     "AtaBlogUser3"
     "AtaBlogUser4"
     "AtaBlogUser5"
 )
 #Parcourir les noms d'utilisateur en utilisant ForEach-Object pour générer un échec de connexion pour chacun.
 $arrUsers | ForEach-Object {
     $securePassword = ConvertTo-SecureString "AtA810GRu13Z%%" -AsPlainText -Force 
     $storedCredential = New-Object System.Management.Automation.PSCredential($_, $securePassword)
     Start-Process -FilePath PowerShell -Credential $storedCredential
 }
 #Générer 30 échecs de connexion pour l'utilisateur AtaBlogUser.
 $i = 0
 Do {
     $securePassword = ConvertTo-SecureString "AtA810GRu13Z%%" -AsPlainText -Force 
     $storedCredential = New-Object System.Management.Automation.PSCredential("AtaBlogUser", $securePassword)
     Start-Process -FilePath PowerShell -Credential $storedCredential
     $i++
 } Until ($i -eq 30)

3. Enregistrez le script PowerShell sous Invoke-BogusEvents.ps1 ou tout autre nom que vous souhaitez et exécutez le script.

Lors de l’exécution, vous remarquerez une erreur attendue répétée 35 fois indiquant Le nom d’utilisateur ou le mot de passe est incorrect.

Authentication failure due to incorrect user name or password.

Si vous ne recevez pas la sortie attendue, assurez-vous que le service de connexion secondaire est dans un état En cours d’exécution.

Accès aux événements Windows avec PowerShell

Maintenant que vous êtes sûr d’avoir au moins 35 événements de sécurité Windows, voyons comment les trouver avec la commande Get-WinEvent de PowerShell.

Vous êtes peut-être familier avec la commande Get-EventLog de PowerShell, qui est également utilisée pour accéder au journal des événements de manière programmatique. Get-EventLog utilise une interface de programmation d’application Win32 (API) qui est obsolète et ne sera pas discutée dans ce post.

Ouvrez une console PowerShell en tant qu’administrateur et invoquez la cmdlet Get-WinEvent, en lui passant les paramètres FilterHashtable et MaxEvents comme indiqué ci-dessous.

La commande ci-dessous interroge le journal de sécurité de votre système (LogName='Security') pour l’identifiant d’événement 4625 (ID=4625) et renvoie les 10 dernières occurrences (MaxEvents 10).

# Filtrer le journal de sécurité pour les 10 premières occurrences de l'ID d'événement 4625
Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 10

Si réussi, vous devriez voir une sortie similaire à ce qui suit :

10 instances of Event ID 4625

Accéder aux propriétés de l’événement avec Get-WinEvent

Dans la section précédente, vous avez utilisé Get-WinEvent pour voir les événements de sécurité de Windows de manière générale, mais un événement Windows contient beaucoup plus d’informations. Chaque événement Windows a des propriétés précieuses que vous pouvez utiliser pour une analyse approfondie.

Événements Windows en XML

Lorsqu’un événement est enregistré dans Windows, il est stocké au format XML. Si c’est le cas, pourquoi votre commande Get-WinEvent renvoie-t-elle des objets PowerShell typiques ? La cmdlet Get-WinEvent lit l’API native de Windows et traduit les événements en objets PowerShell pour une fonctionnalité accrue.

Chaque événement Windows a divers attributs qui suivent un schéma XML ou une structure spécifique.

  • name – Le nom de la propriété
  • inType – La définition du type d’entrée ou comment l’événement accepte une valeur
  • outputType – La définition du type de sortie ou comment l’événement est enregistré

Recherche de modèles XML d’événements avec PowerShell

Comme mentionné précédemment, chaque événement de sécurité Windows est stocké en XML et possède un schéma spécifique, mais à quoi ressemble ce schéma? Découvrons-le.

Dans l’une des sections précédentes, vous avez généré quelques événements avec l’ID 4625 dans le journal des événements de sécurité. Ce type d’événement a des attributs spécifiques qui ne s’appliquent qu’à lui. Pour trouver ces attributs et à quoi ressemble le modèle:

1. Ouvrez une console PowerShell en tant qu’administrateur si ce n’est pas déjà fait.

2. Exécutez à nouveau Get-WinEvent, mais cette fois en utilisant le paramètre ListProvider en spécifiant le fournisseur que Windows utilise pour enregistrer les événements dans le journal des événements de sécurité et en ne renvoyant que la propriété Events.

La propriété Events contient tous les événements enregistrés par le fournisseur de liste et expose le modèle XML pour chacun de ces événements.

(Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events
Get Win Event List Provider

3. Maintenant que vous avez le code pour trouver les modèles de tous les types d’événements, limitez cela en ne renvoyant que l’événement associé à l’ID 4625.

(Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events | Where-Object -Property ID -eq 4625

4. Une fois que vous ne retournez que le type d’événement de connexion avec l’ID d’événement 4625, limitez cela à ne montrer que la propriété Template comme ci-dessous.

#Obtenir le modèle XML d'événement pour les propriétés d'événement de l'ID 4625.
 ((Get-WinEvent -ListProvider 'Microsoft-Windows-Security-Auditing').Events | Where-Object -Property ID -eq 4625).Template

La capture d’écran suivante montre une version tronquée de la sortie du code, identifiant le nom de la propriété de l’événement, le type d’entrée et le type de sortie. Vous pouvez voir que l’événement ID 4625 a des propriétés d’événement avec différentes définitions d’entrée et de sortie.

La capture d’écran ci-dessous met en évidence la propriété SubjectUserSid de l’événement ID 4625. Cet événement particulier accepte un type d’entrée (inType) de win:SID et rend la sortie (outType) comme une chaîne de caractères, c’est ainsi qu’elle est stockée dans le journal de sécurité.

XML template example

Comment PowerShell traduit XML en objets

Maintenant que vous avez vu comment Windows stocke les événements en XML et comment voir ces modèles dans PowerShell, voyons comment PowerShell traduit cet XML en objets.

1. Exécutez à nouveau la commande Get-WinEvent pour retourner notre ID d’événement 4625. Jusqu’à présent, rien de nouveau. Remarquez que PowerShell ne montre que quatre propriétés, TimeCreated, Id, LevelDisplayName et Message.

Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1
Get-WinEvent FilterHashtable

Par défaut, la cmdlet Get-WinEvent ne renvoie pas tous les attributs de la source de données XML de l’événement sous forme d’objet PowerShell.

2. Maintenant, envoyez la sortie de la commande ci-dessus à la cmdlet Select-Object et spécifiez le paramètre Property en passant une valeur de pour afficher toutes les propriétés.

Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1 | Select-Object -Property *

Remarquez ci-dessous que PowerShell cachait de nombreuses propriétés différentes. Plus précisément, une propriété appelée Properties. La propriété Properties contient la valeur de chaque attribut d’événement que vous avez vu précédemment dans le modèle XML.

Powershell hiding Properties

3. Limitez la sortie de la commande Get-WinEvent ci-dessus pour exposer la propriété Properties. Cette propriété stocke toutes les propriétés de l’événement, pas les propriétés de l’objet PowerShell, dans un tableau.

#Sortie du tableau des propriétés de l'événement pour la première instance de l'ID d'événement 4625
 $eventProperties = (Get-WinEvent -FilterHashtable @{LogName='Security';ID=4625} -MaxEvents 1).properties
 $eventProperties

Sur la gauche de la capture d’écran ci-dessous se trouve la sortie de la commande ci-dessus. Le tableau contient les valeurs pour chacun des attributs XML dans le modèle XML sur le côté droit de la capture d’écran.

La sortie du code affichée dans la capture d’écran indique qu’une tentative d’authentification a échoué pour l’utilisateur AtaBlogUser (TargetUserName) à partir du système Desktop-XXXXX (WorkstationName) en utilisant une adresse IP de ::1 (IpAddress).

Expected output correlating property values to Event ID 4625’s XML template.

Peut-être souhaitez-vous uniquement retourner la valeur pour la propriété d’événement TargetUserName. Puisque vous avez déjà stocké toutes les propriétés de l’événement dans une variable appelée $eventProperties, référencez le cinquième indice, qui contient la valeur pour TargetUserName.

Vous devez référencer la propriété valeur sur l’objet de propriété d’événement individuel pour ne retourner que la valeur (AtaBlogUser). $eventProperties[5].valeur

$eventProperties[5].value
Event attribute property positions

Les pratiques décrites tout au long de cette section seront utilisées dans les sections suivantes pour traquer la tentative de force brute que vous avez simulée précédemment dans ce post.

Détection d’une attaque par force brute

Vous êtes maintenant prêt à utiliser vos compétences PowerShell pour traquer l’attaque de force brute que vous avez reproduite plus tôt dans ce post ! Mettons vos compétences à l’épreuve en simulant à quoi cela pourrait ressembler de traquer une attaque de force brute basée sur une période spécifique.

Disons que vous avez été alerté sur un incident où votre organisation pense que quelqu’un essaie d’utiliser un compte administratif pour se connecter à un serveur Windows important. Cette activité a commencé hier. Vous devez découvrir le nombre d’événements ID 4625 : Échec de connexion d’un compte qui ont eu lieu au cours des dernières 24 heures et déterminer le type de connexion de chaque événement.

1. Trouvez tous les événements avec l’ID 4625 (ID=4625) dans le journal de sécurité de Windows (LogName="Security") pour les dernières 24 heures (StartTime=((Get-Date).AddDays(-1).Date), se terminant à l’heure actuelle (Get-Date).

$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1));EndTime=(Get-Date)}

2. Maintenant, comptez tous les événements stockés dans la variable pour déterminer s’il y a plus d’échecs de connexions que prévu.

$events.Count

Vous devriez maintenant voir une valeur numérique indiquant le nombre de fois où l’événement ID 4625 a été trouvé dans le journal d’événements de sécurité au cours des dernières 24 heures.

3. Vous avez donc déterminé qu’une attaque de force brute s’est produite, maintenant recherchez plus d’informations sur ces événements de sécurité Windows. Pour ce faire, retournez uniquement les attributs de chacun des événements qui vous intéressent.

Comme mentionné précédemment, chaque valeur pour un événement particulier est stockée dans un tableau avec un index spécifique. Les propriétés d’événements intéressantes pour cette démo sont les suivantes.

  • TargetUserName Index: [5]
  • LogonType Index: [10]
  • WorkstationName Index: [13]
  • IpAddress Index: [19]

Le code ci-dessous lit chaque objet dans la variable $events, rassemble uniquement les propriétés intéressantes et les concatène en une seule ligne.

#Extraire les propriétés TargetUserName, LogonType, WorkstationName et IpAddress de toutes les instances de l'ID d'événement 4625 au cours des dernières 24 heures.
 $events | ForEach-Object {
     ## Faire référence à la propriété de l'objet propriétés
     ## Ne retourner que la valeur des index 5, 10, 13 et 19 du tableau de propriétés
     ## Concaténer toutes les valeurs en les joignant par une virgule
     $_.properties[5,10,13,19].value -join ", "
 }

La capture d’écran ci-dessous montre une version tronquée de la sortie attendue du code, détaillant une liste séparée par des virgules de TargetUserName, LogonType, WorkstationName, et IpAddress.

A truncated version of the code’s output, detailing TargetUserName, LogonType, WorkstationName, and IpAddress property values.

Comme vous l’avez vu dans le modèle XML précédent, le modèle de l’ID d’événement 4625 a un attribut LogonType. Cet attribut indique la méthode par laquelle le compte a tenté de s’authentifier. Suite à des investigations approfondies, vous avez remarqué que le LogonType variait parfois.

LogonType attribute

La valeur LogonType est une valeur numérique de 2 à 11, mais qu’est-ce que cela signifie ? Vous effectuez des recherches et découvrez ce que signifie chaque valeur.

2 – Interactif – Un utilisateur s’est connecté à cet ordinateur.

3 – Réseau – Un utilisateur ou un ordinateur s’est connecté à cet ordinateur depuis le réseau.

4 – Lot – Le type de connexion par lot est utilisé par les serveurs de traitement par lots, où des processus peuvent être exécutés au nom d’un utilisateur sans leur intervention directe.

5 – Service – Un service a été démarré par le Gestionnaire de contrôle des services.

7 – Déverrouillage – Ce poste de travail a été déverrouillé.

8 – Texte clair réseau – Un utilisateur s’est connecté à cet ordinateur depuis le réseau. Le mot de passe de l’utilisateur a été transmis au package d’authentification sous forme non hachée. Les packages d’authentification intégrés hachent tous les identifiants avant de les envoyer à travers le réseau. Les identifiants ne traversent pas le réseau en texte brut (appelé également texte clair).

9 – Nouvelles informations d’identification – Un appelant a cloné son jeton actuel et spécifié de nouvelles informations d’identification pour les connexions sortantes. La nouvelle session de connexion a la même identité locale, mais utilise des informations d’identification différentes pour d’autres connexions réseau.

10 – Interactif à distance – Un appelant a cloné son jeton actuel et spécifié de nouvelles informations d’identification pour les connexions sortantes. La nouvelle session de connexion a la même identité locale, mais utilise des informations d’identification différentes pour d’autres connexions réseau.

11 – Interactif mis en cache – Un utilisateur s’est connecté à cet ordinateur avec des informations d’identification réseau qui étaient stockées localement sur l’ordinateur. Le contrôleur de domaine n’a pas été contacté pour vérifier les informations d’identification.

Maintenant que vous avez une bonne compréhension de chaque LogonType, plutôt que de voir une valeur numérique dans la sortie, vous voulez une chaîne plus descriptive. Pour créer des « maps » en PowerShell, utilisez une table de hachage.

$logonTypes = @{
     [uint32]2 = "Interactive"
     [uint32]3 = "Network"
     [uint32]4 = "Batch"
     [uint32]5 = "Service"
     [uint32]7 = "Unlock"
     [uint32]8 = "NetworkCleartext"
     [uint32]9 = "NewCredentials"
     [uint32]10 = "RemoteInteractive"
     [uint32]11 = "CachedInteractive"
 }

5. Combinez Get-WinEvent et la table de hachage LogonType avec ForEach-Object pour créer un script qui ne retournera que les propriétés que vous désirez avec une valeur conviviale pour LogonType, comme indiqué ci-dessous. La cmdlet Format-Table ajoute à la sortie conviviale en formatant la réponse de PowerShell sous forme de tableau.

#Utilisez Get-WinEvent pour accéder aux propriétés de chaque instance connectée de l'événement ID 4625
$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
## Créez la "map" de la valeur numérique à la chaîne
$logonTypes = @{
    [uint32]2 = "Interactive"
    [uint32]3 = "Network"
    [uint32]4 = "Batch"
    [uint32]5 = "Service"
    [uint32]7 = "Unlock"
    [uint32]8 = "NetworkCleartext"
    [uint32]9 = "NewCredentials"
    [uint32]10 = "RemoteInteractive"
    [uint32]11 = "CachedInteractive"
}
## Commencez le traitement de chaque objet dans le tableau $events
$events | ForEach-Object {
    ## Recherchez la valeur numérique dans la table de hachage
    $logonType = $logonTypes[$_.properties[10].value] 
    #Créez un objet PowerShell personnalisé pour afficher les propriétés d'événement pertinentes 
    [PSCustomObject]@{     
        TimeCreated = $_.TimeCreated     
        TargetUserName = $_.properties[5].value     
        LogonType = $logonType     
        WorkstationName = $_.properties[13].value     
        IpAddress = $_.properties[19].value 
    }
} | Format-Table -Wrap

À ce stade, vous avez maintenant un script qui renvoie des objets de type PSCustomObject vous permettant d’effectuer de nombreux types d’analyses différents ! Pour finaliser l’analyse de ce tutoriel, priorisez les tentatives de connexion échouées par TargetUserName. Pour prioriser les échecs par la propriété TargetUserName, combinez le code ci-dessus avec la cmdlet Group-Object. Utilisez Sort-Object et son commutateur Descending pour identifier l’utilisateur le plus offensant.

#Utilisez Get-WinEvent pour accéder aux propriétés de chaque instance enregistrée de l'événement ID 4625
$events = Get-WinEvent -FilterHashTable @{LogName="Security";ID=4625;StartTime=((Get-Date).AddDays(-1).Date);EndTime=(Get-Date)}
## Créez la correspondance valeur numérique à chaîne
$logonTypes = @{
    [uint32]2 = "Interactive"
    [uint32]3 = "Network"
    [uint32]4 = "Batch"
    [uint32]5 = "Service"
    [uint32]7 = "Unlock"
    [uint32]8 = "NetworkCleartext"
    [uint32]9 = "NewCredentials"
    [uint32]10 = "RemoteInteractive"
    [uint32]11 = "CachedInteractive"
}
## Commencez à traiter chaque objet dans le tableau $events
$events | ForEach-Object {
    ## Recherchez la valeur numérique dans la table de hachage
    $logonType = $logonTypes[$_.properties[10].value] 
    #Créez un objet PowerShell personnalisé pour afficher les propriétés d'événement pertinentes 
    [PSCustomObject]@{     
        TimeCreated = $_.TimeCreated     
        TargetUserName = $_.properties[5].value     
        LogonType = $logonType     
        WorkstationName = $_.properties[13].value     
        IpAddress = $_.properties[19].value 
    }
} | Group-Object -Property TargetUserName | Sort-Object -Property Count -Descending

Excellent travail ! Vous venez d’utiliser PowerShell pour détecter la tentative de force brute que vous avez simulée plus tôt dans ce post. Selon la sortie, AtaBlogUser a échoué à s’authentifier 30 fois au cours des dernières 24 heures !

AtaBlogUser Logon Failures

Prochaines étapes

Dans ce tutoriel, vous avez appris comment Windows enregistre les événements, comment activer l’enregistrement des événements pour certains types d’événements et comment construire un outil PowerShell pour interroger ces événements.

Avec le script PowerShell que vous avez maintenant, comment pouvez-vous l’améliorer ? Comment allez-vous prendre le code que vous avez appris aujourd’hui et construire un meilleur outil ?

Source:
https://adamtheautomator.com/windows-security-events/