2

我在使用来自本地系统管理员的 Windows API CreateProcessAsUser 的应用程序中遇到问题,以便以其他用户身份运行应用程序。到目前为止一切正常,但 Windows 窗口和框架样式并未以某种方式应用。该窗口总是看起来像带有大框架的 Windows 2000 窗口。我还附上了一些截图

破碎的风格窗口

我还编写了一些示例代码,说明我们如何在不处理句柄和其他东西的情况下使用 C++ 实现所有魔法。

只需确保您在本地设置了密码“test”的用户“test”,并尝试以本地系统管理员身份运行发布的源代码。如果您尝试执行代码,其他用户将导致错误代码 1413。

该问题主要出现在 VirtualBox 中的 Windows 7 VM、某些 Windows 7 系统和所有 Windows 8.1 系统上。很奇怪。谁能帮我解决这个问题?谢谢!

#include <iostream>
#include <Windows.h>
#include <UserEnv.h>
#include <WinWlx.h>

int AddAceToWindowStation( HWINSTA  hwinsta, PSID psid )
{
    DWORD lengthNeeded;

    SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
    if( !GetUserObjectSecurity( hwinsta, &secInfo, NULL, NULL, &lengthNeeded ) )
    {
        if ( GetLastError() != 122 )
        {
            std::cout << "GetUserObjectSecurity1 error: " << GetLastError() << std::endl;
            return 0;
        }
    }

    PSECURITY_DESCRIPTOR pSecDescriptor = ( PSECURITY_DESCRIPTOR ) HeapAlloc(
        GetProcessHeap(),
        HEAP_ZERO_MEMORY,
        lengthNeeded );

    if ( pSecDescriptor == NULL )
    {
        std::cout << "Allocating memory for pSecDescriptor failed: " << GetLastError() << std::endl;
        return 0;
    }

    PSECURITY_DESCRIPTOR pSecDescriptorNew = ( PSECURITY_DESCRIPTOR ) HeapAlloc(
        GetProcessHeap(),
        HEAP_ZERO_MEMORY,
        lengthNeeded );

    if ( pSecDescriptorNew == NULL )
    {
        std::cout << "Allocating memory for pSecDescriptorNew failed: " << GetLastError() << std::endl;
        return 0;
    }

    if ( !GetUserObjectSecurity( hwinsta, &secInfo, pSecDescriptor, lengthNeeded, &lengthNeeded ) )
    {
        std::cout << "GetUserObjectSecurity2 error: " << GetLastError() << std::endl;
        return 0;
    }

    if ( !InitializeSecurityDescriptor( pSecDescriptorNew, SECURITY_DESCRIPTOR_REVISION ) )
    {
        std::cout << "InitializeSecurityDescriptor error: " << GetLastError() << std::endl;
        return 0;
    }

    BOOL DaclPresent;
    PACL pOldDacl;
    BOOL DaclDefaulted;
    if ( !GetSecurityDescriptorDacl( pSecDescriptor, &DaclPresent, &pOldDacl, &DaclDefaulted ) )
    {
        std::cout << "GetSecurityDescriptorDacl error: " << GetLastError() << std::endl;
        return 0;
    }

    // Get size information for DACL
    ACL_SIZE_INFORMATION AclInfo;
    AclInfo.AceCount = 0; // Assume NULL DACL.
    AclInfo.AclBytesFree = 0;
    AclInfo.AclBytesInUse = sizeof( ACL );

    if ( pOldDacl == NULL )
        DaclPresent = FALSE;

    // If not NULL DACL, gather size information from DACL.
    if ( DaclPresent )
    {
        if ( !GetAclInformation( pOldDacl, &AclInfo,
            sizeof( ACL_SIZE_INFORMATION ), AclSizeInformation ) )
        {
            std::cout << "GetAclInformation error: " << GetLastError() << std::endl;
            return 0;
        }
    }

    DWORD cbNewACL = AclInfo.AclBytesInUse + sizeof( ACCESS_ALLOWED_ACE ) + sizeof( ACL ) + sizeof( ACL ) + sizeof( ACCESS_ALLOWED_ACE ) + sizeof( ACL ) + sizeof( ACL );

    PACL pNewACL = ( PACL ) HeapAlloc(
        GetProcessHeap(),
        HEAP_ZERO_MEMORY,
        cbNewACL );

    if ( !InitializeAcl( pNewACL, cbNewACL, ACL_REVISION ) )
    {
        std::cout << "InitializeAcl error: " << GetLastError() << std::endl;
        return 0;
    }

    LPVOID         pTempAce = NULL;

    // Copy old Ace to new DACL
    if ( DaclPresent && AclInfo.AceCount )
    {
        std::cout << "AclInfo.AceCount:" << AclInfo.AceCount << std::endl;
        for ( int i = 0; i < AclInfo.AceCount; ++i )
        {
            if ( !GetAce( pOldDacl, i, &pTempAce ) )
            {
                std::cout << "GetAce[" << i << "] error: " << GetLastError() << std::endl;
                return 0;
            }

            if ( !AddAce( pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
                ( ( PACE_HEADER ) pTempAce )->AceSize ) )
            {
                std::cout << "AddAce[" << i << "] error: " << GetLastError() << std::endl;
                return 0;
            }
        }
    }

    if ( !AddAccessAllowedAceEx( pNewACL, ACL_REVISION, CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL, psid ) )
    {
        std::cout << "AddAccessAllowedAceEx1 error: " << GetLastError() << std::endl;
        return 0;
    }

    if ( !AddAccessAllowedAceEx( pNewACL, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | WINSTA_READSCREEN | STANDARD_RIGHTS_REQUIRED, psid ) )
    {
        std::cout << "AddAccessAllowedAceEx2 error: " << GetLastError() << std::endl;
        return 0;
    }

    if ( !SetSecurityDescriptorDacl( pSecDescriptorNew, TRUE, pNewACL, FALSE ) )
    {
        std::cout << "SetSecurityDescriptorDacl error: " << GetLastError() << std::endl;
        return 0;
    }

    if ( !SetUserObjectSecurity( hwinsta, &secInfo, pSecDescriptorNew ) )
    {
        std::cout << "SetUserObjectSecurity error: " << GetLastError() << std::endl;
        return 0;
    }

    return 1;
}

