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 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 <windows.h>
#include <stdio.h>
#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));
    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);
   
    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));
        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(
            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 (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(),
            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);
        pace->Mask = GENERIC_ACCESS;
       
        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;
       
        //
        // 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
    {
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;
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。