i have a problem in an application using Windows API CreateProcessAsUser from local system admin in order to run an application as a different user. Everything works fine so far, but the Windows window and frame style are not applied somehow. The window always looks like a Windows 2000 window with huge frames. I also attached some screenshot
I also wrote some example code of how we do all the magic in C++ without taking care of handles and stuff.
Just make sure that you have locally some user "test" with password "test" set and try to run the posted source code as local system administrator. Other user will cause an error code 1413 if you try to execute the code.
The problem occurres mainly on Windows 7 VMs in VirtualBox, on some Windows 7 systems and on all Windows 8.1 systems. Very strange. Can anyone help me to solve this problem? Thanks!
#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;
}
}