Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

PrivHound

Local Privilege Escalation, as a Graph.

A BloodHound OpenGraph collector that models Windows local privilege escalation as interconnected attack paths not a wall of text.


The Problem

For a long time, BloodHound has proven that attackers think in graphs, transforming Active Directory misconfigurations from static checklists into explorable attack paths. Yet when it comes to local privilege escalation, the industry is still stuck in 2015: run a tool, read a wall of text, manually connect the dots or have LLM do it for you :P

WinPEAS, PowerUp, and Seatbelt are excellent at finding individual misconfigurations, but they cannot answer questions like:

  • "Does this writable Program Files directory actually lead to SYSTEM because a service runs a binary from it?"
  • "Does this PowerShell history file contain credentials that are valid for a local admin?"
  • "Can I read another user's profile, find their stored credentials, log in as them, and exploit a service they have write access to?"

These tools report findings in isolation. In reality, privilege escalation is a multi-step chain where one finding feeds into another. A writable directory means nothing if no service runs from it. A credential in a history file means nothing if it doesn't belong to a privileged user. The real question is never "what misconfigurations exist?" — it's "what can I actually reach from here?"

If Active Directory attacks can be thought of as a graph, why not local privilege escalation?

The Solution

PrivHound changes this by modeling local privilege escalation as a graph. Built on BloodHound's OpenGraph framework, it enumerates 29 categories of Windows privilege escalation vectors, from weak service permissions to COM hijacking to WebClient relay and outputs them as interconnected nodes and edges.

The result: multi-hop escalation chains become visible, queryable with Cypher, and overlayable on top of existing Active Directory attack paths.

Example: Your current user can read the profile of another user on the machine. That profile contains cleartext credentials stored on their desktop for a third user. That third user has write permission to a service binary running as Administrator. No existing tool connects these dots. PrivHound does automatically.

CurrentUser ─PHCanAccessProfile─→ OtherUser's Profile
  ─PHProfileContains─→ .git-credentials ─PHContainsCreds─→ ...
    ─PHCanLoginAs─→ UserX ─PHCanWriteBinary─→ VulnService ─PHRunsAs─→ SYSTEM


What It Checks

#CheckTechniqueMITRE
1Weak Service PermissionsModifiable services running as SYSTEMT1574.011
2Writable Service BinariesReplace service .exe with payloadT1574.010
3Unquoted Service PathsPath hijacking via writable intermediate dirsT1574.009
4DLL Hijacking (PATH)Writable directories in system PATHT1574.001
5AlwaysInstallElevatedInstall malicious MSI as SYSTEMT1548.002
6Token PrivilegesSeImpersonate, SeDebug, SeBackup, etc.T1134.001
7Scheduled TasksWritable binaries for SYSTEM tasksT1053.005
8Autorun ExecutablesWritable binaries in Run/RunOnce keysT1547.001
9Registry Service KeysWritable service ImagePath in HKLMT1574.011
10Stored CredentialsCredential Manager, AutoLogon passwordsT1552.001
11GPP Cached PasswordsGroup Policy Preferences cpasswordT1552.006
12Unattended Install FilesCredentials in unattend/sysprep XMLT1552.001
13PowerShell HistoryPSReadLine history and transcriptsT1552.001
14Sensitive FilesSAM backups, .kdbx, .rdg, git-credentialsT1552.001
15UAC Bypass OpportunitiesUAC misconfig or admin-not-elevatedT1548.002
16Writable Program DirectoriesWritable dirs in Program FilesT1574.010
17Cross-User ProfilesReadable profiles with sensitive filesT1552.001
18Credential Login PathsValidate extracted creds against local usersT1078.003
19Cross-User Privilege EscalationAnalyze what discovered users can accessT1078.003
20JIT Admin ToolsMakeMeAdmin, CyberArk EPM, Admin By RequestT1548
21Print Spooler / PrintNightmareVulnerable Point and Print configurationT1068
22WSUS HTTP (non-SSL)WSUS MITM for SYSTEM code executionT1557
23SCCM/MECM NAA CredentialsNetwork Access Account DPAPI extractionT1552.001
24COM Object HijackingHKCU CLSID hijack for SYSTEM-context DLL loadT1546.015
25Named Pipe PermissionsPermissive SYSTEM pipe ACLs → impersonationT1134.001
26Cached CredentialsDCC2, WiFi, WinSCP, FileZilla, PuTTY credsT1552.001
27WMI Event SubscriptionsWritable WMI consumer binaries/scriptsT1546.003
28WebClient RelayNTLM relay via WebClient to DC LDAP → SYSTEMT1187
29Service Recovery CommandsWritable failure recovery command binariesT1574.010
30Shadow Copy Sensitive FilesSAM/SYSTEM hives accessible in VSS snapshotsT1003.002

