【解決方法】プロセスは管理者として実行されていますか


ねえ友達

アプリケーションが管理者として実行されているかどうかを何らかの方法で判断することは可能ですか?

デスクトップで Win32 API またはその他の API を使用して?

何かのようなもの

EnumProcess (enumFunc); そして、各プロセスについて、私がそうするかどうかを確認してください

withFunc()
{
if (私は管理者として実行しています)
{
TRACE(“見つかりました\n”);
}

}
よろしく

解決策 1

あなたが望むものは、次のようになります。

HRESULT CheckIfIsUserAdmin(BOOL *pIsAdmin)
{
    int b;
    HANDLE hProcess = NULL;
    HANDLE hProcessToken = NULL;
    HANDLE hLinkedToken = NULL;
    BOOL fIsAdmin = FALSE;
    DWORD dwLength = 0;
    OSVERSIONINFO osver = {sizeof(OSVERSIONINFO)};
    HRESULT hr = S_OK;
 
    *pIsAdmin = FALSE;
 
    hProcess = GetCurrentProcess();
    if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken))
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }
 
    char AdminSID[SECURITY_MAX_SID_SIZE];
    dwLength = sizeof(AdminSID);
    if(!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &AdminSID, &dwLength)) 
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    } 

    if (!CheckTokenMembership( NULL, &AdminSID, &fIsAdmin)) 
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }
 
    if (fIsAdmin) 
    {
        *pIsAdmin = TRUE;
        goto Exit;
    }
 
    if (!GetVersionEx(&osver))
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }
 
    if (osver.dwMajorVersion < 6) 
    {
        goto Exit;        
    }
 
    // Code to handle admin SID filtering in Vista and above
    if (!GetTokenInformation(hProcessToken, TokenLinkedToken,
                                (VOID*) &hLinkedToken, sizeof(HANDLE), &dwLength) )
    {
        b = GetLastError();
        if( b == ERROR_NO_SUCH_LOGON_SESSION ||  b == ERROR_PRIVILEGE_NOT_HELD)
        {
            goto Exit;
        }
 
        hr = HRESULT_FROM_WIN32(b);
        goto Exit;
    } 

    if (!CheckTokenMembership(hLinkedToken, &AdminSID, &fIsAdmin))
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto Exit;
    }
 
    if (fIsAdmin)
    {
        *pIsAdmin = TRUE;
    }
 
Exit:
    if (hProcess) 
    {
        CloseHandle(hProcess);
    }
 
    if (hProcessToken)
    {
        CloseHandle(hProcessToken);
    }
 
    if (hLinkedToken)
    {
        CloseHandle(hLinkedToken);
    }
 
    return hr;
}

現在のトークンに管理者 SID が含まれていない場合、それは必ずしも現在のユーザーが管理者ではないことを意味するわけではありません。これは、Vista 以降のデフォルトでは、管理者グループのメンバーのトークンで管理者 SID をフィルタリングするためです。

そのため、GetTokenInformation を呼び出してリンクされたトークンを取得し、気に入ったトークンに対してもう一度 CheckTokenMembership を呼び出して、フィルター処理されていない管理者 SID を確認する必要があります。

よろしく
アスペン・ハーリン

解決策 2

解決策 3

KB #Q118626 に基づく、「私も」の回答を次に示します。

