T1069

Permission Groups Discovery

Discovery Last updated:

Adversaries may attempt to discover group and permission settings to understand which user accounts and groups are available, group memberships, and which users and groups have elevated permissions. This information informs targeting decisions and enables privilege escalation, lateral movement, and persistence planning. Common enumeration methods include native Windows commands (net group, net localgroup), PowerShell cmdlets (Get-ADGroup, Get-LocalGroup), LDAP queries, BloodHound/SharpHound collection, Linux identity commands (id, groups, getent group), and cloud-provider APIs. Threat actors including APT41, TA505, Volt Typhoon, and Scattered Spider have used these techniques in real-world intrusions.

What is T1069 Permission Groups Discovery?

Permission Groups Discovery (T1069) maps to the Discovery tactic — the adversary is trying to figure out your environment in MITRE ATT&CK.

This page provides production-ready detection logic for Permission Groups Discovery, covering the data sources and telemetry it touches: Process: Process Creation, Command: Command Execution, Microsoft Defender for Endpoint. The queries below are rated medium severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Discovery
Technique
T1069 Permission Groups Discovery
Canonical reference
https://attack.mitre.org/techniques/T1069/
Microsoft Sentinel / Defender
kusto
let GroupDiscoveryCommands = dynamic([
  "net group", "net localgroup", "net user /domain",
  "Get-ADGroup", "Get-ADGroupMember", "Get-LocalGroup", "Get-LocalGroupMember",
  "dsquery group", "dsget group",
  "gpresult", "whoami /groups", "whoami /all",
  "id ", "id;", "groups ", "getent group",
  "SharpHound", "BloodHound"
]);
let SuspiciousParents = dynamic([
  "cmd.exe", "powershell.exe", "pwsh.exe", "wscript.exe", "cscript.exe",
  "mshta.exe", "rundll32.exe", "regsvr32.exe", "svchost.exe"
]);
DeviceProcessEvents
| where Timestamp > ago(24h)
| where (
    // net.exe based group enumeration
    (FileName =~ "net.exe" or FileName =~ "net1.exe")
    and ProcessCommandLine has_any ("group", "localgroup")
  ) or (
    // PowerShell AD/local group cmdlets
    (FileName =~ "powershell.exe" or FileName =~ "pwsh.exe")
    and ProcessCommandLine has_any ("Get-ADGroup", "Get-ADGroupMember", "Get-LocalGroup", "Get-LocalGroupMember", "Get-ADPrincipalGroupMembership")
  ) or (
    // dsquery/dsget LDAP group enumeration
    (FileName =~ "dsquery.exe" or FileName =~ "dsget.exe")
    and ProcessCommandLine has "group"
  ) or (
    // whoami with group flags — common post-exploitation recon
    FileName =~ "whoami.exe"
    and ProcessCommandLine has_any ("/groups", "/all", "/priv")
  ) or (
    // gpresult — Group Policy result showing group memberships
    FileName =~ "gpresult.exe"
  ) or (
    // BloodHound / SharpHound collector binaries
    ProcessCommandLine has_any ("SharpHound", "BloodHound", "-CollectionMethod", "--CollectionMethods")
  )
| extend IsDomainGroupQuery = ProcessCommandLine has_any ("/domain", "net group", "dsquery group", "Get-ADGroup")
| extend IsLocalGroupQuery = ProcessCommandLine has_any ("localgroup", "Get-LocalGroup", "whoami /groups")
| extend IsBloodHound = ProcessCommandLine has_any ("SharpHound", "BloodHound", "-CollectionMethod")
| extend SuspiciousParent = InitiatingProcessFileName has_any (SuspiciousParents)
| project Timestamp, DeviceName, AccountName, AccountDomain,
         FileName, ProcessCommandLine,
         InitiatingProcessFileName, InitiatingProcessCommandLine,
         IsDomainGroupQuery, IsLocalGroupQuery, IsBloodHound, SuspiciousParent
