CreateProcessAsUser

CreateProcessAsUser

2023年6月23日发(作者:)

CreateProcessAsUser

在微软的MSDN文档里,讲到用LogonUser+DuplicateTokenEx+CreateProcessAsUser来以一个新用户身份去运行一个新线程,然而一个问题就是如果新用户是User组,而不是类似Administrator等权限高的用户的时候,会运行时错误退出,原因是要附加一个"winsta0default"以及桌面运行权限。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

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 WINSTA_ALL (WINSTA_ACCESSCLIPBOARD |

WINSTA_ACCESSGLOBALATOMS |

WINSTA_CREATEDESKTOP | WINSTA_ENUMDESKTOPS |

WINSTA_ENUMERATE | WINSTA_EXITWINDOWS |

WINSTA_READATTRIBUTES | WINSTA_READSCREEN |

WINSTA_WRITEATTRIBUTES | DELETE |

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)

#define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE |

GENERIC_ALL)

#include

#include

#define __try for(int _n=0;_n==0;++_n)

#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

);

void RemoveSid(

PSID *psid // ptr to the buffer of the logon sid

);

BOOL AddTheAceWindowStation(

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

);

int main(void)

{

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 (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);

ZeroMemory(&si, sizeof(STARTUPINFO));

= sizeof(STARTUPINFO);

top = "winsta0default";

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(ss);

CloseHandle(d);

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,

tic,

(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++)

{

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;

}

void RemoveSid(PSID *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;

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,

&si,

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

))

__leave;

//

// get dacl from the security descriptor

//

if (!GetSecurityDescriptorDacl(

psd,

&bDaclPresent,

&pacl,

&bDaclExist

))

__leave;

//

// initialize

//

ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));

esInUse = 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 = esInUse + (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

//

if (bDaclPresent) // only copy if DACL was present

{

// copy the ACEs to our new ACL

if (nt)

{

for (i = 0; i < nt; 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(),

HEAP_ZERO_MEMORY,

sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) -

sizeof(DWORD

));

if (pace == NULL)

__leave;

pace->e = ACCESS_ALLOWED_ACE_TYPE;

pace->gs = CONTAINER_INHERIT_ACE |

INHERIT_ONLY_ACE |

OBJECT_INHERIT_ACE;

pace->e = 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->e

))

__leave;

//

// add the second ACE to the windowstation

//

pace->gs = NO_PROPAGATE_INHERIT_ACE;

pace->Mask = WINSTA_ALL;

if (!AddAce(

pNewAcl,

ACL_REVISION,

MAXDWORD,

(LPVOID)pace,

pace->e

))

__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;

//

// indicate success

//

bSuccess = TRUE;

}

__finally

{

//

// 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;

}

BOOL AddTheAceDesktop(HDESK hdesk, PSID psid)

{

ACL_SIZE_INFORMATION aclSizeInfo;

BOOL bDaclExist;

BOOL bDaclPresent;

BOOL bSuccess = FALSE; // assume function will

// fail

DWORD dwNewAclSize;

DWORD dwSidSize = 0;

DWORD dwSdSizeNeeded;

PACL pacl = NULL;

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 security descriptor for the desktop object

//

if (!GetUserObjectSecurity(

hdesk,

&si,

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(

hdesk,

&si,

psd,

dwSidSize,

&dwSdSizeNeeded ))

__leave;

}

else

__leave;

}

//

// create a new security descriptor

//

if (!InitializeSecurityDescriptor(

psdNew,

SECURITY_DESCRIPTOR_REVISION

))

__leave;

//

// obtain the dacl from the security descriptor

//

if (!GetSecurityDescriptorDacl(

psd,

&bDaclPresent,

&pacl,

&bDaclExist

))

__leave;

//

// initialize

//

ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));

esInUse = sizeof(ACL);

//

// call only if NULL dacl

//

if (pacl != NULL)

{

//

// determine the size of the ACL info

//

if (!GetAclInformation(

pacl,

(LPVOID)&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION),

AclSizeInformation

))

__leave;

}

//

// compute the size of the new acl

//

dwNewAclSize = esInUse +

sizeof(ACCESS_ALLOWED_ACE) +

GetLengthSid(psid) - sizeof(DWORD);

//

// allocate buffer for the new acl

//

pNewAcl = (PACL)HeapAlloc(

GetProcessHeap(),

HEAP_ZERO_MEMORY,

dwNewAclSize

);

if (pNewAcl == NULL)

__leave;

//

// initialize the new acl

//

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 (nt)

{

for (i = 0; i < nt; 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 ace to the dacl

//

if (!AddAccessAllowedAce(

pNewAcl,

ACL_REVISION,

DESKTOP_ALL,

psid

))

__leave;

//

// set new dacl to the new security descriptor

//

if (!SetSecurityDescriptorDacl(

psdNew,

TRUE,

pNewAcl,

FALSE

))

__leave;

//

// set the new security descriptor for the desktop object

//

if (!SetUserObjectSecurity(hdesk, &si, psdNew))

__leave;

//

// indicate success

// bSuccess = TRUE;

}

__finally

{

//

// free buffers

//

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;

}

发布者:admin,转转请注明出处:http://www.yc00.com/news/1687516045a16219.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信