BloodHound is the way to go to for finding attack paths in an Active Directory (AD) environment. However, it is not always clear how the data is gathered without looking at the code of SharpHound, the data ingestor for BloodHound.

Microsoft hardened their systems over time through updates, which makes enumeration of Active Directory (AD) objects and relationships harder than it used to be a couple of years ago.

In this series of articles, we deep dive into the enumeration methods of SharpHound and their limitations.

Table of Contents

In this article, we’ll cover user rights enumeration through SAMR and GPOLocalGroup. Further articles in this series:

  • Session Enumeration Through NetWkstaUserEnum & NetSessionEnum (to be published May 12th)
  • Session Enumeration Through Remote Registry & Summary (to be published May 25th)

User Rights Enumeration

Information that proves to be useful during penetration tests is “Which domain user has what permissions on what system?”.

SharpHound will try to enumerate this information from local group membership and BloodHound displays it with the following edges:

  • AdminTo (members of the local Administrators group)
  • CanRDP (members of Remote Desktop Users group)
  • CanPSRemote (members of Distributed COM Users group)
  • ExecuteDCOM (members of Remote Management Users group)

Two methods to acquire this data are covered in this blog post:

  • SAMR
  • GPOLocalGroup


When using the LocalAdmin, RDP, DCOM or PSRemote collection methods, SharpHound enumerates memberships of local groups (their users and permissions) on the target systems by querying the Windows SAM database remotely.

How does it work?

This works by connecting to a named pipe \PIPE\samr, which is exposed via the IPC$ (inter-process communication) SMB share. Then, it uses the Security Account Manager (SAM) Remote Protocol (RPC over SMB on port 445).

Wireshark trace

A Wireshark trace of a successful SharpHound SAMR call allows us to highlight the steps involved:

  1. Establish an SMB connection to the remote host (Kerberos authentication)
  2. Connect to the IPC$ share
  3. Open the samr named pipe (this is similar to opening a file with that name)
  4. Bind to the samr interface with its UUID 12345778-1234-abcd-ef00-0123456789ac using RPC over SMB
  5. Interact using the Security Account Manager (SAM) Remote Protocol
    • The SIDs of users and groups inside of the local group are queried using the function GetMembersInAlias
  6. Close and logoff

Authorization is performed at three different places in this trace:

  1. When we attempt to open the IPC$ share
  2. When we attempt to open the samr named pipe
  3. When we attempt to execute an RPC call via the pipe

This last part fails with a low-privileged user on newer Windows, as we’ll see below.

You can try it for yourself using the following Wireshark filter:

((smb2) || (samr)|| (dcerpc) || (smb)) && !(smb2.ioctl.function == 0x001401fc)

Result filtering

Windows comes with default accounts that we are not interested in. SharpHound filters out the following from the final result:

  • Local user accounts
  • Local service accounts (S-1-5-80)
  • IIS AppPool identities (S-1-5-82)
  • Window Manager accounts (DWM) (S-1-5-90)
  • Font Driver Host accounts (S-1-5-96)

What privileges are required?

There was a time where all authenticated users could access the SAM information for any computer in the domain. This allowed to get all domain and local users assigned to a local group on the machine. Starting with Windows 10 1607+ and Windows Server 2016+, the default configuration has changed and SAMR is now restricted to the members of the local built-in Administrators group.

The presence of older OS in an environment doesn’t necessarily mean that it is possible to enumerate local group membership, since Microsoft provided an optional update down to Windows 7 and Server 2008 R2 to allow control over this behavior. The following GPO can be configured to harden these older versions:

Computer Configuration|Windows Settings|Security Settings|Local Policies|Security Options|Network access: Restrict clients allowed to make remote calls to SAM

This same GPO also allows to reopen access to SAMR for non-admin users!

Before this change, you might have stumbled upon a PowerShell script by Itai Grady named “SAMRi10”, which had a similar purpose.


Some systems are not affected by this restriction: Domain Controllers (DC) and Read-Only Domain Controllers (RODC). All authenticated users still have access to SAMR on such systems to preserve compatibility.

Unfortunately (for us pentesters) this is not really helpful because the local SAM database of a DC isn’t normally used. Why? The SAM database is present (you can verify it with mimikatz lsadump::sam), but it is only used when booting into Directory Services Repair Mode (DSRM) or the Recovery Console.

SAMR otherwise returns domain users from the ntds.dit database instead of local users. This is what happens when issuing the net user /domain command.

Further reading

Technical information about the Security Account Manager (SAM) Remote Protocol:

SharpHound implements SAMR in the CommonLib at: and the code relies on native Windows functions to which the P/Invoke signatures are declared in:

The SAMR RPC calls themselves for all four types of edges are made from this code via GetLocalGroupMembers


Faced with the limitations of SAMR, we will look at the second way SharpHound gathers user rights, the GPOLocalGroup collection method.

How does it work?

Group Policy Objects (GPOs) can be used to manage local groups on computers. This can be done in two different ways and both are collected by SharpHound:

  • Local Users and Groups Group Policy Preferences (GPP) found at Computer Configuration\Preferences\Control Panel Settings\(Despite the fact that this can also be managed in User Configuration, SharpHound will only look at the Computer Configuration part)
  • Restricted Groups found at Computer Configuration\Policies\Windows Settings\Security Settings\

Implementation details

The data collection goes as follows:

  • List all OUs that have a GPO linked (gpLink attribute in LDAP)
  • Skip gpLink that contains no computer object, or are disabled
  • Process the gPCFileSysPath attribute of each linked GPO object (this attribute specifies where on SYSVOL the files containing the rules are stored)
  • Search for Groups.xml (for Local Users and Groups) and GptTmpl.inf (for Restricted Groups) in all gPCFileSysPath
  • Filter for SID we’re interested in:
    • Administrators (S-1-5-32-544…..)
    • Remote Desktop Users (S-1-5-32-555…..)
    • Remote Management Users (S-1-5-32-580…..)
    • Distributed COM Users (S-1-5-32-562…..)
  • Resolve what domain users belong to these groups and which computers these GPOs are applied to.

There is more going on that we won’t explain in detail here. In short: there might be conflicts since both methods could be used simultaneously with different or overlapping membership entries. Users can be deleted, added, updated. Additionally, Restricted Groups have precedence over GPP settings and override them. SharpHound will make sure that everything is taken care of and will return the resultant configuration.


First and foremost, this collection method will not retrieve group memberships added locally (hence the advantage of the SAMR collection method). The completeness of the gathered data will highly vary from domain to domain as some environments heavily rely on GPO to manage local group memberships and other won’t use them at all.

Wireshark trace

A Wireshark trace of a successful SharpHound call allows us to highlight the steps involved:

  1. Get all objects in the domain through LDAP (not all requests are shown above)
  2. Establish a SMB connection to the DC (Kerberos authentication)
  3. Connect to the SYSVOL share and look for the XML files
  4. Close and logoff

Authorization is performed at two different places in this trace:

  1. When querying data through LDAP
  2. When attempting to open the SYSVOL share and the XML files

You can try it for yourself using the following Wireshark filter:

((smb2) || (ldap)|| (dcerpc) || (smb)) && !(smb2.ioctl.function == 0x001401fc)

What privileges are required?

By default, GPOs are readable by all Authenticated Users, which makes this collection method a good candidate for pentesters and attackers. However the Security Filtering of a GPO can be edited to restrict read access:

If the GPO is only readable by computer objects where they apply, access to the policies on SYSVOL will be denied and SharpHound will be blind.

Further reading

SharpHound implements “GPOLocalGroup” in the CommonLib at: