
Powerview on steroids
Installation | Basic Usage | Obfuscation | Modules | Logging | User Defined Rules | MCP | Plugins | Acknowledgements
PowerView.py est une alternative à l'excellent script original PowerView.ps1. La plupart des modules utilisés dans PowerView sont disponibles ici (certains drapeaux ont été modifiés). L'objectif principal est d'obtenir une session interactive sans avoir à s'authentifier à plusieurs reprises auprès de ldap.
https://github.com/aniqfakhrul/powerview.py/wiki/Installation-Guide
[!NOTE] Notez que certaines fonctions kerberos ne fonctionnent pas encore parfaitement, mais elles feront l'essentiel du travail. Une utilisation détaillée se trouve dans la section Wiki
* Maintenir une connexion persistante
> [!TIP]
> La persistance de connexion est désactivée par défaut. Les sessions LDAP expirent après une période d'inactivité. Utilisez `--keepalive-interval` pour envoyer des requêtes périodiques afin de maintenir l'état de la session.
* Démarrer l'interface web```
powerview range.net/lowpriv:[email protected] --web [--web-host 0.0.0.0] [--web-port 3000] [--web-auth user:password1234]

--use-sign-and-seal et --use-channel-binding ne sont disponibles que si vous installez la bibliothèque ldap3 directement depuis cette branche```
powerview range.net/lowpriv:[email protected] [--use-channel-binding | --use-sign-and-seal | --use-simple-auth]* Initialisation avec schannel. L'option `--pfx` accepte un fichier de certificat au format pfx.
> [!NOTE]
> powerview essaiera de charger le certificat sans mot de passe lors de la première tentative. En cas d'échec, il demandera le mot de passe. Aucun paramètre de mot de passe n'est donc nécessaire.```
powerview 10.10.10.10 --pfx administrator.pfx

* Spécifiez les attributs de recherche```
Get-DomainUser -Properties samaccountname,description
* Compter les résultats```
Get-DomainUser -Count
* Formater la sortie dans un tableau.```
Get-DomainUser -Properties samaccountname,memberof -TableView
Get-DomainUser -Properties samaccountname,memberof -TableView [csv,md,html,latex]
Set-DomainObject -Identity "adminuser" -Set 'servicePrincipalname=@/path/to/local/file' Set-DomainObject -Identity "adminuser" -Append 'servicePrincipalname=@/path/to/local/file'
* Mode relais```
powerview 10.10.10.10 --relay [--relay-host] [--relay-port] [--use-ldap | --use-ldaps]

