Skip to content

Instantly share code, notes, and snippets.

@0xfeeddeadbeef
Last active November 30, 2023 04:02
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save 0xfeeddeadbeef/ce341bbca071099fd6952abab896aaac to your computer and use it in GitHub Desktop.
Save 0xfeeddeadbeef/ce341bbca071099fd6952abab896aaac to your computer and use it in GitHub Desktop.
Test whether or not a process is elevated (UAC run as admin)
function Test-ProcessElevated
{
[CmdletBinding()]
[OutputType([bool])]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[System.Diagnostics.Process] $Process
)
begin {
$CSharpCode = @'
namespace SecurityUtils
{
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using Microsoft.Win32.SafeHandles;
public static class Win32
{
public const string Advapi32Dll = "advapi32.dll";
public const string Kernel32Dll = "kernel32.dll";
public const int ERROR_SUCCESS = 0;
public const uint PROCESS_QUERY_INFORMATION = 0x0400;
public const uint PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
[DllImport(Advapi32Dll, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool OpenProcessToken(
SafeProcessHandle ProcessToken,
TokenAccessLevels DesiredAccess,
out SafeAccessTokenHandle TokenHandle);
[DllImport(Advapi32Dll, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern unsafe bool GetTokenInformation(
SafeAccessTokenHandle TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
void* TokenInformation,
uint TokenInformationLength,
out uint ReturnLength);
[DllImport(Kernel32Dll, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr hObject);
[DllImport(Kernel32Dll, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
[SuppressUnmanagedCodeSecurity]
internal static extern SafeProcessHandle OpenProcess(
uint dwDesiredAccess,
[MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
uint dwProcessId);
/// <summary>
/// Determines whether or not the specified application was launched by an administrator
/// in UAC elevated mode.
/// </summary>
/// <returns><c>true</c> if the process possesses an elevated token.</returns>
public static unsafe bool IsProcessElevated(int processId)
{
SafeAccessTokenHandle token;
using (SafeProcessHandle ph = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, (uint)processId))
{
if (ph == null || ph.IsInvalid)
{
throw new Win32Exception();
}
if (!OpenProcessToken(ph, TokenAccessLevels.Query, out token))
{
throw new Win32Exception();
}
using (token)
{
var elevation = new TOKEN_ELEVATION();
uint ignored = 0;
if (!GetTokenInformation(
token,
TOKEN_INFORMATION_CLASS.TokenElevation,
&elevation,
(uint)sizeof(TOKEN_ELEVATION),
out ignored))
{
throw new Win32Exception();
}
return elevation.TokenIsElevated != BOOL.FALSE;
}
}
}
public static unsafe bool IsProcessElevated(Process process)
{
return IsProcessElevated(process.Id);
}
/// <summary>
/// Blittable version of Windows BOOL type. It is convenient in situations where
/// manual marshalling is required, or to avoid overhead of regular bool marshalling.
/// </summary>
/// <remarks>
/// Some Windows APIs return arbitrary integer values although the return type is defined
/// as BOOL. It is best to never compare BOOL to TRUE. Always use bResult != BOOL.FALSE
/// or bResult == BOOL.FALSE .
/// </remarks>
internal enum BOOL : int
{
FALSE = 0,
TRUE = 1,
}
/// <seealso href="https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-token_elevation"/>
internal struct TOKEN_ELEVATION
{
public BOOL TokenIsElevated;
}
/// <seealso href="https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-token_information_class"/>
internal enum TOKEN_INFORMATION_CLASS : uint
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin,
TokenElevationType,
TokenLinkedToken,
TokenElevation,
TokenHasRestrictions,
TokenAccessInformation,
TokenVirtualizationAllowed,
TokenVirtualizationEnabled,
TokenIntegrityLevel,
TokenUIAccess,
TokenMandatoryPolicy,
TokenLogonSid,
TokenIsAppContainer,
TokenCapabilities,
TokenAppContainerSid,
TokenAppContainerNumber,
TokenUserClaimAttributes,
TokenDeviceClaimAttributes,
TokenRestrictedUserClaimAttributes,
TokenRestrictedDeviceClaimAttributes,
TokenDeviceGroups,
TokenRestrictedDeviceGroups,
TokenSecurityAttributes,
TokenIsRestricted,
MaxTokenInfoClass
}
}
}
'@
if (-not ([System.Management.Automation.PSTypeName]'SecurityUtils.Win32').Type)
{
# In Windows PowerShell, Add-Type -CompilerParameters is different:
if ($PSVersionTable.PSVersion.Major -lt 6) {
$compParams = New-Object -TypeName 'System.CodeDom.Compiler.CompilerParameters'
$compParams.CompilerOptions = '/unsafe+'
$compParams.ReferencedAssemblies.Add('System.dll') > $null
$compParams.ReferencedAssemblies.Add('System.Core.dll') > $null
Add-Type -TypeDefinition $CSharpCode -Language CSharp -CompilerParameters $compParams
} else {
Add-Type -TypeDefinition $CSharpCode -Language CSharp -CompilerOptions '-unsafe+'
}
}
# Debugger privilege is required:
[System.Diagnostics.Process]::EnterDebugMode()
}
process {
return [SecurityUtils.Win32]::IsProcessElevated($Process)
}
end {
[System.Diagnostics.Process]::LeaveDebugMode()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment