How do I hide a process in Task Manager in C#?

84,746

Solution 1

There is no supported way to accomplish this. The process list can be read at any privilege level. If you were hoping to hide a process from even Administrators, then this is doubly unsupported.

To get this to work, you would need to write a kernel mode rootkit to intercept calls to NtQuerySystemInformation so that the SystemProcessInformation info class fails to list your hidden process.

Intercepting system calls is very difficult to do safely, and the 64 bit Windows kernels go out of their way to prevent this from being possible: trying to modify the syscall table results in an instant blue screen. It's going to be very difficult on those platforms

Here is an example of a rootkit that tries to do something similar (and has several serious problems).

Solution 2

Don't try to stop it from being killed - you're not going to manage it. Instead, make it regularly call home to a webservice. When the webservice notices a client "going silent" it can ping the machine to see if it's just a reboot issue, and send an email to a manager (or whoever) to discipline whoever has killed the process.

Solution 3

If you want to prevent users from killing the process from task manager, you can just use a security descriptor on the process to deny terminate access to everyone. Administrators technically can still kill the process by taking ownership of the process and resetting the DACL, but there is no interface to do either of these things from Task Manager. Process Explorer may have an interface to though.

When your process starts, use SetKernelObjectSecurity with DACL_SECURITY_INFORMATION using the current process handle. Set a DACL with zero ACLs. This will deny all access to everyone, including those trying to end your process with task manager.

Here is an example that also changes the process's owner:

SECURITY_DESCRIPTOR sd;
ACL dacl;
SID_IDENTIFIER_AUTHORITY ntauth = SECURITY_NT_AUTHORITY;
PSID owner;

assert(InitializeAcl(&dacl, sizeof dacl, ACL_REVISION));

assert(AllocateAndInitializeSid(&ntauth, 1, SECURITY_LOCAL_SYSTEM_RID, 0,0,0,0,0,0,0, &owner));

assert(InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION));

assert(SetSecurityDescriptorDacl(&sd, TRUE, &dacl, FALSE));

assert(SetSecurityDescriptorOwner(&sd, owner, FALSE));

assert(SetKernelObjectSecurity(GetCurrentProcess(), DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION, &sd));

assert(FreeSid(owner) == NULL);

Unfortunately, it doesn't seem to be effective. I can still close the process (although not as a limited user). Perhaps Task Manager is taking ownership or invoking some other privilege to kill the process? I seem to remember this working in previous versions of Windows (I was testing 2003), but I could be mistaken.

Solution 4

I hope that you would not be able to.

Update: given the scenario, I think that you will probably be best off running it under a different admin account. That may help alert people to the fact that they should not kill the process.

Solution 5

Alternatively, you could write a small "checker" utility that checks if the app is running, if it isn't it automatically starts it. Then add code to the app to check for the "checker" utility that does the same. This way if one is terminated, then the other starts it back up. I've seem virus's do this, and it seems to work pretty effectively.

Share:
84,746
jpoday
Author by

jpoday

Gulzar Nazim - A programmer..

Updated on July 18, 2022

Comments

  • jpoday
    jpoday almost 2 years

    I have a requirement to hide a process in Task Manager. It is for Intranet scenario. So, everything is legitimate. :)

    Please feel free to share any code you have (preferably in C#) or any other techniques or any issues in going with this route.

    Update1: Most of the users have admin privileges in order to run some legacy apps. So, one of the suggestion was to hide it in task manager. If there are other approaches to prevent users from killing the process, that would be great.

    Update2: Removing the reference to rootkit. Somehow made this post look negative.

  • Joel Coehoorn
    Joel Coehoorn over 15 years
    I hate to say it, but since users have admin privileges disguising the process is probably his best bet. Be wary, though: anti-virus software may see this as malicious behavior and just block the program.
  • jpoday
    jpoday over 15 years
    The process is in place to educate users. I have to cover this possibility from a technical angle.
  • jpoday
    jpoday over 15 years
    yeah. its possible. wanted to avoid the cpu cycles for all that checking.
  • ochameau
    ochameau over 15 years
    I've tried to do this in a sample app, but it didn't seem to have any effect (although all of the calls succeeded). I hate to say it, but can you link to some code that does this?
  • jpoday
    jpoday over 15 years
    I was about to ask the same question. Thanks Stephen.
  • Zack
    Zack over 14 years
    +100, I initially was looking to do what the original author wanted to do, but this sounds like an excellent idea.
  • Oliver
    Oliver over 11 years
    And what about tasklist.exe, taskkill.exe´ or ProcessMonitor`? So simply preventing the TaskManager seems not being a good way of preventing closing a process.
  • Cacoon
    Cacoon over 11 years
    You could always use your application to kill those aswell.
  • quantum
    quantum about 11 years
    If you use assert() the code will fail when NDEBUG is defined (that macro is defined to nothing when that is defined). assert() doesn't replace error checking.
  • Chris Smith
    Chris Smith about 11 years
    @xiaomao - I supplied a code snippet to illustrate usage of the relevant APIs. There are many different error handling strategies possible, putting in something more complicated would have obfuscated the code. assert() makes my meaning plain, which was the point; it wasn't meant to be pasted into an arbitrary codebase with no understanding. Besides, you can certainly use headers that enforce assert() in all builds.
  • Nate Zaugg
    Nate Zaugg almost 9 years
    When you end a process, atexit is not called (verified via quick experiment)