[!NOTE]
Cette démonstration montre qu'une authentification forcée a été réalisée à l'aide deprinterbug.py. Vous pouvez utiliser d'autres méthodes qui forcent l'authentification HTTP.
PowerView utilise ldapx-py pour obfusquer les requêtes LDAP et les paramètres associés, en faisant varier les motifs observables tout en préservant l'intention de la requête.
* Activer via CLI (codes de chaîne personnalisés)```
powerview range.net/lowpriv:[email protected] --obfuscate CZXANDR
[!TIP] Basculez l'option
Obfuscatedans les paramètres. Cela s'applique aux requêtes suivantes de la session active.
Ce qui est obscurci
Chaînes par défaut (lors de l'utilisation de --obfuscate sans valeur)
| Cible | Chaîne | Techniques |
|---|---|---|
| Filtre | CZNDR | Case, Zeros, aNR, De Morgan, Reorder |
Exécutez ldapx codes --all pour voir tous les codes d'obscurcissement disponibles.
[!NOTE] Les résultats sont fonctionnellement équivalents dans la plupart des cas, mais les expansions par approximation/jokers peuvent élargir les correspondances. Certains codes (G, O, S) peuvent ne pas être compatibles avec ldap3 - à utiliser avec prudence.
[!WARNING] Un obscurcissement excessif peut être rejeté par des serveurs stricts ou des outils intermédiaires. À n'utiliser qu'en cas de besoin.
PV > Add-ADComputer Get-ADObject Get-EventLogChannel Login-As Set-ADObject Add-ADUser Get-CA Get-EventLogPublisher Logoff-Session Set-ADObjectDN Add-CATemplate Get-CATemplate Get-ExchangeDatabase Reboot-Computer Set-CATemplate Add-CATemplateAcl Get-DMSA Get-ExchangeMailbox Remove-ADComputer Set-DomainCATemplate Add-DMSA Get-Domain Get-ExchangeServer Remove-ADObject Set-DomainComputerPassword Add-DomainCATemplate Get-DomainCA Get-GMSA Remove-ADUser Set-DomainDNSRecord Add-DomainCATemplateAcl Get-DomainCATemplate Get-GPOLocalGroup Remove-CATemplate Set-DomainObject Add-DomainComputer Get-DomainComputer Get-GPOSettings Remove-DMSA Set-DomainObjectDN Add-DomainDMSA Get-DomainController Get-LocalUser Remove-DomainCATemplate Set-DomainObjectOwner Add-DomainDNSRecord Get-DomainDMSA Get-NamedPipes Remove-DomainComputer Set-DomainRBCD Add-DomainGMSA Get-DomainDNSRecord Get-NetComputerInfo Remove-DomainDMSA Set-DomainUserPassword Add-DomainGPO Get-DomainDNSZone Get-NetLoggedOn Remove-DomainDNSRecord Set-NetService Add-DomainGroup Get-DomainForeignGroupMember Get-NetProcess Remove-DomainGMSA Set-ObjectOwner Add-DomainGroupMember Get-DomainForeignUser Get-NetService Remove-DomainGroupMember Set-RBCD Add-DomainObjectAcl Get-DomainGMSA Get-NetSession Remove-DomainObject Set-ShadowCred Add-DomainOU Get-DomainGPO Get-NetShare Remove-DomainObjectAcl Set-ShadowCredential Add-DomainUser Get-DomainGPOLocalGroup Get-NetTerminalSession Remove-DomainOU Shutdown-Computer Add-GMSA Get-DomainGPOSettings Get-ObjectAcl Remove-DomainUser Start-NetService Add-GPLink Get-DomainGroup Get-ObjectOwner Remove-GMSA Stop-Computer Add-GPO Get-DomainGroupMember Get-RBCD Remove-GPLink Stop-NetProcess Add-GroupMember Get-DomainObject Get-RegLoggedOn Remove-GroupMember Stop-NetService Add-NetService Get-DomainObjectAcl Get-SCCM Remove-NetService Unlock-ADAccount Add-ObjectAcl Get-DomainObjectOwner Get-ShadowCred Remove-NetSession clear Add-OU Get-DomainOU Get-ShadowCredential Remove-NetTerminalSession exit Clear-Cache Get-DomainRBCD Get-TrustKey Remove-ObjectAcl get_pool_stats ConvertFrom-SID Get-DomainSCCM Get-WDS Remove-OU history ConvertFrom-UACValue Get-DomainTrust Invoke-ASREPRoast Remove-ShadowCred taskkill Disable-DomainDNSRecord Get-DomainTrustKey Invoke-DFSCoerce Remove-ShadowCredential tasklist Get-DomainTrustMapping Find-ForeignGroup Get-DomainUser Invoke-Kerberoast Restart-Computer Find-ForeignUser Get-DomainWDS Invoke-MessageBox Restore-ADObject Find-LocalAdminAccess Get-EventLog Invoke-PrinterBug Restore-DomainObject
### Fonctions Domaine/LDAP
| Module | Alias | Description |
| ------ | ----- | ---- |
|Get-DomainUser||Interroger tous les utilisateurs ou des objets utilisateur spécifiques dans AD|
|Get-DomainComputer||Interroger tous les ordinateurs ou des objets ordinateur spécifiques dans AD|
|Get-DomainGroup||Interroger tous les groupes ou des objets groupe spécifiques dans AD|
|Get-DomainGroupMember||Interroger les membres d'un groupe de domaine spécifique|
|Get-DomainOU||Interroger toutes les UO ou des objets UO spécifiques dans AD|
|Get-Domain||Interroger les informations du domaine|
|Get-DomainController||Interroger les contrôleurs de domaine disponibles|
|Get-DomainDNSRecord||Interroger les enregistrements disponibles. Il parcourt toutes les zones DNS si -ZoneName n'est pas spécifié|
|Get-DomainDNSZone||Interroger les zones DNS disponibles dans le domaine|
|Get-DomainObject|Get-ADObject|Interroger tous les objets de domaine ou les objets de domaine spécifiés dans AD|
|Get-DomainObjectAcl|Get-ObjectAcl|Interroger les ACL de l'objet AD spécifié|
|Get-DomainSCCM|Get-SCCM|Interroger SCCM|
|Get-DomainRBCD|Get-RBCD|Recherche les comptes configurés pour la délégation contrainte basée sur les ressources|
|Get-DomainObjectOwner|Get-ObjectOwner|Interroger le propriétaire de l'objet AD|
|Get-DomainGMSA|Get-GMSA|Interroger les comptes de service gérés de groupe (gMSA) et récupérer leurs blobs de mot de passe|
|Get-DomainDMSA|Get-GDSA|Interroger les comptes de service gérés délégués (dMSA)|
|Remove-DomainGMSA|Remove-GMSA|Supprimer un compte de service géré de groupe (GMSA) existant du domaine|
|Remove-DomainDMSA|Remove-DMSA|Supprimer un compte de service géré délégué (dMSA) existant du domaine|
|Remove-DomainDNSRecord||Supprimer l'enregistrement DNS du domaine|
|Remove-DomainComputer|Remove-ADComputer|Supprimer l'ordinateur du domaine|
|Remove-DomainGroupMember|Remove-GroupMember|Supprimer un membre d'un groupe de domaine spécifique|
|Remove-DomainOU|Remove-OU|Supprimer les UO ou des objets UO spécifiques dans AD|
|Remove-DomainObjectAcl|Remove-ObjectAcl|Supprimer les ACL de l'objet AD spécifié|
|Remove-DomainObject|Remove-ADObject|Supprimer l'objet de domaine spécifié|
|Remove-DomainUser|Remove-ADUser|Supprimer l'utilisateur de domaine spécifié dans AD|
|Set-DomainDNSRecord||Définir l'enregistrement DNS du domaine|
|Set-DomainUserPassword||Définir le mot de passe de l'utilisateur de domaine spécifié|
|Set-DomainComputerPassword||Définir le mot de passe de l'ordinateur de domaine spécifié|
|Set-DomainObject|Set-ADObject|Définir pour les objets de domaine spécifiés dans AD|
|Set-DomainObjectDN|Set-ADObjectDN|Modifier l'attribut distinguishedName de l'objet ainsi que le changement d'UO|
|Set-DomainObjectOwner|Set-ObjectOwner|Définir le propriétaire de l'objet AD|
|Set-ShadowCredential|Set-ShadowCred|Gérer msDS-KeyCredentialLink (informations d'identification fantômes) pour un objet de domaine|
|Get-ShadowCredential|Get-ShadowCred|Lister les informations d'identification fantômes (msDS-KeyCredentialLink) pour un objet de domaine ou tous les objets|
|Remove-ShadowCredential|Remove-ShadowCred|Supprimer les informations d'identification fantômes par DeviceId ou tout effacer d'un objet de domaine|
|Add-DomainDNSRecord||Ajouter un enregistrement DNS au domaine|
|Disable-DomainDNSRecord||Désactiver l'enregistrement DNS en le pointant vers une adresse invalide|
|Add-DomainGMSA|Add-GMSA|Créer un nouveau compte de service géré de groupe (gMSA) dans le domaine|
|Add-DomainDMSA|Add-GMSA|Créer un nouveau compte de service géré délégué (dMSA) dans le domaine|
|Add-DomainUser|Add-ADUser|Ajouter un nouvel utilisateur de domaine dans AD|
|Add-DomainComputer|Add-ADComputer|Ajouter un nouvel ordinateur de domaine dans AD|
|Add-DomainGroupMember|Add-GroupMember|Ajouter un nouveau membre dans le groupe de domaine spécifié dans AD|
|Add-DomainOU|Add-OU|Ajouter un nouvel objet UO dans AD|
|Add-DomainGPO|Add-GPO|Ajouter un nouvel objet GPO dans AD|
|Add-DomainObjectAcl|Add-ObjectAcl|Droits pris en charge pour le moment : All, DCsync, RBCD, ShadowCred, WriteMembers|
|Clear-Cache||Vider le cache|
### Fonctions GPO
| Module | Alias | Description |
| ------ | ----- | ---- |
|Get-DomainGPO||Interroger les objets de stratégie de groupe du domaine|
|Get-DomainGPOLocalGroup|Get-GPOLocalGroup|Interroger tous les GPO d'un domaine qui modifient les appartenances aux groupes locaux via `Restricted Groups` ou `Group Policy preferences`|
|Add-GPLink||Créer un nouveau lien GPO vers une UO|
|Remove-GPLink||Supprimer le lien GPO d'une UO|
### Fonctions d'énumération d'ordinateurs
| Module | Alias | Description |
| ------ | ----- | ---- |
|Get-NetSession||[MS-SRVS] Interroger les informations de session pour l'ordinateur local ou un ordinateur distant|
|Get-NetShare||Interroger les partages ouverts sur l'ordinateur local ou un ordinateur distant|
|Get-NetLoggedOn||[MS-WKST] Interroger les utilisateurs connectés sur l'ordinateur local ou un ordinateur distant|
|Get-EventLog||[MS-EVEN6] Interroger les journaux d'événements Windows d'un ordinateur distant via RPC|
|Get-EventLogChannel||[MS-EVEN6] Lister les canaux de journaux d'événements sur un ordinateur distant avec détection de produits de sécurité|
|Get-EventLogPublisher||[MS-EVEN6] Lister les éditeurs de journaux d'événements sur un ordinateur distant avec détection de produits de sécurité|
|Get-NetService||[MS-SCMR] Interroger les services en cours d'exécution sur l'ordinateur local ou un ordinateur distant|
|Stop-NetService||[MS-SCMR] Arrêter un service spécifique sur l'ordinateur local ou un ordinateur distant|
|Get-NetProcess|tasklist|[MS-TSTS] Interroger les processus en cours d'exécution sur l'ordinateur local ou un ordinateur distant|
|Stop-NetProcess|taskkill|[MS-TSTS] Terminer un processus spécifique sur l'ordinateur local ou un ordinateur distant|
|Get-NetTerminalSession||[MS-TSTS] Interroger les sessions terminal actives sur l'ordinateur local ou un ordinateur distant|
|Remove-NetTerminalSession||[MS-TSTS] Terminer une session terminal spécifique sur l'ordinateur local ou un ordinateur distant|
|Stop-Computer|Shutdown-Computer|[MS-TSTS] Arrêter un ordinateur distant|
|Restart-Computer|Reboot-Computer|[MS-TSTS] Redémarrer un ordinateur distant|
### Fonctions ADCS
| Module | Alias | Description |
| ------ | ----- | ---- |
|Get-DomainCATemplate|Get-CATemplate|Interroger les modèles d'AC disponibles. Prend en charge le filtrage des modèles vulnérables|
|Get-DomainCA|Get-CA|Interroger l'autorité de certification (AC)|
|Remove-DomainCATemplate|Remove-CATemplate|Supprimer le modèle d'AC de domaine spécifié|
|Set-DomainCATemplate|Set-CATemplate|Modifier les attributs d'objet de domaine d'un modèle d'AC|
|Add-DomainCATemplate|Add-CATemplate|Ajouter un nouveau modèle d'AC de domaine|
|Add-DomainCATemplateAcl|Add-CATemplateAcl|Ajouter une ACL à un modèle de certificat. Droits pris en charge pour le moment : All, Enroll, Write|
### Fonctions Exchange
| Module | Alias | Description |
| ------ | ----- | ----------- |
|Get-ExchangeServer|Get-Exchange|Récupérer la liste des serveurs Exchange disponibles dans le domaine|
### Fonctions d'approbation de domaine
| Module | Alias | Description |
| ------ | ----- | ---- |
|Get-DomainTrust||Interroger toutes les approbations de domaine|
|Get-DomainTrustMapping||Mapper récursivement toutes les approbations accessibles depuis le domaine actuel. Saute dans chaque partenaire d'approbation et aplatit les résultats avec les colonnes `SourceName` / `TargetName` (reflète `Get-DomainTrustMapping` de PowerView.ps1). Utilisez `-NoRecurse` pour limiter au domaine de départ.|
|Get-DomainForeignUser|Find-ForeignUser|Interroger les utilisateurs qui sont dans un groupe en dehors du domaine de l'utilisateur|
|Get-DomainForeignGroupMember|Find-ForeignGroup|Interroger les groupes avec des utilisateurs en dehors du domaine du groupe et rechercher les membres étrangers|
### Fonctions diverses
| Module | Alias | Description |
| ------ | ----- | ---- |
|ConvertFrom-SID||Convertir un identificateur de sécurité (SID) donné en nom d'utilisateur/groupe|
|ConvertFrom-UACValue||Convertit une valeur entière UAC en forme lisible par un humain|
|Get-NamedPipes||Lister les canaux nommés (Named Pipes) pour un ordinateur spécifique|
|Invoke-DFSCoerce||Force l'authentification du compte machine via MS-DFSNM NetrDfsRemoveStdRoot()|
|Invoke-Kerberoast||Demande un ticket Kerberos pour un nom de principal de service (SPN) spécifié|
|Invoke-PrinterBug||Déclenche la fonction MS-RPRN RpcRemoteFindFirstPrinterChangeNotificationEx pour forcer un serveur à s'authentifier auprès d'une machine spécifiée|
|Unlock-ADAccount||Déverrouiller les comptes de domaine en modifiant l'attribut lockoutTime|
|Find-LocalAdminAccess||Recherche les ordinateurs du domaine local où l'utilisateur actuel a un accès administrateur local|
### Journalisation
Nous ne manquerons jamais de journaliser pour garder une trace des actions effectuées. Par défaut, powerview crée un dossier `.powerview` dans le répertoire personnel de l'utilisateur actuel _(~)_. Chaque fichier journal est généré en fonction de la date actuelle.
Exemple de chemin : `/root/.powerview/logs/bionic.local/2024-02-13.log`
### Détection de vulnérabilités
PowerView.py inclut un système intégré de détection de vulnérabilités qui identifie automatiquement les problèmes de sécurité courants d'Active Directory. Lors de l'interrogation des objets, les vulnérabilités seront affichées dans la sortie :```
vulnerabilities: [VULN-026] Domain with high machine account quota (allows users to add computer accounts) (MEDIUM)
[VULN-029] Domain with weak minimum password length policy (less than 8 characters) (HIGH)
Vous pouvez définir des règles personnalisées de détection de vulnérabilités en modifiant le fichier vulns.json situé dans le répertoire de stockage de PowerView (~/.powerview/vulns.json).
Chaque règle de vulnérabilité a la structure suivante :```json "rule_name": { "description": "Human-readable description of the vulnerability", "rules": [ { "attribute": "attributeName", "condition": "condition_type", "value": "value_to_check" }, { "attribute": "anotherAttribute", "condition": "another_condition", "value": "another_value" } ], "exclusions": [ { "attribute": "attributeName", "condition": "condition_type", "value": "value_to_exclude" } ], "severity": "low|medium|high|critical", "id": "VULN-XXX", "rule_operator": "AND|OR", "exclusion_operator": "AND|OR", "details": "Optional detailed explanation of the vulnerability and remediation steps" }
**Rule Components:**
- **rules** : Liste des conditions qui doivent être satisfaites pour que la vulnérabilité soit détectée
- **exclusions** : Liste des conditions qui, si elles sont satisfaites, excluront un objet de la détection même s'il correspond aux règles
- **rule_operator** : Comment combiner plusieurs règles (par défaut : « OR »)
- « AND » : Toutes les règles doivent correspondre
- « OR » : N'importe quelle règle peut correspondre
- **exclusion_operator** : Comment combiner plusieurs exclusions (par défaut : « OR »)
- « OR » : N'importe quelle exclusion peut correspondre pour exclure l'objet
- « AND » : Toutes les exclusions doivent correspondre pour exclure l'objet
- **negate** : Booléen facultatif (True/False) qui peut être ajouté à n'importe quelle règle pour inverser son résultat
**Supported Conditions:**
| Condition | Description |
| --------- | ----------- |
| `exists` | L'attribut existe |
| `not_exists` | L'attribut n'existe pas |
| `equals` | Correspondance exacte (insensible à la casse) |
| `not_equals` | Pas une correspondance exacte |
| `contains` | Correspondance de sous-chaîne (insensible à la casse) |
| `not_contains` | Aucune correspondance de sous-chaîne |
| `startswith` | Commence par la chaîne (insensible à la casse) |
| `endswith` | Se termine par la chaîne (insensible à la casse) |
| `older_than` | La date est plus ancienne que le nombre de jours spécifié |
| `newer_than` | La date est plus récente que le nombre de jours spécifié |
| `greater_than` | La valeur numérique est supérieure à la valeur spécifiée |
| `less_than` | La valeur numérique est inférieure à la valeur spécifiée |
| `greater_than_or_equal` | La valeur numérique est supérieure ou égale à la valeur spécifiée |
| `less_than_or_equal` | La valeur numérique est inférieure ou égale à la valeur spécifiée |
| `has_flag` | Le drapeau binaire est défini dans une valeur numérique |
| `missing_flag` | Le drapeau binaire n'est pas défini dans une valeur numérique |
| `any_flag_set` | N'importe lequel des drapeaux spécifiés est défini |
| `all_flags_set` | Tous les drapeaux spécifiés sont définis |
**Multiple Values:**
Vous pouvez spécifier plusieurs valeurs pour une condition en utilisant :
1. Chaîne séparée par des barres verticales : `"value": "value1|value2|value3"`
2. Format de liste : `"value": ["value1", "value2", "value3"]`
**Exemple de règle :**```json
"weak_password_policy": {
"description": "Domain with weak minimum password length policy (less than 8 characters)",
"rules": [
{
"attribute": "objectClass",
"condition": "contains",
"value": "domainDNS"
},
{
"attribute": "minPwdLength",
"condition": "less_than",
"value": 8
}
],
"exclusions": [],
"severity": "high",
"id": "VULN-029",
"rule_operator": "AND"
}
[!note] Ceci n'est pas inclus dans l'installation de base du projet. Vous pouvez exécuter
pip3 install .[mcp] or pip3 install powerview[mcp]pour inclure les fonctionnalités MCP.
Cela active le serveur Model Context Protocol, permettant aux agents IA d'interagir avec les fonctionnalités de PowerView via une interface standardisée par transport HTTP Streamable. Voir la documentation MCP pour plus de détails.
Le serveur MCP expose la plupart des fonctionnalités de PowerView via une interface d'outil standardisée. Cela inclut la possibilité de :
- Interroger et énumérer les objets Active Directory (utilisateurs, ordinateurs, groupes, UO)
- Récupérer des informations sur les approbations de domaine, les objets de stratégie de groupe (GPO) et les appartenances aux groupes
- Rechercher des vulnérabilités de sécurité et des erreurs de configuration
- ...
#### Claude Desktop
Claude Desktop ne prend pas encore en charge le transport basé sur HTTP [Github](https://github.com/orgs/modelcontextprotocol/discussions/16). Vous pouvez utiliser [mcp-proxy](https://github.com/sparfenyuk/mcp-proxy).
* Installer `mcp-proxy````bash
# Option 1: With uv (recommended)
uv tool install mcp-proxy
# Option 2: With pipx (alternative)
pipx install mcp-proxy
#### Cursor
Vous pouvez modifier cela dans les paramètres de Cursor, sous le bouton d'options MCP.
>[!tip]
>Activez le mode YOLO pour activer le mode autonome afin de ne pas avoir à cliquer sur le bouton "Run Tool" à chaque fois. En savoir plus [ici](https://docs.cursor.com/chat/agent#yolo-mode)```json
{
"mcpServers": {
"Powerview": {
"url": "http://127.0.0.1:5000/powerview"
}
}
}
[!warning] Lors de l'utilisation de MCP avec des modèles d'IA publics (comme Claude, GPT, etc.), vos données Active Directory peuvent être transmises à ces services et journalisées par eux selon leurs politiques de traitement des données. Soyez conscient de l'exposition d'informations sensibles lors de l'utilisation de ces outils. Nous ne sommes pas responsables des fuites de données ou des implications de sécurité résultant de la connexion de PowerView à des services d'IA tiers. Self-hosted FTW!
PowerView prend en charge un système de plugins basé sur des décorateurs qui vous permet d'ajouter de nouvelles commandes et de vous brancher avant/après les commandes existantes.
┌────────────────────────────────┐
│ Plugin Loader │
│ Scans directories on startup │
└──────────────┬─────────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌───────────────────┐ ┌───────────────────┐
│ builtin/ plugins │ │ ~/.powerview/ │
│ │ │ plugins/ │
│ dehashed.py │ │ │
│ highlight.py │ │ my_plugin.py │
│ recon.py │ │ ... │
└───────────────────┘ └───────────────────┘
│ │
└───────────────┬───────────────┘
▼
┌──────────────────────┐
│ Sanity Validation │
│ Check signatures & │
│ required decorators │
└──────────┬───────────┘
▼
┌──────────────────────┐
│ Plugin Registry │
│ │
│ commands: {} │
│ before_hooks: {} │
│ after_hooks: {} │
└──────────┬───────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Command Execution Flow │
│ │
│ User Input: "Get-DomainUser -Identity admin" │
│ │ │
│ ▼ │
│ ┌────────────────────────┐ │
│ │ @before hooks │ │
│ │ (modify args) │ │
│ └───────────┬────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────┐ │
│ │ Core command OR │ │
│ │ @command plugin │ │
│ └───────────┬────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────┐ │
│ │ @after hooks │ │
│ │ (modify results) │ │
│ └───────────┬────────────┘ │
│ │ │
│ ▼ │
│ Format & Display │
└─────────────────────────────────────────────────┘
Plugins are single `.py` files discovered automatically from two paths:
| Path | Purpose |
|------|---------|
| `powerview/plugins/builtin/` | Included with the package |
| `~/.powerview/plugins/` | User-managed plugins |
#### Built-in Plugins
| Plugin | Commands | Hooks | Description |
|--------|----------|-------|-------------|
| Recon | `Invoke-DomainRecon` | — | Single-command domain reconnaissance summary |
| Highlight | — | `after:Get-DomainUser` | Highlights passwords found in user descriptions |
#### Plugin Management```
Get-Plugin # List all plugins with status
Enable-Plugin -Name <plugin_name> # Enable a disabled plugin
Disable-Plugin -Name <plugin_name> # Disable a plugin at runtime
Créez un fichier .py dans ~/.powerview/plugins/. Les plugins utilisent trois décorateurs : @command pour enregistrer de nouvelles commandes, @before pour exécuter une logique avant une commande existante, et @after pour exécuter une logique après.```python
from powerview.plugins import command, before, after, PowerviewPlugin
plugin = PowerviewPlugin( name="CustomEnum", description="Custom enumeration helpers", author="yourname", version="1.0", )
@command("Get-DomainAdminUser", args=["-Identity", "-Properties", "-SearchBase"], description="Find users with adminCount=1") def get_domainadminuser(pv, args=None, identity=None, properties=None, searchbase=None): results = pv.get_domainuser( identity=identity or "*", properties=properties or ["sAMAccountName", "adminCount", "memberOf", "description"], searchbase=searchbase, ) if results: return [r for r in results if str(r.get("attributes", r).get("adminCount", "")) == "1"] return results
@before("Get-DomainUser", priority=10) def inject_enabled_filter(pv, args): """Automatically filter out disabled accounts.""" if not hasattr(args, 'ldapfilter') or not args.ldapfilter: args.ldapfilter = "(!(userAccountControl:1.2.840.113556.1.4.803:=2))" return args
@after("Get-DomainUser", priority=20) def add_password_age(pv, args, results): """Enrich results with password age.""" from datetime import datetime, timezone if not results: return results for entry in results: attrs = entry.get("attributes", entry) pwdlast = attrs.get("pwdLastSet") if isinstance(pwdlast, datetime): if pwdlast.tzinfo is None: pwdlast = pwdlast.replace(tzinfo=timezone.utc) age = (datetime.now(timezone.utc) - pwdlast).days attrs["PasswordAge"] = f"{age} days" return results
**Décorateurs:**
| Decorator | Signature | Description |
|-----------|-----------|-------------|
| `@command(name, args, description)` | `func(pv, args=None, **kwargs)` | Enregistre une nouvelle commande verbe-nom |
| `@before(command_name, priority)` | `func(pv, args)` | S'exécute avant une commande. Retourne les arguments modifiés ou `None` |
| `@after(command_name, priority)` | `func(pv, args, results)` | S'exécute après une commande. Retourne les résultats modifiés ou `None` |
> [!NOTE]
> `@before` et `@after` acceptent un nom de commande unique ou une liste (par exemple, `@after(["Get-DomainUser", "Get-DomainComputer"])`). Les valeurs de priorité inférieure s'exécutent en premier.
**Définitions avancées des arguments:**
Les arguments des plugins peuvent être de simples chaînes (`"-Identity"`) ou des dictionnaires pour un contrôle plus fin:```python
@command("Get-CustomThing", args=[
"-Identity",
{"name": "-Days", "type": int, "default": 90, "help": "Threshold in days"},
{"name": "-Verbose", "action": "store_true", "help": "Show details"},
])
[!TIP] Toutes les commandes de plugin reçoivent automatiquement les indicateurs
-OutFile,-TableViewet-SortBy.
| BaseDN |
CX |
| Case, heX encoding |
| Attributs | CR | Case, Reorder |