| sort by Timestamp desc

Detects permission group discovery activity using Microsoft Defender for Endpoint DeviceProcessEvents. Covers net.exe/net1.exe group enumeration (both local and domain), PowerShell AD cmdlets (Get-ADGroup, Get-ADGroupMember, Get-LocalGroup), dsquery/dsget LDAP queries, whoami /groups and /all flags, gpresult execution, and BloodHound/SharpHound collector usage. Flags whether each event targets domain groups, local groups, or appears to be automated BloodHound collection. Parent process context is captured to identify execution from unexpected interpreters.

medium severity medium confidence

Data Sources

Process: Process Creation Command: Command Execution Microsoft Defender for Endpoint

Required Tables

DeviceProcessEvents

False Positives

  • IT administrators and helpdesk staff routinely running net localgroup or net group to troubleshoot access issues
  • Active Directory management scripts and scheduled tasks using Get-ADGroup or Get-ADGroupMember for account provisioning
  • Security tools and monitoring agents (e.g., CrowdStrike, Tenable) that enumerate group memberships as part of posture assessment
  • Software installation processes that check for membership in local Administrators or specific service groups
  • Legitimate BloodHound usage by authorized red team or vulnerability management teams with change management records
  • GPO deployment verification scripts using gpresult to confirm policy application to the correct groups

Sigma rule & cross-platform mapping

The detection logic for Permission Groups Discovery (T1069) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  category: process_creation
  product: windows

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 5 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Local Group Enumeration via net.exe

    Expected signal: Sysmon Event ID 1: Two Process Create events for net.exe (or net1.exe, which net.exe spawns internally). CommandLine values: 'net localgroup' and 'net localgroup Administrators'. Security Event ID 4688 if command line auditing is enabled. Parent process will be cmd.exe or the shell used to execute the commands.

  2. Test 2Domain Group Enumeration via net.exe

    Expected signal: Sysmon Event ID 1: Process Create for net.exe with CommandLine 'net group /domain' and 'net group "Domain Admins" /domain'. Network connection to domain controller on port 389 (LDAP) or 445 (SMB SAMR protocol). On the domain controller: Security Event ID 4661/4662 may fire for SAM group object access.

  3. Test 3PowerShell Active Directory Group Enumeration

    Expected signal: Sysmon Event ID 1: Process Create for powershell.exe with CommandLine containing 'Get-ADGroup' and 'Get-ADGroupMember'. PowerShell ScriptBlock Log Event ID 4104 capturing the full script content. LDAP network traffic to domain controller on port 389/636.

  4. Test 4whoami Group Membership Query

    Expected signal: Sysmon Event ID 1: Two Process Create events for whoami.exe. CommandLine values: 'whoami /groups' and 'whoami /all'. No network traffic (local token query). Output includes SID values, group names, and enabled privileges — this data is often captured via screen scraping in interactive sessions.

  5. Test 5Linux Group Discovery via id and getent

    Expected signal: Linux auditd: syscall execve events for /usr/bin/id, /usr/bin/groups, /usr/bin/getent with respective arguments. Syslog entries if exec auditing is enabled. On systems with osquery or EDR agents: process creation events for each command with full argument lists.


Response Playbook

Triage

  1. Identify the user account that triggered the alert — is it a standard user, privileged admin, service account, or machine account? Standard users running domain group enumeration is highly suspicious.
  2. Review the parent process — was net.exe or dsquery.exe launched by cmd.exe from a user session, or from an unexpected parent like powershell.exe, wscript.exe, mshta.exe, or a service (svchost.exe)? LOLBin parents indicate post-exploitation.
  3. Check whether this is isolated or part of a sequence — look ±5 minutes for other discovery commands (whoami, ipconfig, systeminfo, net user, net share, nltest /domain_trusts). A cluster of discovery commands within a short window is a strong indicator of active intrusion.
  4. For BloodHound/SharpHound detections: check the process hash against VirusTotal and internal allowlists. Confirm with the security team whether an authorized assessment is scheduled. BloodHound binaries from temp directories or user profiles are highly suspicious.
  5. For domain group queries (net group /domain, Get-ADGroup, dsquery group): check if the account normally authenticates to domain controllers. Look for abnormal logon times or source IPs in adjacent authentication logs.
  6. Check for lateral movement indicators in the same timeframe — new logon events (4624 Type 3 or Type 10) on other hosts from the same source user or machine within the hour before/after the group discovery.

