Процесс, созданный с помощью CreateProcessAsUserW из 64-разрядного процесса, немедленно завершает работу с кодом исключения 0xc06d007e в 64-разрядной версии Windows 7 - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть приложение C #, которое запускается из C ++ DLL с использованием API CreateProcessAsUserW. Процесс запущен успешно, но завершается немедленно. Он работает должным образом в Windows 10 [как 32-разрядной, так и 64-разрядной] и 32-разрядной в Windows 7. Я нашел следующую ссылку,

Почему происходит сбой этого процесса при запуске?

однако монитор процесса из SysInternals не находит отсутствующие dll. [Я могу прикрепить сохраненные журналы из ProcMon] Я также попытался передать путь к папке приложения, как предложено в другом месте, в параметре API lpCurrentDirectory, но это тоже не сработало.

Я следовал инструкциям в Как получить активного пользователя, когда в Windows зарегистрировано несколько пользователей? , чтобы написать код, запускающий процесс, и метод, который запускает процесс, вызывается из службы Windows. Чтобы эмулировать это из командной строки, я использовал следующее Как запустить CMD.exe под учетной записью локальной системы? [psexec64 -i -s cmd.exe, а затем запустил процесс из cmd.exe] Метод заключается в следующем // Как получить активного пользователя, когда в Windows зарегистрировано несколько пользователей?

 STDMETHODIMP CProcessManager::LaunchProcessAsActiveUser(BSTR processName, LONG* dwProcessId)
    {

        //char *lpszPath = _com_util::ConvertBSTRToString(processName);
        wchar_t* path = (wchar_t*)processName;//CharToWideChar(lpszPath);

        DWORD session_id = -1;
        DWORD session_count = 0;

        WTS_SESSION_INFOA *pSession = NULL;


        if (WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
        {
            //log success
        }
        else
        {
            //log error
            return S_OK;
        }
        logger->Log(L"Session Count", session_count);
        logger->Log(L"Begin Enumerating Sesions");
        for (int i = 0; i < session_count; i++)
        {
            session_id = pSession[i].SessionId;
            logger->Log(L"SessionId", session_id);

            WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
            WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;

            DWORD bytes_returned = 0;
            if (::WTSQuerySessionInformation(
                WTS_CURRENT_SERVER_HANDLE,
                session_id,
                WTSConnectState,
                reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
                &bytes_returned))
            {
                wts_connect_state = *ptr_wts_connect_state;
                ::WTSFreeMemory(ptr_wts_connect_state);
                if (wts_connect_state != WTSActive) continue;
            }
            else
            {
                //log error
                continue;
            }
            logger->Log(L"End Enumerating Sesions");
            logger->Log(L"Selected Session Id", session_id);
            HANDLE hImpersonationToken;

            if (!WTSQueryUserToken(session_id, &hImpersonationToken))
            {
                //log error
                logger->Log(L"Exception in WTSQueryUserToken", GetLastError());
                continue;
            }


            //Get real token from impersonation token
            DWORD neededSize1 = 0;
            HANDLE *realToken = new HANDLE;
            if (GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1))
            {
                CloseHandle(hImpersonationToken);
                hImpersonationToken = *realToken;
            }
            else
            {
                //log error
                logger->Log(L"Exception in GetTokenInformation", GetLastError());
                continue;
            }


            HANDLE hUserToken;

            if (!DuplicateTokenEx(hImpersonationToken,
                //0,
                //MAXIMUM_ALLOWED,
                TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
                NULL,
                SecurityImpersonation,
                TokenPrimary,
                &hUserToken))
            {
                //log error
                logger->Log(L"Exception in DuplicateTokenEx", GetLastError());
                continue;
            }

            // Get user name of this process
            //LPTSTR pUserName = NULL;
            WCHAR* pUserName;
            DWORD user_name_len = 0;

            if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len))
            {
                //log username contained in pUserName WCHAR string
                // char * lpszUserName = WideCharToChar(pUserName);
                logger->Log(pUserName);
                //LocalFree(lpszUserName);
            }
            else
            {
                logger->Log(L"Exception in WTSQuerySessionInformation", GetLastError());
            }

            //Free memory                         
            if (pUserName) WTSFreeMemory(pUserName);

            ImpersonateLoggedOnUser(hUserToken);

            STARTUPINFOW StartupInfo;

            StartupInfo.cb = sizeof(STARTUPINFOW);




            //GetStartupInfoW(&StartupInfo);
            ZeroMemory(&StartupInfo, sizeof(StartupInfo));
            //Uncommented  by Sagar 20th January 20118 1612
            StartupInfo.lpDesktop = CharToWideChar("winsta0\\default");

            //to Hide Console Process 03-10-2018
            StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
            StartupInfo.wShowWindow = SW_SHOW;//SW_HIDE;



            PROCESS_INFORMATION processInfo;



            SECURITY_ATTRIBUTES Security1;
            ZeroMemory(&Security1, sizeof(Security1));

            Security1.nLength = sizeof SECURITY_ATTRIBUTES;


            SECURITY_ATTRIBUTES Security2;
            ZeroMemory(&Security2, sizeof(Security2));
            Security2.nLength = sizeof SECURITY_ATTRIBUTES;

            void* lpEnvironment = NULL;

            // Get all necessary environment variables of logged in user
            // to pass them to the new process
            BOOL resultEnv = CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE);

            if (!resultEnv)
            {
                //log error
                DWORD err = GetLastError();
                logger->Log(L"Exception in CreateEnvironmentBlock", err);

                continue;
            }

            WCHAR PP[1024]; //path and parameters
            ZeroMemory(PP, 1024 * sizeof WCHAR);
            wcscpy_s(PP, path);
            wcscat_s(PP, L" ");
            //wcscat(PP, args);

            // Start the process on behalf of the current user 
            BOOL result = CreateProcessAsUserW(hUserToken,
                PP,
                NULL,
                &Security1,
                &Security2,
                FALSE,
                NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE/*| CREATE_NO_WINDOW*/,//CREATE_NO_WINDOW to Hide Console Process 03-10-2018
                /*lpEnvironment*/NULL,

                //"C:\\ProgramData\\some_dir",
                NULL,
                /*NULL,*/
                &StartupInfo,
                &processInfo);

            if (!result)
            {
                //log error
                //char * lpszPath = WideCharToChar(PP);
                logger->Log(L"Failed to create process", PP);
                //LocalFree(lpszPath);
                DWORD err = GetLastError();
                logger->Log(L"GetLastError returned", err);

            }
            else
            {
                *dwProcessId = processInfo.dwProcessId;
                logger->Log(L"Created Process", *dwProcessId);
                //log success
            }

            DestroyEnvironmentBlock(lpEnvironment);

            CloseHandle(hImpersonationToken);
            CloseHandle(hUserToken);
            CloseHandle(realToken);

            RevertToSelf();
        }

        WTSFreeMemory(pSession);


        return S_OK;
    }

