turkinator
turkinator

Reputation: 925

Process.GetProcesses() WHERE process.IsElevated?

I'd like to monitor elevated processes running on a machine while a non-administrative user is logged in.

Basically, I want to run the following made-up code from C#:

var elevatedWindows = Process.GetProcesses().Where(p => p.IsElevated || p.ChildWindows.Any(cw => cw.IsElevated));

So far, the only thing I've found to give me the information I want appears to be a BUG in the .NET System.Diagnostics.Process class, as described here:

http://www.codeproject.com/Articles/302856/Bugs-in-System-Diagnostics-Process-Class

If I understand this correctly, the article says that if my program is not running with elevated permissions, it will generate a WIN32 exception with NativeErrorCode equal to 5 if you try to get an elevated process's StartTime or HasExited properties. I feel like this could be an easy workaround for my issue - try to get StartTime or HasExited from a non-elevated program and if it produces that error, it is an elevated process.

Problem is, I can't seem to get this to work reliably, HasExited errors unreliably when I've manually right-clicked notepad and selected "Run as Administrator", and used GetProcessesByName("notepad")

Even more troublesome is I can't isolate individual Explorer Windows. Explorer.exe is always running, and can be elevated, but even if it is running WITHOUT elevation you can still manually start the process as elevated a number of different ways, none of which effect the parent explorer.exe process.

So I guess I need to find WindowHandles from the spawned processes, or their child threads, and somehow see if the window is elevated?

Any help would be appreciated.

Upvotes: 0

Views: 1730

Answers (1)

ken2k
ken2k

Reputation: 49013

Not sure to understand what you mean by "elevated window". The process is elevated, not its windows. Starting a new Explorer view spawns a new process.

That said, you could use Interop to determine whether a process is elevated or not:

Code :

public enum ElevationType
{
    Default = 1,
    Full = 2,
    Limited = 3
}

// Do add some exception handling...etc.
public static ElevationType GetProcessElevationTypeByTokenHandle(IntPtr hTok)
{
    if (hTok.IsNotNull)
    {
        // Get token information struct length
        // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa379626(v=vs.85).aspx for constants
        int ret = 0;
        GetTokenInformation(hTok, TokenInformationClass.TokenElevationType, IntPtr.Zero, 0, ret);
        IntPtr tokenInformation = Marshal.AllocHGlobal(ret);

        // Get token information struct
        // With then TokenElevationType constant, it will returns a TOKEN_ELEVATION_TYPE value
        // See https://msdn.microsoft.com/en-us/library/windows/desktop/bb530718(v=vs.85).aspx
        GetTokenInformation(hTok, TokenInformationClass.TokenElevationType, tokenInformation, ret, null);

        // Get a valid structure
        var value = Marshal.ReadInt32(tokenInformation, 0);
        Marshal.FreeHGlobal(tokenInformation);
        return (ElevationType)value;
    }
    else
    {
        return ElevationType.Default;
    }
}

Upvotes: 1

Related Questions