Containment

  1. If BloodHound/SharpHound is confirmed malicious: immediately isolate the endpoint via EDR network isolation, disable the executing account in Active Directory, and rotate credentials for any accounts whose group memberships were harvested.
  2. If discovery commands were executed by a compromised service account: disable the service account, audit all hosts where that account has been used recently (Security Event ID 4624 filtering on that account name), and reset the password.
  3. If the discovery is part of an active intrusion sequence: escalate to IR and consider broader network segmentation. Group enumeration typically precedes targeted lateral movement to privileged hosts.
  4. Block the source host from communicating with domain controllers via firewall rule until investigation is complete, if isolation of the endpoint is not feasible.
  5. If cloud group enumeration is involved (AWS IAM, Azure AD, GCP IAM): revoke the API credentials or OAuth tokens used for enumeration and audit CloudTrail/Azure Activity logs for subsequent access attempts.

Evidence Collection

  1. Windows Security Event ID 4688 (Process Creation with command line logging enabled) — captures the full command line of net.exe, dsquery.exe, whoami.exe invocations.
  2. Sysmon Event ID 1 (Process Create) — provides parent/child process tree, hashes, and full command line regardless of Security audit policy.
  3. Active Directory event logs on domain controllers: Event ID 4661 (object handle requested) and Event ID 4662 (operation performed on object) for LDAP queries against group objects.
  4. Network traffic captures: BloodHound/SharpHound generates high-volume LDAP/LDAPS traffic to domain controllers on ports 389/636. Capture pcap during the incident window.
  5. PowerShell ScriptBlock Logging (Event ID 4104) — if AD cmdlets were used via PowerShell, this captures full script content including piped commands and output handling.
  6. Prefetch files for net.exe, whoami.exe, dsquery.exe — C:\Windows\Prefetch\*.pf provides execution timestamps and DLL load evidence.
  7. BloodHound output files — search for .json files matching BloodHound schema (computers.json, users.json, groups.json, acls.json, domains.json) in temp directories, user profiles, and removable media.

Escalation Criteria

  • ! BloodHound or SharpHound binary executed — this indicates systematic, automated AD enumeration consistent with pre-ransomware or APT tradecraft.
  • ! Group discovery commands executed under a service account or SYSTEM context with no associated change ticket or maintenance window.
  • ! Discovery activity followed within 15 minutes by net use, PsExec, WMI, or RDP connections to other hosts — indicates active lateral movement using group data.
  • ! Multiple hosts showing the same group discovery commands within a short window (possible worm propagation or scripted campaign).
  • ! Domain admin groups or tier-0 asset groups specifically enumerated (e.g., 'Domain Admins', 'Enterprise Admins', 'Schema Admins', 'Protected Users') — adversary is targeting the highest-privilege accounts.
  • ! Discovery commands originating from a host that has no legitimate administrative role (user workstation querying domain group membership via LDAP directly rather than via net.exe).

Investigation Guide

