# Query PowerShell alternative hosts with WMI

This snippet is a WMI query that lists all processes that have `System.Management.Automation.dll` loaded and it's meant to expand on [Alternate PowerShell Hosts](../alternate-powershell-hosts) and [Find signed alternate PowerShell hosts](find-signed-alternate-powershell-hosts).

```powershell
﻿# trying to find WMI classes that might be vaguely related to processes or DLLs
# note that 'root/cimv2' is implicit.
Get-CimClass -ClassName *Module*
Get-CimClass -ClassName *Process*

# CIM_ProcessExecutable is our candidate WMI class
Get-CimClass -ClassName CIM_ProcessExecutable | Select-Object -ExpandProperty CimClassProperties
# MSDN docs: https://msdn.microsoft.com/en-us/library/aa387977%28v=vs.85%29.aspx

# see what instances look like
Get-CimInstance -ClassName CIM_ProcessExecutable

# since the Antecedent property contains the DLL filename
# we group by filename and then look at the associated processes
Get-CimInstance -ClassName CIM_ProcessExecutable | Group-Object -Property {$_.Antecedent.Name} | Sort-Object -Property Name

# now let's filter the results to just return instances with System.Management.Automation(.ni).dll
Get-CimInstance -ClassName CIM_ProcessExecutable | Where-Object { $_.Antecedent.Name -match 'System\.Management\.Automation' }

# return proper Win32_Process instances for the running PowerShell host processes
# the Dependent property only stores the Win32_Process.Handle property (presumably for perf/latency reasons)
Get-CimInstance -ClassName CIM_ProcessExecutable | Where-Object { $_.Antecedent.Name -match 'System\.Management\.Automation' } | ForEach-Object {
    # note we're sticking to pure WMI to support consistent remote scenarios
    Get-CimInstance -ClassName Win32_Process -Filter "ProcessId = $($_.Dependent.Handle)"
}

Get-CimInstance -ClassName CIM_ProcessExecutable | Group-Object -Property { $_.BaseAddress.ToString('X16') } |
    Sort-Object -Property Count -Descending

# sorting by loaded base address
# modules that don't opt in to ASLR
Get-CimInstance -ClassName CIM_ProcessExecutable | Group-Object -Property { $_.BaseAddress.ToString('X16') } |
    Sort-Object -Property Name

Get-CimInstance -ClassName CIM_ProcessExecutable | Where-Object { $_.BaseAddress -eq $_.ModuleInstance } | Measure-Object
Get-CimInstance -ClassName CIM_ProcessExecutable | Where-Object { $_.BaseAddress -ne $_.ModuleInstance } | Measure-Object

Get-CimInstance -ClassName CIM_ProcessExecutable | Where-Object { $_.BaseAddress -eq $_.ModuleInstance } | ForEach-Object {
    $_.Antecedent.Name
} | Sort-Object -Unique
```
