CreateProcessAsUser
在微软的MSDN文档里,讲到用LogonUser+DuplicateTokenEx+CreateProcessAsUser来以一个新用户身份去运行一个新线程,然而一个问题就是如果新用户是User组,而不是类似Administrator等权限高的用户的时候,会运行时错误退出,原因是要附加一个"winsta0\\default"以及桌面运行权限。For example, if the process that was started was trying to create a window, the process would have to have DESKTOP_CREATEWINDOW access to the desktop object. If the process has not been granted this access right, an error would occur in the User32.dll file, which would cause the system error box to appear and the process would fail to start.
正确代码见下文。
但要注意的一点是,SetUserObjectSecurity may gives error code ERROR_NOT_ENOUGH_QUOTA. If you call SetUserObjectSecurity millions.
所以使用类似代码的时候要格外小心,一个较好的办法是LogonUser得到的HTOKEN保存起来,
下次要使用相同的用户的时候就直接使用该HTOKEN,如果这样做,那么请不要对HTOKEN使用CloseHandle,否则保存的值无效,但你就很可能在程序结束后也没有使用CloseHandle,不过不关闭这个句柄会有什么后果就不太清楚。但如果不这样做,那么事实上调用并不需要很多次(大约84次)就会出现 ERROR_NOT_ENOUGH_QUOTA的结果
以下代码来自MSDN,本人有改动
#define RTN_OK 0
#define RTN_ERROR 13
#define RTN_ERROR 13
#define WINSTA_ALL (WINSTA_ACCESSCLIPBOARD | WINSTA_ACCESSGLOBALATOMS | \
WINSTA_CREATEDESKTOP | WINSTA_ENUMDESKTOPS | \
WINSTA_ENUMERATE | WINSTA_EXITWINDOWS | \
WINSTA_READATTRIBUTES | WINSTA_READSCREEN | \
WINSTA_CREATEDESKTOP | WINSTA_ENUMDESKTOPS | \
WINSTA_ENUMERATE | WINSTA_EXITWINDOWS | \
WINSTA_READATTRIBUTES | WINSTA_READSCREEN | \
WINSTA_WRITEATTRIBUTES | DELETE | \
READ_CONTROL | WRITE_DAC | \
WRITE_OWNER)
READ_CONTROL | WRITE_DAC | \
WRITE_OWNER)
#define DESKTOP_ALL (DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | \
DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | \
DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD | \
DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | \
DESKTOP_WRITEOBJECTS | DELETE | \
READ_CONTROL | WRITE_DAC | \
WRITE_OWNER)
DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | \
DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD | \
DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | \
DESKTOP_WRITEOBJECTS | DELETE | \
READ_CONTROL | WRITE_DAC | \
WRITE_OWNER)
#define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)
#include <windows.h>
#include <stdio.h>
#define __try for(int _n=0;_n==0;++_n)
#define __leave break
#define __finally ;
#define __leave break
#define __finally ;
BOOL ObtainSid(
HANDLE hToken, // Handle to an process access token.
PSID *psid // ptr to the buffer of the logon sid
);
HANDLE hToken, // Handle to an process access token.
PSID *psid // ptr to the buffer of the logon sid
);
void RemoveSid(
PSID *psid // ptr to the buffer of the logon sid
);
PSID *psid // ptr to the buffer of the logon sid
);
BOOL AddTheAceWindowStation(
HWINSTA hwinsta, // handle to a windowstation
HWINSTA hwinsta, // handle to a windowstation
PSID psid // logon sid of the process
);
);
BOOL AddTheAceDesktop(
HDESK hdesk, // handle to a desktop
PSID psid // logon sid of the process
);
HDESK hdesk, // handle to a desktop
PSID psid // logon sid of the process
);
int main(void)
{
HANDLE hToken;
HDESK hdesk;
HWINSTA hwinsta;
PROCESS_INFORMATION pi;
PSID psid;
STARTUPINFO si;
{
HANDLE hToken;
HDESK hdesk;
HWINSTA hwinsta;
PROCESS_INFORMATION pi;
PSID psid;
STARTUPINFO si;
if (!LogonUser(
"test",
NULL,
"onlinejudge",
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hToken))
{
return RTN_ERROR;
}
hwinsta = OpenWindowStation(
"winsta0",
FALSE,
READ_CONTROL | WRITE_DAC
);
if (hwinsta == NULL)
return RTN_ERROR;
HWINSTA hwinstaold = GetProcessWindowStation();
if (!SetProcessWindowStation(hwinsta))
return RTN_ERROR;
hdesk = OpenDesktop(
"default",
0,
FALSE,
READ_CONTROL | WRITE_DAC |
DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS
if (hwinsta == NULL)
return RTN_ERROR;
HWINSTA hwinstaold = GetProcessWindowStation();
if (!SetProcessWindowStation(hwinsta))
return RTN_ERROR;
hdesk = OpenDesktop(
"default",
0,
FALSE,
READ_CONTROL | WRITE_DAC |
DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS
);
if (hdesk == NULL)
return RTN_ERROR;
if (!ObtainSid(hToken, &psid))
return RTN_ERROR;
if (!AddTheAceWindowStation(hwinsta, psid))
return RTN_ERROR;
if (!AddTheAceDesktop(hdesk, psid))
return RTN_ERROR;
RemoveSid(&psid);
if (hdesk == NULL)
return RTN_ERROR;
if (!ObtainSid(hToken, &psid))
return RTN_ERROR;
if (!AddTheAceWindowStation(hwinsta, psid))
return RTN_ERROR;
if (!AddTheAceDesktop(hdesk, psid))
return RTN_ERROR;
RemoveSid(&psid);
CloseWindowStation(hwinsta);
CloseDesktop(hdesk);
CloseDesktop(hdesk);
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = "winsta0\\default";
if (!CreateProcessAsUser(
hToken,
NULL,
"C:\\",
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = "winsta0\\default";
if (!CreateProcessAsUser(
hToken,
NULL,
"C:\\",
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi
))
{
return RTN_ERROR;
}
SetProcessWindowStation(hwinstaold); //set it back
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
NULL,
&si,
&pi
))
{
return RTN_ERROR;
}
SetProcessWindowStation(hwinstaold); //set it back
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return RTN_OK;
}
}
BOOL ObtainSid(HANDLE hToken, PSID *psid)
{
BOOL bSuccess = FALSE; // assume function will
// fail
DWORD dwIndex;
DWORD dwLength = 0;
TOKEN_INFORMATION_CLASS tic = TokenGroups;
PTOKEN_GROUPS ptg = NULL;
__try
{
if (!GetTokenInformation(
hToken,
{
BOOL bSuccess = FALSE; // assume function will
// fail
DWORD dwIndex;
DWORD dwLength = 0;
TOKEN_INFORMATION_CLASS tic = TokenGroups;
PTOKEN_GROUPS ptg = NULL;
__try
{
if (!GetTokenInformation(
hToken,
tic,
(LPVOID)ptg,
0,
&dwLength
))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
ptg = (PTOKEN_GROUPS)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwLength
);
if (ptg == NULL)
__leave;
(LPVOID)ptg,
0,
&dwLength
))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
ptg = (PTOKEN_GROUPS)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwLength
);
if (ptg == NULL)
__leave;
}
else
__leave;
}
if (!GetTokenInformation(
hToken,
tic,
(LPVOID)ptg,
dwLength,
&dwLength
))
__leave;
for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++)
else
__leave;
}
if (!GetTokenInformation(
hToken,
tic,
(LPVOID)ptg,
dwLength,
&dwLength
))
__leave;
for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++)
{
if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
{
dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid);
*psid = (PSID)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwLength
);
if (*psid == NULL)
__leave;
if (!CopySid(dwLength, *psid, ptg->Groups[dwIndex].Sid))
if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID)
{
dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid);
*psid = (PSID)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwLength
);
if (*psid == NULL)
__leave;
if (!CopySid(dwLength, *psid, ptg->Groups[dwIndex].Sid))
__leave;
break;
}
}
bSuccess = TRUE;
}
__finally
{
if (ptg != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
}
return bSuccess;
}
break;
}
}
bSuccess = TRUE;
}
__finally
{
if (ptg != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
}
return bSuccess;
}
void RemoveSid(PSID *psid)
{
HeapFree(GetProcessHeap(), 0, (LPVOID)*psid);
}
{
HeapFree(GetProcessHeap(), 0, (LPVOID)*psid);
}
BOOL AddTheAceWindowStation(HWINSTA hwinsta, PSID psid)
{
ACCESS_ALLOWED_ACE *pace = NULL;
ACL_SIZE_INFORMATION aclSizeInfo;
BOOL bDaclExist;
BOOL bDaclPresent;
BOOL bSuccess = FALSE; // assume function will
//fail
DWORD dwNewAclSize;
DWORD dwSidSize = 0;
DWORD dwSdSizeNeeded;
{
ACCESS_ALLOWED_ACE *pace = NULL;
ACL_SIZE_INFORMATION aclSizeInfo;
BOOL bDaclExist;
BOOL bDaclPresent;
BOOL bSuccess = FALSE; // assume function will
//fail
DWORD dwNewAclSize;
DWORD dwSidSize = 0;
DWORD dwSdSizeNeeded;
PACL pacl;
PACL pNewAcl = NULL;
PSECURITY_DESCRIPTOR psd = NULL;
PSECURITY_DESCRIPTOR psdNew = NULL;
PVOID pTempAce;
SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
unsigned int i;
__try
{
//
// obtain the dacl for the windowstation
//
if (!GetUserObjectSecurity(
hwinsta,
PACL pNewAcl = NULL;
PSECURITY_DESCRIPTOR psd = NULL;
PSECURITY_DESCRIPTOR psdNew = NULL;
PVOID pTempAce;
SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
unsigned int i;
__try
{
//
// obtain the dacl for the windowstation
//
if (!GetUserObjectSecurity(
hwinsta,
&si,
psd,
dwSidSize,
&dwSdSizeNeeded
))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
psd = (PSECURITY_DESCRIPTOR)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwSdSizeNeeded
);
if (psd == NULL)
__leave;
psd,
dwSidSize,
&dwSdSizeNeeded
))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
psd = (PSECURITY_DESCRIPTOR)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwSdSizeNeeded
);
if (psd == NULL)
__leave;
psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwSdSizeNeeded
);
if (psdNew == NULL)
__leave;
dwSidSize = dwSdSizeNeeded;
if (!GetUserObjectSecurity(
hwinsta,
&si,
psd,
dwSidSize,
&dwSdSizeNeeded
))
__leave;
}
else
__leave;
}
//
// create a new dacl
//
if (!InitializeSecurityDescriptor(
psdNew,
SECURITY_DESCRIPTOR_REVISION
))
&dwSdSizeNeeded
))
__leave;
}
else
__leave;
}
//
// create a new dacl
//
if (!InitializeSecurityDescriptor(
psdNew,
SECURITY_DESCRIPTOR_REVISION
))
__leave;
//
// get dacl from the security descriptor
//
if (!GetSecurityDescriptorDacl(
psd,
&bDaclPresent,
&pacl,
&bDaclExist
))
__leave;
//
// initialize
//
// get dacl from the security descriptor
//
if (!GetSecurityDescriptorDacl(
psd,
&bDaclPresent,
&pacl,
&bDaclExist
))
__leave;
//
// initialize
//
ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
aclSizeInfo.AclBytesInUse = sizeof(ACL);
//
// call only if the dacl is not NULL
//
if (pacl != NULL)
{
// get the file ACL size info
if (!GetAclInformation(
pacl,
(LPVOID)&aclSizeInfo,
sizeof(ACL_SIZE_INFORMATION),
AclSizeInformation
ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
aclSizeInfo.AclBytesInUse = sizeof(ACL);
//
// call only if the dacl is not NULL
//
if (pacl != NULL)
{
// get the file ACL size info
if (!GetAclInformation(
pacl,
(LPVOID)&aclSizeInfo,
sizeof(ACL_SIZE_INFORMATION),
AclSizeInformation
))
__leave;
}
//
// compute the size of the new acl
//
dwNewAclSize = aclSizeInfo.AclBytesInUse + (2 *
sizeof(ACCESS_ALLOWED_ACE)) + (2 * GetLengthSid(psid)) - (2 *
sizeof(DWORD));
//
// allocate memory for the new acl
//
pNewAcl = (PACL)HeapAlloc(
__leave;
}
//
// compute the size of the new acl
//
dwNewAclSize = aclSizeInfo.AclBytesInUse + (2 *
sizeof(ACCESS_ALLOWED_ACE)) + (2 * GetLengthSid(psid)) - (2 *
sizeof(DWORD));
//
// allocate memory for the new acl
//
pNewAcl = (PACL)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwNewAclSize
);
if (pNewAcl == NULL)
__leave;
//
// initialize the new dacl
//
if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
__leave;
//
// if DACL is present, copy it to a new DACL
HEAP_ZERO_MEMORY,
dwNewAclSize
);
if (pNewAcl == NULL)
__leave;
//
// initialize the new dacl
//
if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
__leave;
//
// if DACL is present, copy it to a new DACL
//
if (bDaclPresent) // only copy if DACL was present
{
// copy the ACEs to our new ACL
if (aclSizeInfo.AceCount)
{
for (i = 0; i < aclSizeInfo.AceCount; i++)
{
// get an ACE
if (!GetAce(pacl, i, &pTempAce))
__leave;
// add the ACE to the new ACL
if (!AddAce(
pNewAcl,
if (bDaclPresent) // only copy if DACL was present
{
// copy the ACEs to our new ACL
if (aclSizeInfo.AceCount)
{
for (i = 0; i < aclSizeInfo.AceCount; i++)
{
// get an ACE
if (!GetAce(pacl, i, &pTempAce))
__leave;
// add the ACE to the new ACL
if (!AddAce(
pNewAcl,
ACL_REVISION,
MAXDWORD,
pTempAce,
((PACE_HEADER)pTempAce)->AceSize
))
__leave;
}
}
}
//
// add the first ACE to the windowstation
//
pace = (ACCESS_ALLOWED_ACE *)HeapAlloc(
GetProcessHeap(),
MAXDWORD,
pTempAce,
((PACE_HEADER)pTempAce)->AceSize
))
__leave;
}
}
}
//
// add the first ACE to the windowstation
//
pace = (ACCESS_ALLOWED_ACE *)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) -
sizeof(DWORD
));
if (pace == NULL)
__leave;
pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
pace->Header.AceFlags = CONTAINER_INHERIT_ACE |
INHERIT_ONLY_ACE |
OBJECT_INHERIT_ACE;
pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid(psid) - sizeof(DWORD);
sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) -
sizeof(DWORD
));
if (pace == NULL)
__leave;
pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
pace->Header.AceFlags = CONTAINER_INHERIT_ACE |
INHERIT_ONLY_ACE |
OBJECT_INHERIT_ACE;
pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid(psid) - sizeof(DWORD);
pace->Mask = GENERIC_ACCESS;
if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid))
__leave;
if (!AddAce(
pNewAcl,
ACL_REVISION,
MAXDWORD,
(LPVOID)pace,
pace->Header.AceSize
))
__leave;
//
if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid))
__leave;
if (!AddAce(
pNewAcl,
ACL_REVISION,
MAXDWORD,
(LPVOID)pace,
pace->Header.AceSize
))
__leave;
//
// add the second ACE to the windowstation
//
pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;
pace->Mask = WINSTA_ALL;
if (!AddAce(
pNewAcl,
ACL_REVISION,
MAXDWORD,
(LPVOID)pace,
pace->Header.AceSize
))
__leave;
//
//
pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;
pace->Mask = WINSTA_ALL;
if (!AddAce(
pNewAcl,
ACL_REVISION,
MAXDWORD,
(LPVOID)pace,
pace->Header.AceSize
))
__leave;
//
// set new dacl for the security descriptor
//
if (!SetSecurityDescriptorDacl(
psdNew,
TRUE,
pNewAcl,
FALSE
))
__leave;
//
// set the new security descriptor for the windowstation
//
if (!SetUserObjectSecurity(hwinsta, &si, psdNew))
__leave;
//
if (!SetSecurityDescriptorDacl(
psdNew,
TRUE,
pNewAcl,
FALSE
))
__leave;
//
// set the new security descriptor for the windowstation
//
if (!SetUserObjectSecurity(hwinsta, &si, psdNew))
__leave;
//
// indicate success
//
bSuccess = TRUE;
}
__finally
{
startupinfo //
// free the allocated buffers
//
if (pace != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)pace);
if (pNewAcl != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);
if (psd != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
if (psdNew != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);
}
return bSuccess;
}
if (psd != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
if (psdNew != NULL)
HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);
}
return bSuccess;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论