拒绝尝试打开进程的访问权限

时间:2014-05-22 09:37:14

标签: c++ windows memory process

说明:我遇到了一个问题,我正在尝试打开一个进程并读取该进程的内存。它在我的VS 2013 IDE中调试时工作正常但是,如果我构建它并以管理员身份运行独立可执行文件(或更低的凭据),则无法正常打开进程,我收到错误代码5,这是拒绝访问

让我感到困惑的是它在IDE中运行良好但不支持独立可执行文件。我不明白为什么VS 2013拥有比以管理员身份运行程序更高的凭据。

代码的链接在这里:

https://floobits.com/Simple2012/Simple_Bot
The important section is memoryReading.cpp line 30-35

问题摘要如下: 1。在Visual Studio 2013中一切正常。 2。尝试打开“该”进程时,独立可执行文件被拒绝访问。 3. 可执行文件以管理员的完全权限运行,IDE也是如此。

我想更加详细地理解这一点,所以我有两个关键问题,如果有人心情愉快,我希望得到一个非常详细的解释。
问题1:如何使用独立的可执行文件打开进程?
问题2:为什么会出现这种问题?

如果您遗失任何信息,请不要犹豫,我会尽快加入。我还尝试对某些部分进行高亮处理,使其阅读更加舒适,并快速简单地了解问题。

1 个答案:

答案 0 :(得分:0)

  

我试图打开一个进程并读取该进程的内存。它在调试时工作正常

这是因为您的用户帐户有SE_DEBUG_NAME (SeDebugPrivilege)。开发人员使用SE_DEBUG_NAME进行开发很常见,但不建议使用。

您应该开发为常规用户帐户,以确保您不会遇到这些意外的依赖关系。


  

让我感到困惑的是它在IDE中运行良好,但没有使用独立的可执行文件......

现在问题已经解决......


  

问题1:如何使用独立可执行文件打开进程?
  问题2:为什么会出现这种问题?

有几种方法可以解决它。

首先,你可以"编译"通过在清单选项中设置/MANIFESTUAC:level=requireAdministrator来获得权限。 "编译"中的权限有点误导,因为UAC仍然会提示您。请参阅MSDN上的/MANIFESTUAC

其次,您可以在程序的属性中设置"以管理员身份运行" 。右键单击可执行文件,然后选择兼容性选项卡。请参阅Technet上的Configure Applications to Always Run as an Administrator。 UAC会提示您。

第三,您可以右键单击您的可执行文件,然后选择"以管理员身份运行" 。您需要在每次调用程序时执行此操作。 UAC会提示您。


"以管理员身份运行" 是不够的。您现在需要启用一两个权限。这是因为Windows 启动了启用所有权限的进程(与Linux / Unix和susudo不同)。在Privilege Constants中列出的特权中,有三个或四个有趣的特权:

  • SE_ASSIGNPRIMARYTOKEN_NAME
  • SE_DEBUG_NAME
  • SE_TCB_NAME
  • SE_INCREASE_QUOTA_NAME

这是我用来启用权限的代码,例如"SeDebugPrivilege"

BOOL CUserPrivilege::EnablePrivilege( LPCTSTR pszPrivilege, BOOL bEnabled ){

    // Returned to caller
    BOOL bResult = FALSE;

    // Thread or Process token
    HANDLE hToken = NULL;

    __try {

        bResult = OpenThreadToken( GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, TRUE, &hToken );
        if( !bResult )
        {
            bResult = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken );
            assert( TRUE == bResult );
            if( FALSE == bResult ) { __leave; }
        }

        bResult = EnablePrivilege( hToken, pszPrivilege, bEnabled );
        DWORD dwError = GetLastError();
        assert( TRUE == bResult || ( ERROR_SUCCESS == GetLastError() || ERROR_NOT_ALL_ASSIGNED == dwError ) );

        // We're only enabling one privilege. If we get back
        // ERROR_NOT_ALL_ASSIGNED, then we failed.
        if( ERROR_NOT_ALL_ASSIGNED == dwError ) { bResult = FALSE; }
    }

    __finally {
        if( NULL != hToken ) {
            CloseHandle( hToken ); hToken = NULL;
        }
    }

    return bResult;
}

