ImpersonateLoggedOnUser успешен, но вторичный процесс все еще выполняется в начальном контексте

У меня есть установщик, который пытается (пере) запустить мое приложение в контексте текущего пользователя после завершения установки.
Программа установки работает в контексте SYSTEM и перед запуском приложения пытается (и теоретически успешно) выдать себя за текущего пользователя. Однако, когда я смотрю в диспетчере задач, я вижу, что мое приложение работает в контексте SYSTEM.

Это (фрагмент из) моего кода:

    TCHAR szUsername[128] = _T("");
DWORD dwUsernameSize = 128;
GetUserName(szUsername, &dwUsernameSize);

// Lets the calling process impersonate the security context of a logged-on user.
if (!ImpersonateLoggedOnUser(hToken))
{
throw Win32Exception(GetLastError(), _T("Failed to impersonate current user"));
}

TCHAR szUsername2[128] = _T("");
DWORD dwUsernameSize2 = 128;
GetUserName(szUsername2, &dwUsernameSize2);

MLOGD(_T("ProcessUtils::StartProcessInCurrentUserContext: Successfully impersonated %s"), szUsername2);

ProcessUtils::StartProcess(sExeName, lstParams, sWorkingDir, bWaitToFinish, errCode);

ProcessUtils :: StartProcess — это оболочка для CreateProcess.

szUsername содержит SYSTEM, а szUsername2 содержит текущего пользователя. Так что ImpersonateLoggedOnUser успешен.
Однако, как упоминалось выше, процесс запускается в контексте SYSTEM, а не в контексте текущего пользователя.

Я не уверен, насколько это может быть полезно, но мой установщик написан на NSIS и вызывает функцию, которая содержит код сверху, через плагин, написанный на C / C ++.

Кто-нибудь знает, почему мое приложение не запускается в текущем контексте пользователя?

0

Решение

Win32 CreateProcess создает процесс в так же контекст безопасности как вызывающий, который является СИСТЕМОЙ (даже если вы подражаете).

Думаю, вам нужно вызывать CreateProcessAsUser.

3

Другие решения

У меня была очень похожая проблема пару лет назад, когда я был также
работает над установщиком приложения. После МНОГО разочарования, вызванного
неудачными попытками запустить приложение в контексте текущего
пользователь, использующий CreateProcessAsUserЯ наконец сдался. После тщательного
поиск в Интернете, я нашел блестящую реализацию, которая использует
IShellDispatch2 интерфейс. Вот пример:

#include <Windows.h>
#include <exdisp.h>
#include <Shobjidl.h>
#include <Shlwapi.h>
#include <comutil.h>
#include <SHLGUID.h>
#include <cstdlib>
#include <iostream>

#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "comsuppw.lib")

bool ShellExecuteAsCurrentUser(const TCHAR *pcOperation, const TCHAR *pcFileName, const TCHAR *pcParameters,
const TCHAR *pcsDirectory, const DWORD dwShow)
{
bool bSuccess = false;

IShellWindows *psw = NULL;
HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&psw));

if(SUCCEEDED(hr))
{
HWND hwnd = 0;
IDispatch* pdisp = NULL;
_variant_t vEmpty;
if(S_OK == psw->FindWindowSW(&vEmpty, &vEmpty, SWC_DESKTOP, reinterpret_cast<long*>(&hwnd), SWFO_NEEDDISPATCH, &pdisp))
{
if((hwnd != NULL) && (hwnd != INVALID_HANDLE_VALUE))
{
IShellBrowser *psb;
hr = IUnknown_QueryService(pdisp, SID_STopLevelBrowser, IID_PPV_ARGS(&psb));
if(SUCCEEDED(hr))
{
IShellView *psv = NULL;
hr = psb->QueryActiveShellView(&psv);
if(SUCCEEDED(hr))
{
IDispatch *pdispBackground = NULL;
HRESULT hr = psv->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&pdispBackground));
if(SUCCEEDED(hr))
{
IShellFolderViewDual *psfvd = NULL;
hr = pdispBackground->QueryInterface(IID_PPV_ARGS(&psfvd));
if(SUCCEEDED(hr))
{
IDispatch *pdisp = NULL;
hr = psfvd->get_Application(&pdisp);
if(SUCCEEDED(hr))
{
IShellDispatch2 *psd;
hr = pdisp->QueryInterface(IID_PPV_ARGS(&psd));
if(SUCCEEDED(hr))
{
_variant_t verb(pcOperation);
_variant_t file(pcFileName);
_variant_t para(pcParameters);
_variant_t dir(pcsDirectory);
_variant_t show(dwShow);
if(SUCCEEDED(psd->ShellExecute(file.bstrVal, para, vEmpty, verb, show)))
bSuccess = true;

psd->Release();
psd = NULL;
}
pdisp->Release();
pdisp = NULL;
}
}
pdispBackground->Release();
pdispBackground = NULL;
}
psv->Release();
psv = NULL;
}
psb->Release();
psb = NULL;
}
}
pdisp->Release();
pdisp = NULL;
}
psw->Release();
psw = NULL;
}

return bSuccess;
}

int main(int argc, char *argv[])
{
CoInitialize(NULL);

if(ShellExecuteAsCurrentUser(L"open", L"notepad", nullptr, nullptr, SW_SHOWNORMAL))
std::cout << "SUCCESS" << std::endl;

CoUninitialize();

return 0;
}

Это просто небольшая демонстрация, реализация ShellExecuteAsCurrentUser может быть
улучшено использование умных указателей для интерфейсов COM и некоторого рефакторинга. Этот метод
работал для меня на версиях WinXP SP3 — Win 8.1, не уверен, работает ли он на Windows 10. Для
Более подробную информацию смотрите на странице авторов github:

https://github.com/lordmulder/stdutils/tree/master/Contrib/StdUtils

2

Если бы вы прочитали документация для CreateProcess, Вы бы нашли ответ на свой вопрос в первых трех предложениях:

Создает новый процесс и его основной поток. Новый процесс выполняется в контексте безопасности вызывающего процесса.

Если вызывающий процесс выдает себя за другого пользователя, новый процесс использует токен для вызывающего процесса, а не токен олицетворения.

Больше нечего сказать; поведение, которое вы описываете, является задокументированным. Если вы хотите создать процесс как другой пользователь, вы должны использовать CreateProcessAsUser или одна из связанных функций.

1
По вопросам рекламы [email protected]