Скриншоты Procmon прилагается ниже Пожалуйста помоги. Спасибо, Сагар

[![Pg 1](https://i.stack.imgur.com/CJCrG.png)
[![Pg 2](https://i.stack.imgur.com/uo8Uw.png)
[![Pg 3](https://i.stack.imgur.com/G7g12.png)
[![Pg 4](https://i.stack.imgur.com/6e5w4.png)
[![Pg 5](https://i.stack.imgur.com/8k2b0.png)

Я попробовал следующие перестановки

Target Process : ATL DLL : Launcher:Result
 64 bit      64 bit     64 bit      Crashes
 64 bit      32 bit     64 bit      Crashes
 32 bit      32 bit     64 bit      Crashes
 32 bit      64 bit     64 bit      Crashes
 32 bit      32 bit     32 bit      OK
 64 bit      32 bit     32 bit      OK
 64 bit      64 bit     32 bit      OK
 32 bit      64 bit     32 bit      OK

Так что, похоже, что процесс запуска 64-битный, он всегда падает, а если он 32-битный, он всегда завершается успешно. В чем разница между 64-битным и 32-битным процессами запуска?

1 Ответ

0 голосов
/ 21 ноября 2018

Я получил ответ на https://social.msdn.microsoft.com/Forums/vstudio/en-US/fb9d15fb-dc9f-488e-92c4-e0bb438442e1/64-bit-dot-net-process-created-with-createprocessasuserw-exits-immediately-with-exception-code?forum=vcgeneral [RLWA32 ответил на него] Возникла проблема с запуском процесса. Его код для запуска процесса выглядит следующим образом, и он отлично работает.

UINT __stdcall RunProgram(LPVOID pv)
{
    WCHAR szTarg32[MAX_PATH] = TARGET32_PATH, szTarg64[MAX_PATH] = TARGET64_PATH;
    LPWSTR pszProcess = nullptr;
    PWTS_SESSION_INFOW pwsi = NULL;
    DWORD dwSession = -1, dwCount = 0;
    HANDLE hToken = NULL;
    LPVOID lpEnvironment = nullptr;
    LPWSTR pszPath = nullptr;
    UINT ret = 1;


    DWORD dwOpcode = reinterpret_cast<DWORD>(pv);

    if (dwOpcode == LAUNCH_X86PROCESS)
        pszProcess = szTarg32;
    else
        pszProcess = szTarg64;

    if (!WTSEnumerateSessionsW(WTS_CURRENT_SERVER, 0, 1, &pwsi, &dwCount))
    {
        Report(L"WTSEnumerateSessions failed with %d\n", GetLastError());
        return ret;
    }

    for (DWORD i = 0; i < dwCount; i++)
    {
        if (pwsi[i].State == WTSActive)
        {
            dwSession = pwsi[i].SessionId;
            break;
        }
    }

    if (dwSession != -1)
    {
        if (WTSQueryUserToken(dwSession, &hToken))
        {
            if (CreateEnvironmentBlock(&lpEnvironment, hToken, FALSE))
            {
                HRESULT hr;
                if (SUCCEEDED((hr = SHGetKnownFolderPath(FOLDERID_Documents, KF_FLAG_DEFAULT, hToken, &pszPath))))
                {
                    if (ImpersonateLoggedOnUser(hToken))
                    {
                        STARTUPINFOW si = { sizeof si };
                        PROCESS_INFORMATION pi = {};

                        if (CreateProcessAsUserW(hToken, pszProcess, nullptr, nullptr, nullptr, FALSE, CREATE_UNICODE_ENVIRONMENT, lpEnvironment, pszPath, &si, &pi))
                        {
                            CloseHandle(pi.hThread);
                            CloseHandle(pi.hProcess);
                            Report(L"CreateProcessAsUser started %s, pid is %d\n", pszProcess, pi.dwProcessId);
                            ret = 0;
                        }
                        else
                            Report(L"CreateProcessAsUser failed with %d\n", GetLastError());

                        RevertToSelf();
                    }
                    else
                        Report(L"ImpersonateLoggedOnUser failed with %d\n", GetLastError());
                }
                else
                    Report(L"SHGetKnownFolderPath failed with 0x%X\n", hr);
            }
            else
                Report(L"CreateEnvironmentBlock failed with %d\n", GetLastError());
        }
        else
            Report(L"WTSQueryUserToken failed with %d\n", GetLastError());
    }
    else
        Report(L"WTSEnumerateSessions reported no active session\n");

    if (pwsi)
        WTSFreeMemory(pwsi);

    if (hToken)
        CloseHandle(hToken);

    if (lpEnvironment)
        DestroyEnvironmentBlock(lpEnvironment);

    if (pszPath)
        CoTaskMemFree(pszPath);

    return ret;
}
...