Multi-Hop Attack Paths

This is what separates PrivHound from traditional privesc tools. Instead of listing findings in isolation, PrivHound connects them into exploitable chains:

ChainPath
Credential pipelineUser → PSHistory → PHContainsCreds → PHCanLoginAs → LocalUser → Admin
Writable dir → serviceUser → WritableProgramDir → PHHostsBinaryFor → Service → SYSTEM
Cross-user profileUser → Profile → SensitiveFile → PHCanLoginAs → LocalUser → Admin
Cross-user escalationUser → (creds) → PHCanLoginAs → UserX → PHCanWriteBinary → Service → SYSTEM
SeBackup sub-chainUser → SeBackup → PHCanReadProtected → SAM → PHCanExtractHashes → Admin
Stored creds → runasUser → StoredCred → PHCanLoginViaRunas → LocalUser → Admin
SCCM NAA → credsUser → SCCMCred → PHContainsCreds → PHCanLoginAs → Admin
WebClient relayUser → WebClientRelay → PHEscalatesTo → SYSTEM
COM hijackUser → COMHijack → PHExecutesAs → SYSTEM
WMI subscriptionUser → WMISubscription → PHRunsAs → SYSTEM
Named pipeUser → NamedPipe → PHRunsAs → SYSTEM
Service recoveryUser → PHCanWriteRecoveryBin → Service → SYSTEM
Shadow copy hashesUser → ShadowCopy → SAM → PHCanExtractHashes → Admin
JIT adminUser → MakeMeAdmin → PHGrantsTempAdmin → Admin

Cross-User Privilege Escalation

When PrivHound discovers valid credentials for other local users (via GPP passwords, AutoLogon, unattend files, PowerShell history, cross-user profiles, etc.), it doesn't stop at creating a PHCanLoginAs edge. It analyzes what those discovered users can actually do.

How it works (no SeImpersonatePrivilege required):

  1. LogonUser obtains a token handle for each discovered user
  2. GetTokenInformation extracts group memberships (SIDs) and token privileges
  3. ACL checks run using the discovered user's groups — not the current user's
  4. Edges are created from the discovered user's node to any vulnerable resources they can access
  5. The token is closed — no impersonation occurs, no elevated privileges needed

What it checks for each discovered user:

Sub-checkEdge created
Service binary writePHCanWriteBinary
Service SDDL modifyPHCanModifyService
Unquoted path hijackPHCanHijackPath
DLL hijack PATH dirsPHCanWriteTo
Scheduled task binaryPHCanWriteTaskBinary
Autorun binaryPHCanWriteAutorun
Program directoryPHCanWriteProgDir
Token privilegesPHHasPrivilege
Service recovery binaryPHCanWriteRecoveryBin

All cross-user edges include a discovered_via="credential" property for filtering.


Quick Start

1. Run PrivHound on target

# Basic collection .\PrivHound.ps1 # Custom output path .\PrivHound.ps1 -OutputPath C:\Temp\privhound.json # Skip specific checks .\PrivHound.ps1 -SkipChecks "ScheduledTasks","Autoruns" # Skip credential validation (no logon attempts) .\PrivHound.ps1 -NoCredTest

2. Register custom node icons (once per BH instance)

Custom icons give your nodes distinct visuals instead of the default "?" icon.

# Generate the icon definition file .\PrivHound.ps1 -OutputFormat BloodHound-customnodes # → Outputs privhound_customnodes.json # Upload to BloodHound CE .\tests\Upload-CustomNodes.ps1 -Token "<JWT_TOKEN>" # Or with a remote BH instance .\tests\Upload-CustomNodes.ps1 -BHUrl "http://192.168.1.50:8080" -Token "<JWT_TOKEN>"
Manual upload via curl
curl -X POST http://localhost:8080/api/v2/custom-nodes \ -H "Authorization: Bearer <JWT_TOKEN>" \ -H "Content-Type: application/json" \ -H "Prefer: wait=30" \ -d @privhound_customnodes.json

If you get a 409 Conflict (types already exist), use Upload-CustomNodes.ps1 which handles deletion and re-creation automatically.

3. Upload OpenGraph data to BloodHound

  • Navigate to Administration → File Ingest
  • Drag and drop privhound_<HOSTNAME>_<timestamp>.json
  • Wait for ingest to complete

4. Query in BloodHound

