6

I'm using CreateProcessAsUser to create a process under user-specified credentials.

I'm posting what are hopefully the relevant parts of the code. Let me know if you want to see anything more.

First LogonUser to get the token:

result = LogonUser(
        username,
        wcschr(username, '@') ? NULL : (domain ? domain : L"."),
        password,
        LOGON32_LOGON_INTERACTIVE,
        LOGON32_PROVIDER_DEFAULT,
        &hrunastoken);

I then load the profile, set the lpDesktop value of the STARTUPINFO structure to NULL (which makes it use the desktop of the calling process), and call CreateProcessAsUser:

result = CreateProcessAsUser(
        hrunastoken,
        NULL,
        apptorun,
        NULL,
        NULL,
        FALSE,
        CREATE_UNICODE_ENVIRONMENT,
        envblock ? envblock : NULL,
        NULL,
        &si,
        &pi);

This works fine - it logs in and creates the process successfully, and the process "works". The problem is that the windows it creates are black, as in this screenshot of a notepad process started with my program:

notepad screenshot

Possibly relevant context:

My account is a local account on a Windows 7 machine with full admin rights, and I am logged on with that account. I used psexec (Sysinternals utility) to open a command prompt running interactively under the local system account. I am launching my program from that command prompt. The credentials I am passing to it are from my account.

I have not done anything with permissions to windowstations/desktops; I assume the process I create should have rights to those as the process is being created in my session and using the same account I'm already logged in with - albeit going through the SYSTEM account first. Using Process Explorer, I don't see any difference in the permissions on the values and handles to windowstation/desktop by the process opened via my program vs opened normally. Maybe that's completely irrelevant.

I also cannot use CreateProcessWithLogonW function because it must work when run from the SYSTEM account - that function as well as the "runas" program that comes with Windows don't work under SYSTEM.

Funnily enough, I can't use my current method to open processes unless I'm running it under the SYSTEM account, as "a required privilege is not held by the client", so I can't compare the windows created when starting my program under my account vs the SYSTEM account...

404
  • 8,022
  • 2
  • 27
  • 47
  • Are you passing |envblock|? This looks a lot like the code I use with success. Differences being (maybe): I always pass an environment block created with CreateEnvironmentBlock() and the user token in my case is from WTSQueryUserToken(). – NuSkooler Nov 21 '14 at 23:14
  • @NuSkooler If the call to CreateEnvironmentBlock() was successful then I pass the environment block. And the call is successful as the program informs me if not, and I checked the process environment with Process Explorer and the user's environment was loaded. – 404 Nov 22 '14 at 07:50
  • 1
    @NuSkooler: WTSQueryUserToken will give you a token that includes the logon SID for the target session, so your child process will already have all the necessary permissions to the window station and desktop. That's why it's working for you but not for the OP. – Harry Johnston Nov 22 '14 at 22:22

1 Answers1

6

The default DACL for window stations and desktops grant full access to the logon SID (which is unique to the current logon session) rather than to the user's SID. (The user's SID also appears in the DACL for the window station but has only limited permissions. It does not appear in the desktop DACL.)

The call to LogonUser generates a new session (and associated logon SID) rather than reusing the existing one, so your process does not have access to the desktop, and only has minimal access to the window station. (Actually I'm slightly puzzled as to how the process manages to run at all; when I tried to reproduce your results the process exited immediately with exit code 0xC0000142, as expected.)

The second piece of code in this answer shows how to change the DACL on the window station and desktop to allow the process to run properly. (This may not be the best solution, however, depending on your specific goals.)

Community
  • 1
  • 1
Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
  • Adding permissions to the window station and desktop fixed it, thank you very much. Re: processes exiting immediately with code 0xC0000142, I am in fact experiencing that as well, if the user whose credentials I pass to my program is not a member of the administrators group. If it is a member, the process starts successfully. And I am still experiencing this behaviour after having made the changes to show the GUI successfully. Still troubleshooting... – 404 Nov 22 '14 at 13:22
  • I guess the code in the linked answer was only ever tested for administrative users, you probably just need to adjust one or both of the permissions masks. I've edited my answer to include the change I recommend trying first. Please let me know whether that works, if so I'll edit the other answer accordingly. – Harry Johnston Nov 22 '14 at 22:19
  • I can confirm adding `READ_CONTROL` as well as `WINSTA_ALL_ACCESS` to the access permissions for the window station has resolved it: processes created under non-admin accounts start successfully. Massive thanks! – 404 Nov 23 '14 at 12:58
  • @404 Any chance to get a running code example with CreateProcessAsUser and WINSTA_ALL_ACCESS? I stuck the same issue and get it not to work with the information and the link from, Harry Johnston. – N-iceman Jan 09 '23 at 09:44