Zaid Amir
Zaid Amir

Reputation: 4775

Impersonate standard user

I am trying to make a running process of mine which is elevated to restart explorer using the standard user token.

What I'm doing is first I run the main process as an administrator, then I take a snapshot of the running:

if (Process32First(hSnapshot,&pe32))
    {
        do
        {
            if (!wcsicmp(pe32.szExeFile, L"explorer.exe"))
            {
                DWORD dwExplorerSessId = 0;
                if (ProcessIdToSessionId(pe32.th32ProcessID, &dwExplorerSessId) && dwExplorerSessId == dwSessionId)
                {
                    dwExplorerLogonPid = pe32.th32ProcessID;
                    break;
                }
            }

        } while (Process32Next(hSnapshot, &pe32));
    }

    CloseHandle(hSnapshot);

then once I get the PID of explorer which is running under the standard user account, I call:

OpenProcessToken(hProcess,TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_IMPERSONATE
            ,&hPToken))

then I call:

ImpersonateLoggedOnUser(hPToken);

and finally I taskkill explorer.exe and shell execute it again but its running under the administrators privileges.

Its as if the impersonateLoggedonUser is not working. Although its returning true and GetLastError() returns 0;

I have also tried using CreateProcessAsUser() but this always gives an ERROR_FILE_NOT_FOUND:

    STARTUPINFO si;
    GetStartupInfo(&si);                
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

    TCHAR tchcmd[MAX_PATH];
    _tcscpy(tchcmd, _T("explorer.exe"));
    PVOID penv;
    CreateEnvironmentBlock(&penv, hToken, FALSE);
HANDLE hNewToken;
DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityIdentification, TokenImpersonation, &hNewToken);
    CreateProcessAsUser(, NULL, tchcmd, 0, 0, 0, CREATE_DEFAULT_ERROR_MODE, penv, 0, &si, &pi );

Any Ideas or suggestions.

Upvotes: 4

Views: 4517

Answers (2)

Marko Popovic
Marko Popovic

Reputation: 4153

I have encountered a similar problem when trying to run a program as a standard user from an installer started with elevated admin privileges. After trying ( and failing miserably ) to do this using CreateProcessAsUser function I have stumbled upon a solution that uses ShellExecute from IShellDispatch2 interface.

It can be used to start a process as current interactive user. For complete implementation look here: https://code.google.com/p/mulder/source/browse/trunk/Utils/nsis_stdutils/Contrib/StdUtils/ShellExecAsUser.cpp?r=327

Hope this helps!

Upvotes: 0

Brian R. Bondy
Brian R. Bondy

Reputation: 347276

Are you calling DuplicateTokenEx on the token before using it? You should.

Instead of ImpersonateLoggedOnUser, you could more easily just call CreateProcessAsUser.

Edit to match yours:

  • Your CreateProcessAsUser by the way should be passing: CREATE_DEFAULT_ERROR_MODE | CREATE_UNICODE_ENVIRONMENT for the dwCreationFlags.

  • You should also be error checking your CreateEnvironmentBlock.

  • You should also be adjusting the Ace of the desktop and window station.

  • Instead of specifying the path directly in CreateProcessByUser you should first expand any environment variables in the string by using ExpandEnvironmentStringsForUser. This will for example convert: %windir%\explorer.exe to C:\windows\explorer.exe

.

wchar_t szNewCommandLine[MAX_PATH];
if(!::ExpandEnvironmentStringsForUser(hNewToken, tchcmd, szNewCommandLine, MAX_PATH - 1))
{
    DWORD dwExpandEnvLastError = GetLastError();
    //error handling
}   

For further reading please see this post on Session, Window Station, and Desktop management.

Upvotes: 3

Related Questions