Prevent task manager from killing service process as admin

I'm looking for a way to prevent an administrator from terminating a service running in its own process space as SYSTEM. Perhaps by removing a permission so that OpenProcess fails when requesting PROCESS_TERMINATE permission? I haven't debugged taskmgr yet to determine how exactly it kills processes, but hopefully someone has an idea of how to block admins from terminating a service process.

I'm using VC++ 6, WinXP+.
LVL 4
jimstarAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

peprCommented:
When the administrator is not capable to decide what process should or should not be killed then he or she should not be the administrator. In other words, who will administer such system that can be out of control?

The solution in your case may be not to give the user administrator rights.
0
SeanDurkinCommented:
It probably uses the TerminateProcess() function to terminate processes using the "End Process" button, so the way I'd go about doing this would be to inject a DLL into Windows Task Manager and hook TerminateProcess() causing it to fail on whatever process you wish.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jkrCommented:
The only way is to disable the 'SeDebugName' privilege, yet thathas to be done *before* the task manager is launched:

BOOL DisablePrivilege(PCSTR name)
{
    TOKEN_PRIVILEGES priv = {1, {0, 0, SE_PRIVILEGE_REMOVED}};
    LookupPrivilegeValue(0, name, &priv.Privileges[0].Luid);

    HANDLE hToken;
    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);

    AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof priv, 0, 0);
    BOOL rv = GetLastError() == ERROR_SUCCESS;

    CloseHandle(hToken);
    return rv;
}

However, that privilege - though it is granted to administrators by default - usually is disabled anyway, so you should not encounter a problem here in the 1st place.
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

jimstarAuthor Commented:
pepr,

Thanks for the suggestion. For purposes of this question, I'm trying to figure out how, at a lower level, to prevent an administrator from being able to terminate the process via taskmgr. I'm aware that ultimately an admin can always figure out some way to get around the barriers that I implement, such as enabling privileges, overwriting memory, etc, but I'm only concerned with the taskmgr at this point, not the other possibilities. This makes it quite a bit easier.

SeanDurkin,

Thanks for the suggestion. While that would most definitely work, I'm trying to figure out the lowest-footprint solution. If it is possible to remove a neccessary privilege so that the action fails, that eliminates the need to have code loaded into each process in the system, and would be much cleaner than DLL injection. However, I may come back to this as the best solution after I investigate the other options.

jkr,

The fact that I can go in and kill MyService.exe process running as SYSTEM, from my interactive admin login, means that somehow either the process DACL grants Administrators permission to system processes, or else taskmgr requests those permissions, as you allude to in your response above. I went ahead and debugged taskmgr.exe, and discovered that it performs the following actions when a user clicks End Process:

1. It locates the selected process' PID in the process array.
2. Calls IsSystemProcess, which I suspect checks if the System process is selected (the process name, I suspect, not the process owner - though it really doesn't matter).
3. Calls CPrivilegeEnable, which enables SeDebugPrivilege for the EffectiveToken.
4. Calls kernel32 ! TerminateProcess.

So, the means by which it terminates the process is TerminateProcess(), and the granting of SeDebugPrivilege. That pretty much says it all - SeDebugPrivilege allows it to bypass the DACL-checking on an object, so that's the master key that needs to be withheld.

Expanding on this privilege issue, I'm thinking about a few options to explore:

1. Remove the privilege from the administrator's token (which would require creating a new, restricted token, and somehow swapping that for the user's primary token - not really sure how to do this at the moment).  I think malware does this to prevent the admin from running malware-removal apps. Also, I'm unsure if a process token actually has SeDebugPrivilege rights, or if it obtains those from the user account that owns the process (thus, removing it from the owning  user would immediately prevent the process from having that right). Either way, removing this on-the-fly would be messy I think (?).

2. Block the ability for administrators to enable SeDebugPrivilege by intercepting the call and failing. Similar to blocking/intercepting TerminateProcess() api.

3. Removing the Administrators group from the local security policy rights assignment for Debug Processes. This would require a logoff/logon to make it effective for the logged-on-user. Because it's not instantaneous, I don't really like this option.

I'm going to play around with this some more, but at the moment API interception for TerminateProcess seems like the best bet. Unless, of course, I can find a good way to block the termination via privilege management. But it's not looking promising.
0
jimstarAuthor Commented:
>> Also, I'm unsure if a process token actually has SeDebugPrivilege rights,
>> or if it obtains those from the user account that owns the process