int AddAceToDesktop( HDESK  hdesk, PSID psid )
{
    DWORD lengthNeeded;

    SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
    if ( !GetUserObjectSecurity( hdesk, &secInfo, NULL, NULL, &lengthNeeded ) )
    {
        if ( GetLastError() != 122 )
        {
            std::cout << "GetUserObjectSecurity1 error: " << GetLastError() << std::endl;
            return 0;
        }
    }

    PSECURITY_DESCRIPTOR pSecDescriptor = ( PSECURITY_DESCRIPTOR ) HeapAlloc(
        GetProcessHeap(),
        HEAP_ZERO_MEMORY,
        lengthNeeded );

    if ( pSecDescriptor == NULL )
    {
        std::cout << "Allocating memory for pSecDescriptor failed: " << GetLastError() << std::endl;
        return 0;
    }

    PSECURITY_DESCRIPTOR pSecDescriptorNew = ( PSECURITY_DESCRIPTOR ) HeapAlloc(
        GetProcessHeap(),
        HEAP_ZERO_MEMORY,
        lengthNeeded );

    if ( pSecDescriptorNew == NULL )
    {
        std::cout << "Allocating memory for pSecDescriptorNew failed: " << GetLastError() << std::endl;
        return 0;
    }

    if ( !GetUserObjectSecurity( hdesk, &secInfo, pSecDescriptor, lengthNeeded, &lengthNeeded ) )
    {
        std::cout << "GetUserObjectSecurity2 error: " << GetLastError() << std::endl;
        return 0;
    }

    if ( !InitializeSecurityDescriptor( pSecDescriptorNew, SECURITY_DESCRIPTOR_REVISION ) )
    {
        std::cout << "InitializeSecurityDescriptor error: " << GetLastError() << std::endl;
        return 0;
    }

    BOOL DaclPresent;
    PACL pOldDacl;
    BOOL DaclDefaulted;
    if ( !GetSecurityDescriptorDacl( pSecDescriptor, &DaclPresent, &pOldDacl, &DaclDefaulted ) )
    {
        std::cout << "GetSecurityDescriptorDacl error: " << GetLastError() << std::endl;
        return 0;
    }

    // Get size information for DACL
    ACL_SIZE_INFORMATION AclInfo;
    AclInfo.AceCount = 0; // Assume NULL DACL.
    AclInfo.AclBytesFree = 0;
    AclInfo.AclBytesInUse = sizeof( ACL );

    if ( pOldDacl == NULL )
        DaclPresent = FALSE;

    // If not NULL DACL, gather size information from DACL.
    if ( DaclPresent )
    {
        if ( !GetAclInformation( pOldDacl, &AclInfo,
            sizeof( ACL_SIZE_INFORMATION ), AclSizeInformation ) )
        {
            std::cout << "GetAclInformation error: " << GetLastError() << std::endl;
            return 0;
        }
    }

    DWORD cbNewACL = AclInfo.AclBytesInUse + sizeof( ACCESS_ALLOWED_ACE ) + sizeof( ACL ) + sizeof( ACL );

    PACL pNewACL = ( PACL ) HeapAlloc(
        GetProcessHeap(),
        HEAP_ZERO_MEMORY,
        cbNewACL );

    if ( !InitializeAcl( pNewACL, cbNewACL, ACL_REVISION ) )
    {
        std::cout << "InitializeAcl error: " << GetLastError() << std::endl;
        return 0;
    }

    LPVOID         pTempAce = NULL;

    // Copy old Ace to new DACL
    if ( DaclPresent && AclInfo.AceCount )
    {
        std::cout << "AclInfo.AceCount:" << AclInfo.AceCount << std::endl;
        for ( int i = 0; i < AclInfo.AceCount; ++i )
        {
            if ( !GetAce( pOldDacl, i, &pTempAce ) )
            {
                std::cout << "GetAce[" << i << "] error: " << GetLastError() << std::endl;
                return 0;
            }

            if ( !AddAce( pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
                ( ( PACE_HEADER ) pTempAce )->AceSize ) )
            {
                std::cout << "AddAce[" << i << "] error: " << GetLastError() << std::endl;
                return 0;
            }
        }
    }

    if ( !AddAccessAllowedAce( pNewACL, ACL_REVISION, DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED, psid ) )
    {
        std::cout << "AddAccessAllowedAce error: " << GetLastError() << std::endl;
        return 0;
    }

    if ( !SetSecurityDescriptorDacl( pSecDescriptorNew, TRUE, pNewACL, FALSE ) )
    {
        std::cout << "SetSecurityDescriptorDacl error: " << GetLastError() << std::endl;
        return 0;
    }

    if ( !SetUserObjectSecurity( hdesk, &secInfo, pSecDescriptorNew ) )
    {
        std::cout << "SetUserObjectSecurity error: " << GetLastError() << std::endl;
        return 0;
    }

    return 1;
}

