OSCP notesExtended library
Browse tracks

AD Manual Enumeration

Users / Groups / Computers

# get a list of all users in the domain
cmd> net user /domain
PS > Get-NetUser | select cn # Using PowerView.ps1

# get details about a specific user 
cmd> net user [username] /domain # more than 10 group memberships, cmd will fail
PS > Get-ADUser -Identity <username> -Server asd.domain.com -Properties * # Powershell

# get list of all groups in the domain
cmd> net group /domain
PS > Get-ADUser -Filter 'Name -like "*lorenzo"' -Server asd.domain.com | Format-Table Name,SamAccountName -A
PS > Get-NetGroup -GroupName * # Using PowerView.ps1

# enumerate AD groups
PS > Get-ADGroup -Identity Administrators -Server asd.domain.com

# get details such as membership to a group
cmd> net group [groupname] /domain
PS > Get-ADGroupMember -Identity Administrators -Server domain.com # Powershell

# get the password policy of the domain
cmd> net accounts /domain

# get all AD objects that were changed after a specific date
PS > $ChangeDate = New-Object DateTime(2022, 02, 28, 12, 00, 00)
PS > Get-ADObject -Filter 'whenChanged -gt $ChangeDate' -includeDeletedObjects -Server asd.domain.com

# enumerate accounts that have a badPwdCount that is greater than 0
# useful to avoid these accounts in our bruteforce attacks
PS > Get-ADObject -Filter 'badPwdCount -gt 0' -Server domain.com

# get additional information about the specific domain
PS> Get-ADDomain -Server asd.domain.com

# get all computers in domain
cmd> net view
cmd> net view /domain

# get resources/shares of specified computer
cmd> net view \\[computer_name] /domain

# get a list of all operating systems on the domain 
PS > Get-NetComputer -fulldata | select operatingsystem # Using PowerView.ps1

Domain Controller hostname (PdcRoleOwner)**

PS> [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()

This PowerShell script will collect all users along with their attributes:

$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher.SearchRoot = $objDomain
$Searcher.filter="samAccountType=805306368"
$Result = $Searcher.FindAll()
Foreach($obj in $Result)
{
    Foreach($prop in $obj.Properties)
    {
        $prop
    }
    Write-Host "------------------------"
}

In the filter property, we can set any attribute of the object type we desire. For example, we can use the name property to create a filter for the Jeff_Admin user as shown below:

$Searcher.filter="name=Jeff_Admin"

Nested Groups

For a candidate exposed by collection, query the exact group/object instead of repeating the entire directory inventory. See object-rights validation when membership or an ACL is the missing prerequisite.

Locate all groups in the domain and print their names:

$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher.SearchRoot = $objDomain
$Searcher.filter="(objectClass=Group)"
$Result = $Searcher.FindAll()
Foreach($obj in $Result)
{
    $obj.Properties.name
}

List the members of a group by setting an appropriate filter on the name property. In addition, we will only display the member attribute to obtain the group members.

$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher.SearchRoot = $objDomain
$Searcher.filter="(name=GROUPNAME)"
$Result = $Searcher.FindAll()
Foreach($obj in $Result)
{
    $obj.Properties.member
}

Logged-in users and active user sessions

PS> Set-ExecutionPolicy Unrestricted
PS> Import-Module .\PowerView.ps1
PS> Get-NetLoggedon -ComputerName [computer_name]    # enum logged-in users
PS> Get-NetSession -ComputerName [domain_controller] # enum active user sessions

Service Principal Names (AD Service Accounts)

For example, let's update our PowerShell enumeration script to filter the serviceprincipalname property for the string *http*, indicating the presence of a registered web server:

$domainObj = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$PDC = ($domainObj.PdcRoleOwner).Name
$SearchString = "LDAP://"
$SearchString += $PDC + "/"
$DistinguishedName = "DC=$($domainObj.Name.Replace('.', ',DC='))"
$SearchString += $DistinguishedName
$Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString)
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher.SearchRoot = $objDomain
$Searcher.filter="serviceprincipalname=*http*"
$Result = $Searcher.FindAll()
Foreach($obj in $Result)
{
    Foreach($prop in $obj.Properties)
    {
        $prop
    }
}
# Kerberoast: https://github.com/nidem/kerberoast/blob/master/GetUserSPNs.ps1
PS> .\GetUserSPNs.ps1

# Powershell Empire: https://github.com/compwiz32/PowerShell/blob/master/Get-SPN.ps1
PS> .\Get-SPN.ps1

Validate control over a specific AD object

Use the reviewed PowerView module under the current domain identity. TARGET_OBJECT is the user, group or computer identified by enumeration:

Import-Module .\PowerView.ps1
Get-DomainObjectAcl -Identity TARGET_OBJECT -ResolveGUIDs | Select-Object SecurityIdentifier,ActiveDirectoryRights,ObjectAceType,AceType,IsInherited
whoami /user
whoami /groups

Compare the ACE trustee with your identity and effective groups. GenericAll, GenericWrite, WriteDacl, WriteOwner and a specific extended right enable different actions; inspect object type, property/GUID, deny ACEs and inheritance. Seeing a right in someone else's ACE does not grant it to you.

PowerView ACL query. Keep writes and cleanup in the selected procedure; do not modify every interesting object.

Prepare tools used on this page

Use the shared Kali workspace preparation first. Optional tools are not additional mandatory passes. Skip a clone when its reviewed checkout already exists.

Prepare RSAT Active Directory PowerShell

Runs on an owned Windows 10/11 Pro or Enterprise management host, not Kali. Install from elevated PowerShell only when you administer that host; a low-privilege domain shell does not imply this feature is available. This feature is required for the Get-AD* examples, not for PowerView or the native LDAP helper. Upstream.

Get-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools*
Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0

Check on the Windows management host:

Get-Module -ListAvailable ActiveDirectory
Import-Module ActiveDirectory
Get-Command Get-ADUser

On Windows Server, use elevated PowerShell instead:

Install-WindowsFeature RSAT-AD-PowerShell
Import-Module ActiveDirectory
Get-Command Get-ADUser

If you cannot install RSAT, use the existing LDAP/PowerView methods rather than assuming Get-ADUser is a built-in cmdlet.

Prepare Kerberoast scripts and tgsrepcrack

Retained legacy PowerShell SPN-enumeration alternative. The actual script referenced here is GetUserSPNs.ps1; this does not install obsolete cracking scripts. Prefer the existing Impacket/Rubeus owner for ticket requests; these mechanisms have distinct prerequisites. Upstream.

mkdir -p "$HOME/oscp/tools/artifacts/windows/legacy-ad"
curl -fL https://raw.githubusercontent.com/nidem/kerberoast/master/GetUserSPNs.ps1 -o "$HOME/oscp/tools/artifacts/windows/legacy-ad/GetUserSPNs.ps1"

Check on Kali:

test -s "$HOME/oscp/tools/artifacts/windows/legacy-ad/GetUserSPNs.ps1"
Prepare Get-SPN.ps1

Retained standalone PowerShell SPN lookup; inspect the script and available directory context before use. Obtaining a script is separate from having authenticated directory access. Upstream.

mkdir -p "$HOME/oscp/tools/artifacts/windows/legacy-ad"
curl -fL https://raw.githubusercontent.com/compwiz32/PowerShell/master/Get-SPN.ps1 -o "$HOME/oscp/tools/artifacts/windows/legacy-ad/Get-SPN.ps1"

Check on Kali:

test -s "$HOME/oscp/tools/artifacts/windows/legacy-ad/Get-SPN.ps1"