Here's how to find all processes on local and remote computers that are running under administrative credentials using PowerShell.

When it comes to security, one of the scariest situations is when you've got a rampant piece of malware doing it's bidding across the network. Multiply that situation by 10 when you find out that malware is running with local administrative privileges across all of your computers. But how do you know? This malware has sneaked past your perimeter defense and your workstation antivirus. It's clear that the security tools you've implemented aren't going to stop it.

It's time to roll up your sleeves and get this done yourself with some PowerShell!

First, define what you need to do. Malware is on lots of computers and you know it's causing a lot of grief because the process it's running under has somehow managed to run under a user account that has administrative control over the computer. We first need get a list of potential computers. In Active Directory, we can use the Get-AdComputer command to enumerate all of the computer accounts.

$adComputers = Get-AdComputer -Filter * | Select-Object -ExpandProperty Name

Next, we need to figure out how to query processes for a single computer to see which computers are running this process. One way to do that is by using PowerShell remoting and the Get-Process command. This would typically work, but Get-Process doesn't return the process owner. We're going to need this later on. Instead, we'll query WMI to get the process list.

PS> Get-CimInstance -ComputerName WEBSRV1 -ClassName Win32_Process -Filter "Name = 'malware.exe'"
ProcessId Name HandleCount WorkingSetSize VirtualSize PSComputerName
--------- ---- ----------- -------------- ----------- --------------
1864 malware.exe 158 6524928 41701376 WEBSRV1 

Once we've got code to find the processes, we now need to figure from the processes that are returned, under what user that process is running under. To that, I can invoke the GetOwner CIM method on each of the process objects returned.

PS> (Invoke-CimMethod -InputObject $p -MethodName GetOwner).User NETWORK SERVICE 

We now have some code to see if the process is running on a computer and the owner of that process. Next, we need some code to gather up all of the local users on that computer that are a member of the Administrators group.

PS> $group = [ADSI]"WinNT://WEBSRV1/Administrators"
PS> @($group.Invoke('Members')) | foreach {
    $_.GetType().Invokemember('Name','GetProperty',$null,$_,$null)
}

Administrator jschmoe Domain Admins 

We're now ready to put it all together! We'll create a script that queries all of the computers in Active Directory that have our malware.exe process running. For each process found, we'll find the owner of that process and then compare that user account with any member of the local administrators' group.

$adComputers = Get-AdComputer -Filter * | Select-Object -ExpandProperty Name
foreach ($computer in $adComputers) {
    if ($malwareProcs = Get-CimInstance -ComputerName $_ -ClassName Win32_Process -Filter "Name = 'malware.exe'") {
        $adminGroup = [ADSI]"WinNT://$_/Administrators"
        $adminMembers = @($adminGroup.Invoke('Members')) | foreach { $_.GetType().Invokemember('Name','GetProperty',$null,$_,$null) }
        $malwareProcs | foreach {
        if ((Invoke-CimMethod -InputObject $_ -MethodName GetOwner).User -in $adminMembers) {
            Write-Host "The computer [$($computer)] has malware running under admin privileges!!" -ForegroundColor Red
        }
    }
}

Join the Jar Tippers on Patreon

It takes a lot of time to write detailed blog posts like this one. In a single-income family, this blog is one way I depend on to keep the lights on. I'd be eternally grateful if you could become a Patreon patron today!

Become a Patron!