How to prevent an app from being killed in task manager?

此生再无相见时 提交于 2019-12-20 09:25:01

问题


I'm working on a parental control app (written in WPF) and would like to disallow anybody (including administrator) to kill my process. A while back, I found the following code online and it almost works perfectly, except that it doesn't work sometimes.

static void SetAcl()
{
    var sd = new RawSecurityDescriptor(ControlFlags.None, new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null), null, null, new RawAcl(2, 0));
    sd.SetFlags(ControlFlags.DiscretionaryAclPresent | ControlFlags.DiscretionaryAclDefaulted);
    var rawSd = new byte[sd.BinaryLength];

    sd.GetBinaryForm(rawSd, 0);
    if (!Win32.SetKernelObjectSecurity(Process.GetCurrentProcess().Handle, SecurityInfos.DiscretionaryAcl, rawSd))
        throw new Win32Exception();
}

In Win7, if the app is started by the logged in user, even the admin cannot kill the process (access denied). However, if you switch to another user account (admin or standard user), then check "Show processes for all users", then you kill the process without a problem. Can anybody give me a hint why and how to fix it?

EDIT:
I understand some people are upset by this question, but here is my dilemma. This is a parental control I wrote primarily for my own use. The main feature is that I want to monitor and limit my kids' on games (not simply turn off all games). I could assign kids a standard user account and they cannot kill the process. However, some games (e.g. Mabinogi) require admin right to be playable. So, I had to type in my admin password each time, which is annoying.

By the way, I'm not sure if it's against Stackoverflow's policy, here is my app if you'd like to check it out: https://sites.google.com/site/goppieinc/pc-screen-watcher.

EDIT:
My main point of this post is to ask if somebody could give me a hint why the posted code doesn't always work - e.g. in case you show processes for all users.


回答1:


Some of the comments are right, you're playing a game that might very well be doomed to have no end. However, from what I can tell, setting your process as a critical kernel process appears to give you the clear victory. Any attempt to kill the process will simply BSOD your computer. Code is:

/*
Copyright © 2017 Jesse Nicholson  
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/


using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace MyRedactedNamespace
{
    /// <summary>
    /// Class responsible for exposing undocumented functionality making the host process unkillable.
    /// </summary>
    public static class ProcessProtection
    {
        [DllImport("ntdll.dll", SetLastError = true)]
        private static extern void RtlSetProcessIsCritical(UInt32 v1, UInt32 v2, UInt32 v3);

        /// <summary>
        /// Flag for maintaining the state of protection.
        /// </summary>
        private static volatile bool s_isProtected = false;

        /// <summary>
        /// For synchronizing our current state.
        /// </summary>
        private static ReaderWriterLockSlim s_isProtectedLock = new ReaderWriterLockSlim();

        /// <summary>
        /// Gets whether or not the host process is currently protected.
        /// </summary>
        public static bool IsProtected
        {
            get
            {
                try
                {
                    s_isProtectedLock.EnterReadLock();

                    return s_isProtected;
                }
                finally
                {
                    s_isProtectedLock.ExitReadLock();
                }
            }
        }

        /// <summary>
        /// If not alreay protected, will make the host process a system-critical process so it
        /// cannot be terminated without causing a shutdown of the entire system.
        /// </summary>
        public static void Protect()
        {
            try
            {
                s_isProtectedLock.EnterWriteLock();

                if(!s_isProtected)
                {
                    System.Diagnostics.Process.EnterDebugMode();
                    RtlSetProcessIsCritical(1, 0, 0);
                    s_isProtected = true;
                }
            }
            finally
            {
                s_isProtectedLock.ExitWriteLock();
            }
        }

        /// <summary>
        /// If already protected, will remove protection from the host process, so that it will no
        /// longer be a system-critical process and thus will be able to shut down safely.
        /// </summary>
        public static void Unprotect()
        {
            try
            {
                s_isProtectedLock.EnterWriteLock();

                if(s_isProtected)
                {
                    RtlSetProcessIsCritical(0, 0, 0);
                    s_isProtected = false;
                }
            }
            finally
            {
                s_isProtectedLock.ExitWriteLock();
            }
        }
    }
}

The idea here is that you call the Protect() method ASAP, and then call Unprotect() when you're doing a voluntary shutdown of the app.

For a WPF app, you're going to want to hook the SessionEnding event, and this is where you'll call the Unprotect() method, in case someone logs off or shuts down the computer. This absolutely must be the SessionEnding event, and not the SystemEvents.SessionEnded event. Very often by the time the SystemEvents.SessionEnded event is called, your application can be force terminated if you're taking too long to release the protection, leading to a BSOD every time you restart or log off. If you use the SessionEnding event, you avoid this problem. Another interesting fact about that event is that you're able to, to some degree, contest the logoff or shutdown. Also you'll obviously want to call Unprotect() inside the Application.Exit event handler.

Ensure that your application is stable before deploying this mechanism, because a crash would also BSOD your computer if the process is protected.

As a note for all of the people attacking you for taking these measures, please ignore them. It doesn't matter if someone could potentially use this code to do something malicious, that's a poor excuse to stop perfectly legitimate research for a perfectly legitimate cause. In my case I have developed this as part of my own application, because adults (administrators) don't want to be able to stop my process by killing it. They explicitly desire this functionality, because it prevents themselves from being able to bypass what the software was designed to do.




回答2:


Make it so that the WPF side is just a client. The "server" in this case must be a Windows Service. Then set the Service to start automatically (this last part requires admin privileges). Bonus if it runs as a network admin.

If the service's process is killed, Windows starts it again immediately. And then no matter what users try, they can't really stop your program's logic unless they have admin powers and stop the service themselves. Use the WPF GUI just for configuration.




回答3:


The system account is higher (at least in case of OS) than administrator. The system account and admin account have the same file privileges, but they have different functions. The system account is used by the operating system and by services that run under Windows. There are many services and processes within Windows that need the capability to log on internally (for example during a Windows installation). The system account was designed for that purpose; it is an internal account, does not show up in User Manager, cannot be added to any groups, and cannot have user rights assigned to it.

So the challenge is how to elevate your application privilege to system account while on course of installation. I am not sure how to elevate your process. But worth reading following post ref 1, ref 2. In addition, even if we assume you managed to get it to system account, you might still face more challenge when it comes to managing your own application even being an exponentially super user.



来源:https://stackoverflow.com/questions/16968581/how-to-prevent-an-app-from-being-killed-in-task-manager

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!