Check if another process has admin privileges

大兔子大兔子 提交于 2019-12-24 15:47:07

问题


I have wrote a code to check is a process running on the same machine has administrator privileges or not. But it always returns false.

Can you tell me what's wrong with it.

private static bool HasAdminPrivileges(int processId)
{
    var hProcess = WinApi.OpenProcess(ProcessAccessFlags.QueryInformation, false, processId);
    var opened = WinApi.OpenProcessToken(hProcess, WinApi.TOKEN_QUERY, out IntPtr hToken);
    if (opened)
    {
        var token = new IntPtr(hProcess.ToInt64() + hToken.ToInt64()); // 64 bit machine only

        WinApi.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, IntPtr.Zero, IntPtr.Zero, out uint cbSidUint);
        var cbSid = new IntPtr(cbSidUint);

        var succeed = WinApi.CheckTokenMembership(token, cbSid, out bool isMember);

        return succeed && isMember;
    }
    return false;
}

public class WinApi
{
    public const int TOKEN_QUERY = 0X00000008;

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr OpenProcess(ProcessAccessFlags processAccess, bool bInheritHandle, int processId);    

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool CreateWellKnownSid(WELL_KNOWN_SID_TYPE WellKnownSidType, IntPtr DomainSid, IntPtr pSid, out uint cbSid);    

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool CheckTokenMembership(IntPtr TokenHandle, IntPtr SidToCheck, out bool IsMember);
}

public enum ProcessAccessFlags : uint
{
    QueryInformation = 0x00000400
}

public enum WELL_KNOWN_SID_TYPE
{
    WinBuiltinAdministratorsSid = 26
}

回答1:


You cannot add handles together (new IntPtr(hProcess.ToInt64() + hToken.ToInt64()); ), that makes no sense.

You need the process handle to get the process token handle, then pass the token handle to CheckTokenMembership.

You also need to close these handles with CloseHandle.

using System;
using System.Runtime.InteropServices;
...
public class WinApi
{
    public const int TOKEN_DUPLICATE = 0x0002;
    public const int TOKEN_QUERY = 0x00000008;
    public const int SecurityImpersonation = 2;
    public const int TokenImpersonation = 2;

    [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
    [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool DuplicateTokenEx(IntPtr hTok, UInt32 DesiredAccess, IntPtr SecAttPtr, int ImpLvl, int TokType, out IntPtr TokenHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr OpenProcess(ProcessAccessFlags processAccess, bool bInheritHandle, int processId);

    [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CreateWellKnownSid(WELL_KNOWN_SID_TYPE WellKnownSidType, IntPtr DomainSid, IntPtr pSid, ref uint cbSid);

    [DllImport("advapi32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool CheckTokenMembership(IntPtr TokenHandle, IntPtr SidToCheck, out bool IsMember);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern int GetCurrentProcessId();
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern int CloseHandle(IntPtr h);
}

public enum ProcessAccessFlags : uint
{
    QueryInformation = 0x00000400,
    QueryLimitedInformation = 0x1000
}

public enum WELL_KNOWN_SID_TYPE
{
    WinBuiltinAdministratorsSid = 26
}

private static bool IsAdminGroupMember(int processId)
{
    IntPtr hPriToken = IntPtr.Zero, hImpToken = IntPtr.Zero;
    var hProcess = WinApi.OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, processId);
    if (hProcess == IntPtr.Zero) hProcess = WinApi.OpenProcess(ProcessAccessFlags.QueryInformation, false, processId); // < Vista
    var haveToken = WinApi.OpenProcessToken(hProcess, WinApi.TOKEN_DUPLICATE, out hPriToken);
    if (haveToken) 
    {
        haveToken = WinApi.DuplicateTokenEx(hPriToken, WinApi.TOKEN_QUERY, IntPtr.Zero, WinApi.SecurityImpersonation, WinApi.TokenImpersonation, out hImpToken);
        WinApi.CloseHandle(hPriToken);
    }
    if (hProcess != IntPtr.Zero) WinApi.CloseHandle(hProcess);
    if (haveToken)
    {
        uint cbSid = 0;
        bool isMember = false;
        WinApi.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, IntPtr.Zero, IntPtr.Zero, ref cbSid);
        IntPtr pSid = Marshal.AllocCoTaskMem(Convert.ToInt32(cbSid));
        var succeed = pSid != IntPtr.Zero && WinApi.CreateWellKnownSid(WELL_KNOWN_SID_TYPE.WinBuiltinAdministratorsSid, IntPtr.Zero, pSid, ref cbSid);
        succeed = succeed && WinApi.CheckTokenMembership(hImpToken, pSid, out isMember);
        Marshal.FreeCoTaskMem(pSid);
        WinApi.CloseHandle(hImpToken);
        return succeed && isMember;
    }
    return false;
}


[STAThread]static void Main(/*string[] args*/) 
{

    bool admin = IsAdminGroupMember(WinApi.GetCurrentProcessId());
    Console.WriteLine(string.Format("IsAdminGroupMember={0}", admin));
}



回答2:


I have created Process.Extensions.dll extension using solution offered by Anders

using System;
using ProcessExtensions;
using System.Diagnostics;
static void Main(string[] args)
{
    bool isAdminGroupMember = Process.GetCurrentProcess().IsAdminGroupMember();
    Console.WriteLine(string.Format("IsAdminGroupMember={0}", isAdminGroupMember));
}

https://github.com/IamhereTeam/Process.Extensions.git

Process.Extensions.dll



来源:https://stackoverflow.com/questions/53459123/check-if-another-process-has-admin-privileges

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!