Important: OpenGraph custom data is Cypher-only. The BH pathfinding UI (search bar → shortest path) does not work for custom nodes. Use the Cypher tab in Explore.

// All privesc paths to SYSTEM MATCH p=(u:PHUser)-[*1..5]->(t:PHPrivTarget) WHERE t.account = "NT AUTHORITY\\SYSTEM" RETURN p // Full PrivHound graph MATCH p=()-[r]->() WHERE type(r) STARTS WITH "PH" RETURN p // Cross-user credential chain to admin MATCH p=(u:PHUser)-[*1..6]->(t:PHPrivTarget) WHERE any(r IN relationships(p) WHERE type(r) = "PHCanAccessProfile") AND any(r IN relationships(p) WHERE type(r) = "PHCanLoginAs") RETURN p

See queries/privhound_queries.cypher for 50+ prebuilt queries covering every attack path category.


Sample Output

Multi-Endpoint Collection

# On each host .\PrivHound.ps1 -OutputPath ".\privhound_$env:COMPUTERNAME.json" # Collect all JSONs and upload together Compress-Archive -Path .\privhound_*.json -DestinationPath privhound_all.zip

Each endpoint gets its own set of nodes (IDs are hostname-scoped), so data from multiple hosts coexists cleanly in the same graph.

// Find all endpoints with SYSTEM-level privesc paths MATCH (u:PHUser)-[*1..5]->(t:PHPrivTarget) WHERE t.account = "NT AUTHORITY\\SYSTEM" RETURN u.hostname AS Endpoint, count(*) AS PathCount ORDER BY PathCount DESC

Combining with SharpHound Data

The real power is overlaying PrivHound on existing AD attack paths:

// AD user → local session → privesc → SYSTEM MATCH (adUser:User)-[:HasSession]->(comp:Computer) MATCH (phu:PHUser)-[*1..5]->(target:PHPrivTarget) WHERE target.account = "NT AUTHORITY\\SYSTEM" AND phu.hostname = comp.name RETURN adUser.name, comp.name, target.account

This reveals scenarios like: "The intern's AD account has a session on SERVER01 where a writable service binary gives them SYSTEM — from there, DCSync the domain."


Graph Model

Node Kinds

KindDescriptionIcon
PHUserThe user running PrivHounduser-secret (blue)
PHPrivTargetEscalation target (SYSTEM / Local Admin)crown (red)
PHEndpointThe computer being assesseddesktop (gray)
PHServiceWindows service with weak permsgear (yellow)
PHUnquotedPathUnquoted service path findingroute (orange)
PHWritablePathWritable directory in PATHfolder-open (red)
PHRegistryMisconfigRegistry misconfiguration (AIE)key (red)
PHTokenPrivilegeDangerous token privilegeshield-halved (purple)
PHScheduledTaskScheduled task with writable binaryclock (green)
PHAutoRunAutorun with writable executableplay (orange)
PHWritableRegKeyWritable service registry keypen-to-square (red)
PHStoredCredentialCached/stored credentialsunlock (red)
PHGPPPasswordGPP cached password filekey (red)
PHUnattendFileUnattended install file with credsfile-lines (orange)
PHPSHistoryPowerShell history/transcript fileterminal (blue)
PHSensitiveFileSensitive file on diskfile-shield (orange)
PHUACBypassUAC bypass opportunityshield (red)
PHWritableProgramDirWritable Program Files directoryfolder (red)
PHLocalUserA local user accountuser (yellow)
PHUserProfileAnother user's accessible profileaddress-card (blue)
PHJITAdminToolJIT admin tool (MakeMeAdmin, etc.)user-clock (orange)
PHPrintSpoolerPrint Spooler with vulnerable configprint (red)
PHWSUSConfigWSUS configured over HTTPdownload (red)
PHSCCMCredentialSCCM/MECM NAA credentialserver (red)
PHCOMHijackHijackable COM object CLSIDpuzzle-piece (purple)
PHNamedPipeNamed pipe with permissive ACLsfaucet (orange)
PHCachedCredsCached credential sourcedatabase (yellow)
PHWMISubscriptionWMI subscription with writable consumerbolt (purple)
PHWebClientRelayWebClient NTLM relay attack surfaceshare-nodes (red)
PHShadowCopyVolume Shadow Copy with sensitive fileshard-drive (gray)

Edge Kinds