If the process itself has the privilege assignments, then I could poll the system process list (or watch for process creations) and then create a restricted token from taskmgr.exe's primary token, removing the SeDebugPrivilege, and then somehow swapping in the new, restricted token. Because I'm only concerned about taskmgr.exe, this may be a cleaner solution...

If the privileges however are derived from the user's token whenever they are checked, then this would not work as it would affect all processes, not just taskmgr.exe. I'll have to read up on how permissions work in this regard to determine if I should pursue this angle.
0
jimstarAuthor Commented:
At first glance, it appears that a process token copies all permissions that the owning user has at creation time, and then there is no relationship between the two tokens as far as conferring rights are concerned. Thus, I'd be able to create a restricted process token whenever I see taskmgr.exe open, and remove SeDebugPrivilege from this list, essentially causing the AdjustTokenPrivileges to fail as if a normal user had created the task manager process.

Only issue may be the lag time in adjusting the process token... assuming I can recognize a proc creation and adjust the token within 500-1000ms, which seems reasonable, then this may work.
0
jkrCommented:
>> Also, I'm unsure if a process token actually has SeDebugPrivilege rights,
>> or if it obtains those from the user account that owns the process

The latter is the case, or a mix of both. I e.g. launch my task manager via a launcher that enblesthis privilege and starts the process, so the settings are inherited and I canc onveniently kill services. The process topen is what it is all about.

I was entertaining the idea to manipulate this token, yet I did not follow that idea, since an admin process can also change the token to regain access, thus I'll sum that up as: You can, but there's no bullet proof solution. To some extent, you won't be able to prevent the killing of services, you can just make it harder.
0
jimstarAuthor Commented:
In my particular case, it is safe to assume that no custom code is on the computer (just Windows default applications). When I investigated, however, I discovered that you cannot replace a process' primary token. In Server 2003 and later, you can actually remove privileges from an existing token, but this won't work for me as I need XP compatibility. Another option is to have each thread in the target proc impersonate the restricted token with SeDebug removed, essentially getting the desired reduction in privilege. This is messy, and also requires additional messing around with the token to allow impersonation. Of course, if the target app called RevertToSelf, it would gain full access again - though again in my case, because we're assuming that only Windows-default apps are installed/available, this would only occur if taskmgr itself called Revert which would be easy to check (and I'm guessing it doesn't happen).

Now that I've fully explored (I think) the privilege option, I'll probably go the route of CBT-style hook injection and overwrite the IAT entry for TerminateProcess within taskmgr.exe. I'll update the thread once I've done that.
0
jkrCommented:
Stupid remark: Why don't you launch your processes to run under a non-privileged account that cannot kill services in teh 1st place?
0
jimstarAuthor Commented:
The issue is that task manager gets started by winlogon.exe, so I cannot tell it to create that process as a non-privileged account. Of course, this issue wouldn't be an issue if interactive users always ran under a non-privileged account except for true admins. But, as you know, this isn't always the case so I need to do what I can to account for the inexperienced customer.
0
jkrCommented:
>>The issue is that task manager gets started by winlogon.exe

Err, no, that process is started only if you want it to (e.g. by adding it to any autostart means or launching it manually. If you want an easy solution, revoke the access rights:

cacls.exe %SystemRoot%\system32\taskmgr.exe /E /R Everyone
0
jimstarAuthor Commented:
Ah, I see what you're saying. The problem is that completely preventing taskmgr from running is fairly extreme... users and admins need to be able to kill off their own misbehaving apps, and I doubt they'd be happy if it was completely disabled. I'm trying to find a balance where they can still access the functionality to manage their own procs via CTRL+ALT+DEL->TaskMgr (which is where winlogon.exe starts it), but at the same time prohibiting them from mucking with my service.

I'm almost finished with intercepting OpenProcess to remove the PROCESS_TERMINATE permission bit whenever it opens my service's PID from within taskmgr.exe, which should cause TerminateProcess to fail by itself with access denied.
0
jkrCommented:
>>The problem is that completely preventing taskmgr from running is fairly
>>extreme...

Not really, depending on the environment. With a 'kiosk' like setup, that would be quite OK. Admins can easily regain access by a hearty

cacls.exe %SystemRoot%\system32\taskmgr.exe /E /G Admonistrator:F

yet that is a limit. One of a few you can impose.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.