Forensic Artifacts

  • > Registry: HKLM\SYSTEM\CurrentControlSet\Services\NetLogon\Parameters — domain membership details queried during group enumeration.
  • > File System: BloodHound output files (*.json matching AD schema) in %TEMP%, %USERPROFILE%, or mapped drives — contain harvested group membership graphs.
  • > File System: C:\Windows\Prefetch\NET.EXE-*.pf, WHOAMI.EXE-*.pf, DSQUERY.EXE-*.pf — execution timestamps and run counts.
  • > File System: PowerShell history at %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt — may contain Get-ADGroup or Get-LocalGroup commands run interactively.
  • > Event Log: Microsoft-Windows-PowerShell/Operational Event ID 4104 — full script block content for PowerShell AD cmdlet usage.
  • > Event Log: Security Event ID 4661/4662 on domain controllers — LDAP/SAM access to group objects, records SAM group enumeration by remote hosts.
  • > Network: LDAP queries on port 389/636 to domain controllers from non-admin hosts — BloodHound generates hundreds of LDAP queries in short bursts (visible in DC network captures or firewall logs).
  • > Memory: If SharpHound is injected rather than run as a standalone binary, process memory of the injected host may contain BloodHound collection data structures.

Tuning Guidance

Start by building a baseline of legitimate group discovery in your environment. Key allowlist candidates: (1) IT helpdesk accounts running net localgroup Administrators on support calls — allowlist specific account+host combinations, not the command pattern itself; (2) AD provisioning scripts running as service accounts — allowlist the specific service account name + initiating process (e.g., task scheduler or specific automation tool); (3) Security scanning tools — allowlist by parent process hash rather than command line. Avoid suppressing any BloodHound/SharpHound indicators regardless of context — always require a ticket. For domain group discovery specifically, consider raising severity when the initiating account is a non-admin user, when the parent process is an Office application or browser (indicating phishing-delivered access), or when the host has no legitimate AD administration role. In high-AD-activity environments, layer the detection by requiring the discovery commands to be followed within 10 minutes by a network logon (Event ID 4624 Type 3) to another host from the same account — this correlation dramatically improves precision.


Hunting Queries

Hunt for accounts or hosts executing three or more net group/localgroup commands within the past 7 days. High command counts from a single account or device indicate scripted enumeration rather than one-off administrative lookups — consistent with APT41 and TA505 tooling patterns.

Hunting — KQL
kql
DeviceProcessEvents
| where Timestamp > ago(7d)
| where (FileName =~ "net.exe" or FileName =~ "net1.exe")
    and ProcessCommandLine has_any ("group", "localgroup")
| summarize
    CommandCount = count(),
    UniqueCommands = dcount(ProcessCommandLine),
    Commands = make_set(ProcessCommandLine, 20),
    FirstSeen = min(Timestamp),
    LastSeen = max(Timestamp)
  by AccountName, DeviceName, InitiatingProcessFileName
| where CommandCount >= 3
| sort by CommandCount desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
    (Image="*\\net.exe" OR Image="*\\net1.exe")
    (CommandLine="*group*" OR CommandLine="*localgroup*")
| stats
    count as CommandCount,
    dc(CommandLine) as UniqueCommands,
    values(CommandLine) as Commands,
    earliest(_time) as FirstSeen,
    latest(_time) as LastSeen
  by User, host, ParentImage
| where CommandCount >= 3
| sort - CommandCount

Hunt for burst PowerShell AD group enumeration — more than 5 cmdlet executions per hour by a single account, or the same account enumerating groups across more than 2 hosts. This pattern distinguishes automated BloodHound-style collection from legitimate one-time admin queries and is consistent with pre-ransomware reconnaissance tradecraft.

Hunting — KQL
kql
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName =~ "powershell.exe" or FileName =~ "pwsh.exe"
| where ProcessCommandLine has_any (
    "Get-ADGroup", "Get-ADGroupMember", "Get-LocalGroup",
    "Get-LocalGroupMember", "Get-ADPrincipalGroupMembership",
    "net group", "net localgroup"
  )
| summarize
    Count = count(),
    Devices = dcount(DeviceName),
    Commands = make_set(ProcessCommandLine, 10)
  by AccountName, bin(Timestamp, 1h)