EdgeMeaning
PHCanModifyServiceUser can change service config (binPath)
PHCanWriteBinaryUser can overwrite the service binary
PHCanHijackPathUser can exploit unquoted path
PHCanWriteToUser can write to a PATH directory
PHDLLHijackToWritable PATH enables DLL hijack to SYSTEM
PHCanExploitUser can exploit a misconfiguration
PHHasPrivilegeUser holds a dangerous token privilege
PHCanEscalateToPrivilege enables escalation to target
PHCanWriteTaskBinaryUser can replace scheduled task binary
PHCanWriteAutorunUser can replace autorun executable
PHCanModifyRegKeyUser can modify service registry key
PHHasStoredCredsUser has stored credentials
PHCanReadCredsUser can read stored credentials
PHCanDecryptGPPUser can decrypt GPP cpassword
PHCanReadHistoryUser can read PS history/transcripts
PHCanAccessFileUser can access a sensitive file
PHCanBypassUACUser can bypass UAC
PHCanWriteProgDirUser can write to a Program Files dir
PHCanLoginAsRecovered credentials are valid for a local user
PHCanLoginViaRunasStored cred enables runas /savecred
PHCanAccessProfileUser can read another user's profile
PHCanRequestJITUser can request JIT admin elevation
PHCanExploitSpoolerSpooler vulnerable to PrintNightmare
PHCanExploitWSUSWSUS over HTTP enables MITM
PHCanReadNAASCCM NAA credentials are extractable
PHCanHijackCOMCOM CLSID can be hijacked via HKCU
PHCanImpersonatePipeNamed pipe allows token impersonation
PHHasCachedCredsCached credentials are accessible
PHCanModifyWMIWMI consumer binary/script is writable
PHCanRelayWebClientWebClient enables NTLM relay to DC LDAP
PHCanWriteRecoveryBinUser can replace service recovery binary
PHCanAccessShadowCopyUser can access shadow copy sensitive files
PHRunsAsService/task runs as SYSTEM
PHEscalatesToMisconfiguration escalates to target
PHExecutesAsAutorun/COM executes in a privileged context
PHHostsBinaryForWritable dir hosts a service/task binary
PHRunsAsUserService runs as a named local user
PHMemberOfLocal user is a member of Administrators
PHHostsComputer hosts a privilege target
PHHasSessionOnUser has a session on the computer
PHProfileContainsProfile contains a sensitive file
PHContainsCredsFile contains embedded credentials
PHGrantsTempAdminJIT tool grants temporary admin
PHCanReadProtectedSeBackup allows reading protected hives
PHCanExtractHashesSAM hive enables hash extraction
PHCanWriteProtectedSeRestore allows writing protected files
PHCanInjectIntoSeDebug allows process injection
PHContainsSensitiveFileShadow copy contains extractable sensitive file

Requirements

  • Target: Windows PowerShell 5.1+ or PowerShell 7+
  • Privileges: Standard user (most checks). Some checks benefit from local admin.
  • BloodHound: CE v8.0.0+ with PostgreSQL backend, or BloodHound Enterprise

Project Structure

PrivHound/
├── PrivHound.ps1                      # Main collector script
├── privhound_customnodes.json         # Custom node icons for BloodHound UI
├── queries/
│   └── privhound_queries.cypher       # 50+ prebuilt Cypher queries
├── tests/
│   ├── Setup-VulnLab.ps1             # Create vulnerable lab environment
│   ├── Teardown-VulnLab.ps1          # Clean up lab artifacts
│   └── Upload-CustomNodes.ps1        # Upload custom node icons to BH CE
└── README.md

Extending PrivHound

Adding a new check:

  1. Create a function Check-YourNewCheck
  2. Add nodes with Add-PHNode (use PH prefix for kinds)
  3. Add edges with Add-PHEdge (use PH prefix for edge kinds)
  4. Add findings with Add-PHFinding
  5. Register the check in the $checks array in Invoke-PrivHound
  6. Add the new kind to Get-CustomNodeKinds
function Check-NewVector { Write-PHStatus "Checking new vector..." $nodeId = New-PHId "newtype" "unique-name" Add-PHNode -Id $nodeId -Kinds @("PHNewType") -Properties @{ name = "Finding@$Script:HOSTNAME" objectid = $nodeId hostname = $Script:HOSTNAME } Add-PHEdge -StartId $Script:CurrentUserId -EndId $nodeId -Kind "PHCanExploitNew" Add-PHEdge -StartId $nodeId -EndId $Script:SystemNodeId -Kind "PHEscalatesTo" Add-PHFinding "NewVector" "HIGH" "Description" "Abuse command" }

关于 About

A BloodHound OpenGraph collector that models Windows local privilege escalation as interconnected attack paths.

语言 Languages

PowerShell90.0%
Cypher10.0%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
6
Total Commits
峰值: 3次/周
Less
More

核心贡献者 Contributors