//-------------------------------------------------------------------------
// This function checks the token of the calling thread to see if the caller
// belongs to the Administrators group.
//
// Return Value:
//   TRUE if the caller is an administrator on the local machine.
//   Otherwise, FALSE.
// --------------------------------------------------------------------------
// Based on code from KB #Q118626, at http://support.microsoft.com/kb/118626
BOOL IsCurrentUserLocalAdministrator()
{
    BOOL   fReturn         = FALSE;
    DWORD  dwStatus        = 0;
    DWORD  dwAccessMask    = 0;
    DWORD  dwAccessDesired = 0;
    DWORD  dwACLSize       = 0;
    DWORD  dwStructureSize = sizeof(PRIVILEGE_SET);
    PACL   pACL            = NULL;
    PSID   psidAdmin       = NULL;

    HANDLE hToken              = NULL;
    HANDLE hImpersonationToken = NULL;

    PRIVILEGE_SET   ps = {0};
    GENERIC_MAPPING GenericMapping = {0};

    PSECURITY_DESCRIPTOR     psdAdmin           = NULL;
    SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;

    // Determine if the current thread is running as a user that is a member 
    // of the local admins group.  To do this, create a security descriptor 
    // that has a DACL which has an ACE that allows only local administrators 
    // access.  Then, call AccessCheck with the current thread's token and
    // the security descriptor.  It will say whether the user could access an
    // object if it had that security descriptor.  Note: you do not need to
    // actually create the object.  Just checking access against the
    // security descriptor alone will be sufficient.

    const DWORD ACCESS_READ  = 1;
    const DWORD ACCESS_WRITE = 2;

    __try
    {
        // AccessCheck() requires an impersonation token.  We first get a 
        // primary token and then create a duplicate impersonation token.
        // The impersonation token is not actually assigned to the thread, but
        // is used in the call to AccessCheck.  Thus, this function itself never
        // impersonates, but does use the identity of the thread.  If the thread
        // was impersonating already, this function uses that impersonation 
        // context.
        if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY, TRUE, &hToken))
        {
            if (GetLastError() != ERROR_NO_TOKEN)
                __leave;

            if (!OpenProcessToken(GetCurrentProcess(), 
                TOKEN_DUPLICATE|TOKEN_QUERY, &hToken))
                __leave;
        }

        if (!DuplicateToken (hToken, SecurityImpersonation, &hImpersonationToken))
            __leave;

        // Create the binary representation of the well-known SID that
        // represents the local administrators group.  Then create the 
        // security descriptor and DACL with an ACE that allows only local
        // admins access.  After that, perform the access check.  This will
        // determine whether the current user is a local admin.
        if (!AllocateAndInitializeSid(&SystemSidAuthority, 2,
            SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
            0, 0, 0, 0, 0, 0, &psidAdmin))
            __leave;

        psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
        if (psdAdmin == NULL)
            __leave;

        if (!InitializeSecurityDescriptor(psdAdmin, SECURITY_DESCRIPTOR_REVISION))
            __leave;

        // Compute size needed for the ACL.
        dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) +
            GetLengthSid(psidAdmin) - sizeof(DWORD);

        pACL = (PACL)LocalAlloc(LPTR, dwACLSize);
        if (pACL == NULL)
            __leave;

        if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
            __leave;

        dwAccessMask= ACCESS_READ | ACCESS_WRITE;

        if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin))
            __leave;

        if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE))
            __leave;

        // AccessCheck validates a security descriptor somewhat; set the group
        // and owner so that enough of the security descriptor is filled out to
        // make AccessCheck happy.

        SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE);
        SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE);

        if (!IsValidSecurityDescriptor(psdAdmin))
            __leave;

        dwAccessDesired = ACCESS_READ;

        // Initialize GenericMapping structure even though you
        // do not use generic rights.
        GenericMapping.GenericRead    = ACCESS_READ;
        GenericMapping.GenericWrite   = ACCESS_WRITE;
        GenericMapping.GenericExecute = 0;
        GenericMapping.GenericAll     = ACCESS_READ | ACCESS_WRITE;

        if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired,
            &GenericMapping, &ps, &dwStructureSize, &dwStatus,
            &fReturn))
        {
            fReturn = FALSE;
            __leave;
        }
    }
    __finally
    {
        // Clean up.
        if (pACL)
            LocalFree(pACL);
        if (psdAdmin)
            LocalFree(psdAdmin);
        if (psidAdmin)
            FreeSid(psidAdmin);
        if (hImpersonationToken)
            CloseHandle (hImpersonationToken);
        if (hToken)
            CloseHandle (hToken);
    }

    return fReturn;
}

コメント

タイトルとURLをコピーしました