| where Count > 5 or Devices > 2
| sort by Count desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
    (Image="*\\powershell.exe" OR Image="*\\pwsh.exe")
    (CommandLine="*Get-ADGroup*" OR CommandLine="*Get-ADGroupMember*" OR CommandLine="*Get-LocalGroup*" OR CommandLine="*Get-LocalGroupMember*")
| bin _time span=1h
| stats
    count as Count,
    dc(host) as Devices,
    values(CommandLine) as Commands
  by User, _time
| where Count > 5 OR Devices > 2
| sort - Count

Hunt for discovery trifectas — accounts executing 5+ distinct discovery commands using 3+ different tools within a 30-minute window. This holistic view catches the broader reconnaissance phase where group discovery is part of a systematic environment survey, regardless of which individual commands appear in the main alert. Consistent with APT41 and Volt Typhoon living-off-the-land discovery phases.

Hunting — KQL
kql
let DiscoveryCommands = DeviceProcessEvents
| where Timestamp > ago(24h)
| where ProcessCommandLine has_any (
    "net group", "net localgroup", "net user",
    "whoami", "ipconfig", "systeminfo", "hostname",
    "tasklist", "netstat", "arp ", "route print",
    "dsquery", "nltest", "Get-ADGroup", "Get-ADUser"
  )
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, FileName;
DiscoveryCommands
| summarize
    TotalCommands = count(),
    UniqueTools = dcount(FileName),
    CommandList = make_set(ProcessCommandLine, 20),
    FirstSeen = min(Timestamp),
    LastSeen = max(Timestamp),
    SpanMinutes = datetime_diff('minute', max(Timestamp), min(Timestamp))
  by AccountName, DeviceName
| where TotalCommands >= 5 and UniqueTools >= 3 and SpanMinutes <= 30
| sort by TotalCommands desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
    (
        (Image="*\\net.exe" AND (CommandLine="*group*" OR CommandLine="*user*" OR CommandLine="*share*"))
        OR (Image="*\\whoami.exe")
        OR (Image="*\\ipconfig.exe")
        OR (Image="*\\systeminfo.exe")
        OR (Image="*\\hostname.exe")
        OR (Image="*\\tasklist.exe")
        OR (Image="*\\netstat.exe")
        OR (Image="*\\dsquery.exe")
        OR (Image="*\\nltest.exe")
    )
| bin _time span=30m
| stats
    count as TotalCommands,
    dc(Image) as UniqueTools,
    values(CommandLine) as CommandList
  by User, host, _time
| where TotalCommands >= 5 AND UniqueTools >= 3
| sort - TotalCommands

Atomic Red Team Tests

Test 1 Local Group Enumeration via net.exe
windows

Enumerates local groups on the current system using the built-in net.exe utility, then queries membership of the local Administrators group. This is one of the most common first-stage discovery commands observed in post-exploitation frameworks and manual attacker activity. The double-invocation (list all groups, then query a specific high-value group) mirrors real adversary behavior.

Command

powershell
net localgroup
net localgroup Administrators

Expected Telemetry

Sysmon Event ID 1: Two Process Create events for net.exe (or net1.exe, which net.exe spawns internally). CommandLine values: 'net localgroup' and 'net localgroup Administrators'. Security Event ID 4688 if command line auditing is enabled. Parent process will be cmd.exe or the shell used to execute the commands.

Expected Detection

KQL: FileName matches net.exe/net1.exe AND ProcessCommandLine has 'localgroup'. IsLocalGroupQuery=true. SPL: match on net.exe with 'localgroup' in CommandLine. Both queries will generate two separate events.

Test 2 Domain Group Enumeration via net.exe
windows

Enumerates domain groups and specifically queries the membership of the Domain Admins group using net.exe with the /domain flag. This technique is used by APT41, TA505, and Volt Typhoon operators to identify privileged accounts for targeting. Requires domain-joined machine and network connectivity to a domain controller.

