我在使用来自本地系统管理员的 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;
}
}