int AddAceToBaseNameObjectsDirectory( PSID psid, TOKEN_INFORMATION_CLASS tClass )
{
    return 0;
}

int main( int argc, TCHAR *argv[] )
{
    HANDLE userToken;

    if ( !LogonUser( L"test", L"", L"test", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &userToken ) )
    {
        std::cout << "LogonUser error: " << GetLastError() << std::endl;
        return -1;
    }

    HANDLE token;

    if ( !DuplicateTokenEx( userToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &token ) )
    {
        std::cout << "DuplicateTokenEx error: " << GetLastError() << std::endl;
        return -1;
    }

    PROFILEINFO profileInfo;
    profileInfo.lpUserName = L"test";
    profileInfo.dwFlags = NULL;
    profileInfo.lpProfilePath = L"C:\\Users\\test";

    LoadUserProfile( token, &profileInfo );

    LUID tcb_privilege_flag;

    if ( !LookupPrivilegeValue( NULL, SE_SECURITY_NAME, &tcb_privilege_flag ) )
    {
        std::cout << "LookupPrivilegeValue error: " << GetLastError() << std::endl;
        return -1;
    }

    TOKEN_PRIVILEGES tp;

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = tcb_privilege_flag;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if ( !AdjustTokenPrivileges( token, FALSE, &tp, sizeof( TOKEN_PRIVILEGES ), ( PTOKEN_PRIVILEGES ) NULL, ( PDWORD ) NULL ) )
    {
        std::cout << "AdjustTokenPrivileges error: " << GetLastError() << std::endl;
        return -1;
    }

    HWINSTA hwinstasave = GetProcessWindowStation();
    HWINSTA hwinsta = OpenWindowStation( L"winsta0", FALSE, READ_CONTROL | WRITE_DAC );

    HDESK hdesk = OpenDesktop( L"default", NULL, FALSE, READ_CONTROL | WRITE_DAC | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS );

    DWORD token_group_size;

    if ( !GetTokenInformation( token, TokenGroups, NULL, 0, &token_group_size ) )
    {
        if ( GetLastError() != 122 )
        {
            std::cout << "GetTokenInformation1 error: " << GetLastError() << std::endl;
            return -1;
        }
    }

    PTOKEN_GROUPS pTokenGroup = ( PTOKEN_GROUPS ) new BYTE[token_group_size];
    memset( pTokenGroup, 0, token_group_size );

    if ( !GetTokenInformation( token, TokenGroups, pTokenGroup, token_group_size, &token_group_size ) )
    {
        std::cout << "GetTokenInformation2 error: " << GetLastError() << std::endl;
        return -1;
    }

    PSID pSid = NULL;
    for ( int i = 0; i < pTokenGroup->GroupCount; ++i )
    {
        if ( ( pTokenGroup->Groups[i].Attributes & SE_GROUP_LOGON_ID ) == SE_GROUP_LOGON_ID )
        {
            pSid = pTokenGroup->Groups[i].Sid;
        }
    }

    if ( pSid == NULL )
    {
        std::cout << "Unable to get logonSID error! No entry found!!!" << std::endl;
        return -1;
    }

    if ( !AddAceToWindowStation( hwinsta, pSid ) )
    {
        std::cout << "AddAceToWindowStation error: " << GetLastError() << std::endl;
        return -1;
    }

    if ( !AddAceToDesktop( hdesk, pSid ) )
    {
        std::cout << "AddAceToDesktop error: " << GetLastError() << std::endl;
        return -1;
    }

    //if ( !AddAceToBaseNameObjectsDirectory( pSid, TokenSessionId ) )
    //{
    //  std::cout << "AddAceToBaseNameObjectsDirectory error: " << GetLastError() << std::endl;
    //  return -1;
    //}

    if ( !ImpersonateLoggedOnUser( token ) )
    {
        std::cout << "ImpersonateLoggedOnUser error: " << GetLastError() << std::endl;
        return -1;
    }

    STARTUPINFO startupInfo;

    memset( &startupInfo, 0, sizeof( startupInfo ) );

    startupInfo.dwFlags = STARTF_USESHOWWINDOW;
    startupInfo.wShowWindow = SW_SHOWNORMAL;
    startupInfo.lpDesktop = L"winsta0\\default";
    startupInfo.cb = sizeof( startupInfo );

    PROCESS_INFORMATION procInfo;

    memset( &procInfo, 0, sizeof( procInfo ) );

    if ( !SetCurrentDirectory( L"C:\\Windows" ) )
    {
        std::cout << "SetCurrentDirectory error: " << GetLastError() << std::endl;
        return -1;
    }

    if ( !CreateProcessAsUserW( token, L"Notepad.exe", L"Notepad.exe", NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &startupInfo, &procInfo ) )
    {
        std::cout << "CreateProcessAsUser error: " << GetLastError() << std::endl;
        return -1;
    }

    if ( !WaitForSingleObject( token, INFINITE ) )
    {
        std::cout << "WaitForSingleObject error: " << GetLastError() << std::endl;
        return -1;
    }
}
4

0 回答 0