Command

powershell
net group /domain
net group "Domain Admins" /domain

Expected Telemetry

Sysmon Event ID 1: Process Create for net.exe with CommandLine 'net group /domain' and 'net group "Domain Admins" /domain'. Network connection to domain controller on port 389 (LDAP) or 445 (SMB SAMR protocol). On the domain controller: Security Event ID 4661/4662 may fire for SAM group object access.

Expected Detection

KQL: IsDomainGroupQuery=true, ProcessCommandLine has '/domain'. SPL: CommandLine matches 'group' and '/domain'. Both are elevated-priority events due to domain targeting.

Test 3 PowerShell Active Directory Group Enumeration
windows

Uses the ActiveDirectory PowerShell module to enumerate all AD groups and retrieve membership of the Domain Admins group. This is a more capable and scriptable alternative to net.exe used by sophisticated actors and BloodHound-equivalent tools. Requires the RSAT ActiveDirectory module (available on domain-joined Windows 10/11 and Server).

Command

powershell
powershell.exe -NoProfile -Command "Import-Module ActiveDirectory; Get-ADGroup -Filter * | Select-Object Name, GroupScope, GroupCategory | Format-Table; Get-ADGroupMember -Identity 'Domain Admins' | Select-Object Name, SamAccountName, objectClass"

Expected Telemetry

Sysmon Event ID 1: Process Create for powershell.exe with CommandLine containing 'Get-ADGroup' and 'Get-ADGroupMember'. PowerShell ScriptBlock Log Event ID 4104 capturing the full script content. LDAP network traffic to domain controller on port 389/636.

Expected Detection

KQL: FileName matches powershell.exe AND ProcessCommandLine has 'Get-ADGroup' AND 'Get-ADGroupMember'. IsDomainGroupQuery=true. SPL: match on powershell.exe with Get-ADGroup and Get-ADGroupMember in CommandLine.

Test 4 whoami Group Membership Query
windows

Uses the built-in whoami.exe utility with the /groups and /all flags to display all group memberships and privileges for the current user token. This is commonly executed as an immediate post-exploitation step to understand what access level has been obtained. The /all flag additionally reveals privileges (SeDebugPrivilege, SeImpersonatePrivilege, etc.) that inform further exploitation steps.

Command

powershell
whoami /groups
whoami /all

Expected Telemetry

Sysmon Event ID 1: Two Process Create events for whoami.exe. CommandLine values: 'whoami /groups' and 'whoami /all'. No network traffic (local token query). Output includes SID values, group names, and enabled privileges — this data is often captured via screen scraping in interactive sessions.

Expected Detection

KQL: FileName matches whoami.exe AND ProcessCommandLine has_any('/groups', '/all'). IsLocalGroupQuery=true. SPL: Image matches whoami.exe and CommandLine matches /groups or /all.

Test 5 Linux Group Discovery via id and getent
linux

Enumerates group memberships on a Linux system using the id, groups, and getent commands. The id command shows current user's primary and supplementary groups; getent group dumps the entire /etc/group database including service accounts and system groups. Used by threat actors including Volt Typhoon during Linux-based infrastructure compromises.

Command

bash
id
groups
getent group
getent group sudo
cat /etc/group | grep -v '^#'

Expected Telemetry

Linux auditd: syscall execve events for /usr/bin/id, /usr/bin/groups, /usr/bin/getent with respective arguments. Syslog entries if exec auditing is enabled. On systems with osquery or EDR agents: process creation events for each command with full argument lists.

Expected Detection

Linux-focused detections using auditd or syslog sourcetypes. KQL (if Linux hosts forward to Sentinel via MMA/AMA): Syslog table entries matching 'getent group' or 'id ' commands. SPL: sourcetype=linux_secure or syslog filtering on these command names with group-related arguments.

Related Detections

Tactic Hub