OpenProcess / SetProcessAffinityMask on process started by my service - c++

In my manager.exe, I'm trying to change the CPU usage of my worker.exe, which is started by my service.exe. Service.exe is running under the System Account, while manager.exe is running under the logged in user's account.
When I call OpenProcess in manager.exe with worker.exe's PID, I get NULL for procHandle:
HANDLE procHandle = OpenProcess(PROCESS_SET_INFORMATION, 0, pid);
Using GetLastError() I see that I got an Access Denied error.
Any ways around this? Can I somehow modify worker.exe to grant other processes full control over itself?

You shouldn't have to call OpenProcess.
The service should already have a full-permission handle to the worker from when it called CreateProcessAsUser or CreateProcessWithLogonW. Use DuplicateHandle to make a version of that handle suitable for use by the manager process, and then have the service send that handle to the manager. The service already has a handle to the manager, right? It will need that for DuplicateHandle.
Or have the manager ask the service to change the worker process.

Related

Assigning JobObject to process with non-zero session id launched from a SYSTEM service

I have a Windows SYSTEM service which needs to launch a new process in the context of the logged-in user. Along with this, I need to create a Job for the new process with certain limits.
I am extracting the process token of explorer.exe and duplicating it to create a primary token. I use this token in CreateProcessAsUser to create the new process running in the context of the user with a session id which is non-zero. When I assign the Job to this process, AssignProcessToJobObject function fails with Access denied error. Specifically, I am not able to set JOBOBJECT_BASIC_UI_RESTRICTIONS limits (JOBOBJECT_EXTENDED_LIMIT_INFORMATION works though).
The process is created as suspended and after assigning the job, I am resuming the thread.
When I use the token of the current process (i.e. SYSTEM service with session id 0) instead of explorer.exe, everything works fine.
I am testing this on Windows 10

Calling OpenWindowStation from a service running under a "user" account

My service start an interactive client process with something really similar to this: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379608(v=vs.85).aspx
It works when the service Log On as Local System, and it work if it's running under an Administrator account with the SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME privileges.
My issue is when using a Standard User account OR Local Service, it fails at OpenWindowStation with error code 5 (ACCESS DENIED).
// Get a handle to the interactive window station.
hwinsta = OpenWindowStation(_T("winsta0"), // the interactive window station
FALSE, // handle is not inheritable
READ_CONTROL | WRITE_DAC); // rights to read/write the DACL
Is it possible to call OpenWindowStation from a Standard User account or my service must run under an Administrator account? I tried almost all Local Policies without success
Thanks!
Unfortunately it can't be done, it seems that only an Administrator can open the interactive station.

CreateProcessAsUser creates blank/black window

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:
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...
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.)

Windows : How to protect process from getting killed in C/C++

Is there any "GODLY" method through which i can protect my process from getting killed from:
1>Task manager 2>Command prompt -- forcefully kill
Things i tried : 1. Hooking Open Process and Terminate Process
Result i got: well not much , i could only protect it from task manager but it gets killed through command prompt task kill command
It is not too difficult to modify a process so it cannot be terminated by any other user than an administrator.
Look into:
GetKernelObjectSecurity
SetKernelObjectSecurity
In short: Obtain the security descriptor of the process to be protected, modify its DACL and write it back. Users that you deny access this way get an "Access denied" when trying to kill the process.

Impersonating and CreateProcess

The document states CreateProcess create a process running under the calling process’s security context, not the current impersonating token’s security context. Does this mean the permission for the new process will be the same regardless impersonating or not?
I have the following code that fails with ACCESS_DENIED error:
Process A runs under administrator;
Process A impersonates a normal user “test”;
Process A starts a new process B by calling CreateProcess;
Process B calls OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, ..);
Step 4 fails with ACCESS_DENIED error (5). I checked process B is running under Administrator as process A. Why would it fail when it’s running under the same user context as process A?
As a commenter said, you want CreateProcessAsUser. You might find the following sample code on MSDN helpful, I used it with success a few years ago: http://support.microsoft.com/kb/165194