BOOL CUserPrivilege::EnablePrivilege( HANDLE hToken, LPCTSTR pszPrivilege, BOOL bEnabled )
{
    BOOL bResult = FALSE;

    __try {

        LUID luid;
        TOKEN_PRIVILEGES priv;

        bResult = LookupPrivilegeValue( NULL, pszPrivilege, &luid );
        assert( TRUE == bResult );
        if( FALSE == bResult ) { __leave; }

        priv.PrivilegeCount = 1;
        priv.Privileges[0].Luid = luid;
        priv.Privileges[0].Attributes =
            (bEnabled ? SE_PRIVILEGE_ENABLED : FALSE );

        bResult = AdjustTokenPrivileges( hToken, FALSE, &priv, sizeof(priv), NULL, NULL );

        // We're only enabling one privilege. If we get back
        // ERROR_NOT_ALL_ASSIGNED, we failed.
        if( ERROR_NOT_ALL_ASSIGNED == GetLastError() ) { bResult = FALSE; }

        if( FALSE == bResult ) { __leave; }

        bResult = TRUE;
    }
    __finally { ; }

    return bResult;
}

您可以使用与以下类似的代码检查您拥有的权限:

CUserPrivilege::Status CUserPrivilege::HasPrivilege( LPCTSTR pszPrivilege )
{
    // Returned to caller
    Status status = Error;

    // Thread or Process token
    HANDLE hToken = NULL;

    // Scratch
    BOOL bResult = FALSE;

    __try {

        bResult = OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken );
        if( !bResult )
        {
            bResult = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken );
            assert( TRUE == bResult );
            if( FALSE == bResult ) { __leave; }
        }

        status = HasPrivilege( hToken, pszPrivilege );
    }

    __finally {
        if( NULL != hToken ) {
            CloseHandle( hToken ); hToken = NULL;
        }
    }

    return status;
}

CUserPrivilege::Status CUserPrivilege::HasPrivilege( HANDLE hToken, LPCTSTR pszPrivilege )
{
    // Returned to caller
    Status status = Error;

    // Scratch
    BOOL bResult = FALSE;

    PBYTE pBuffer = NULL;
    TOKEN_PRIVILEGES* pTokenInfo = NULL;

    __try
    {
        LUID uid = { 0, 0 };
        bResult = LookupPrivilegeValue( NULL, pszPrivilege, &uid );
        assert( TRUE == bResult );
        if( FALSE == bResult ) { __leave; }

        DWORD dwRequired = 0;
        bResult = GetTokenInformation( hToken, TokenPrivileges, NULL, 0, &dwRequired );
        assert( FALSE == bResult );
        if( TRUE == bResult || 0 == dwRequired ) { __leave; }

        pBuffer = new BYTE[dwRequired];
        assert( NULL != pBuffer );
        if( NULL == pBuffer ) { __leave; }

        DWORD dwSize = dwRequired;
        bResult = GetTokenInformation( hToken, TokenPrivileges, pBuffer, dwSize, &dwRequired );
        assert( TRUE == bResult );
        if( FALSE == bResult || dwSize != dwRequired ) { __leave; }

        pTokenInfo = (TOKEN_PRIVILEGES*)pBuffer;
        DWORD count = pTokenInfo->PrivilegeCount;

        // Status changed...
        status = Missing;

        for( DWORD i = 0; i<count; i++ )
        {
            if( pTokenInfo->Privileges[i].Luid.HighPart == uid.HighPart && 
                pTokenInfo->Privileges[i].Luid.LowPart == uid.LowPart )
            {
                DWORD attrib = pTokenInfo->Privileges[i].Attributes;
                if( (attrib & SE_PRIVILEGE_ENABLED) ||
                    (attrib & SE_PRIVILEGE_ENABLED_BY_DEFAULT) )
                {
                    status = Enabled;
                }
                else if( (attrib & SE_PRIVILEGE_REMOVED) )
                {
                    status = Disabled;
                }

                break;
            }
        }
    }
    __finally
    {
        if( NULL != pBuffer ) {
            delete[] pBuffer; pBuffer = NULL;
        }
    }

    return status;
}

这里是代码中提到的Status枚举:

enum Status { Missing = -1, Error = 0, Disabled = 1, Enabled = 2 };