Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何防止应用程序在任务管理器中被杀死?_C#_Wpf_Acl_Taskmanager - Fatal编程技术网

C# 如何防止应用程序在任务管理器中被杀死?

C# 如何防止应用程序在任务管理器中被杀死?,c#,wpf,acl,taskmanager,C#,Wpf,Acl,Taskmanager,我正在开发一个家长控制应用程序(用WPF编写),不允许任何人(包括管理员)杀死我的进程。不久前,我在网上发现了下面的代码,它几乎可以完美地工作,只是有时候不工作 static void SetAcl() { var sd = new RawSecurityDescriptor(ControlFlags.None, new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null), null, null, new RawAcl(2,

我正在开发一个家长控制应用程序(用WPF编写),不允许任何人(包括管理员)杀死我的进程。不久前,我在网上发现了下面的代码,它几乎可以完美地工作,只是有时候不工作

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();
}
在Win7中,如果应用程序是由登录用户启动的,则即使管理员也无法终止该进程(访问被拒绝)。但是,如果您切换到另一个用户帐户(管理员或标准用户),然后选中“为所有用户显示进程”,则您可以毫无问题地终止进程。谁能给我一个提示,为什么以及如何修复它

编辑:
我知道有些人对这个问题感到不安,但这是我的困境。这是一个家长控制我写的主要是为了我自己使用。主要特点是我想监控和限制我的孩子玩游戏(而不是简单地关闭所有游戏)。我可以给孩子们分配一个标准的用户帐户,他们不能终止这个进程。但是,有些游戏(如Mabinogi)需要管理员权限才能玩。所以,我每次都必须输入我的管理员密码,这很烦人

顺便说一句,我不确定这是否违反了Stackoverflow的政策,如果您想查看我的应用程序,这里是:

编辑:

我这篇文章的主要目的是问是否有人可以给我一个提示,为什么发布的代码并不总是有效的-例如,如果你为所有用户显示流程。

让WPF端只是一个客户端。这种情况下的“服务器”必须是Windows服务。然后将服务设置为自动启动(最后一部分需要管理员权限)。如果它以网络管理员身份运行,将获得额外奖励


如果该服务的进程被终止,Windows会立即重新启动它。然后,无论用户尝试什么,他们都无法真正停止您的程序逻辑,除非他们拥有管理权限并自行停止服务。仅将WPF GUI用于配置。

系统帐户高于管理员帐户(至少在操作系统中是这样)。系统帐户和管理员帐户具有相同的文件权限,但功能不同。系统帐户由操作系统和在Windows下运行的服务使用。Windows中有许多服务和进程需要能够在内部登录(例如在Windows安装期间)。系统帐户就是为此目的而设计的;它是一个内部帐户,不显示在用户管理器中,不能添加到任何组,也不能为其分配用户权限


因此,面临的挑战是如何在安装过程中将应用程序权限提升到系统帐户。我不知道如何提升您的流程。但下面的帖子值得一读。此外,即使我们假设您成功地将其发送到了系统帐户,在管理自己的应用程序时,即使您是一个指数级超级用户,您也可能会面临更多的挑战。

一些评论是正确的,您正在玩一个可能注定无止境的游戏。然而,据我所知,将您的进程设置为关键内核进程似乎给您带来了明显的胜利。任何试图终止进程的行为都会使您的计算机死机。代码是:

/*
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();
            }
        }
    }
}
/*
版权所有©2017 Jesse Nicholson
此源代码表单受Mozilla Public的条款约束
许可证。2.0. 如果MPL的副本未随此一起分发
文件,您可以在http://mozilla.org/MPL/2.0/.
*/
使用制度;
使用System.Runtime.InteropServices;
使用系统线程;
名称空间MyRedactedNamespace
{
/// 
///类负责公开使主机进程不可修改的未记录功能。
/// 
公共静态类进程保护
{
[DllImport(“ntdll.dll”,SetLastError=true)]
专用静态外部无效RTLSetProcessCritical(UInt32 v1、UInt32 v2、UInt32 v3);
/// 
///保持保护状态的旗帜。
/// 
私有静态易失性bool s_isProtected=false;
/// 
///用于同步当前状态。
/// 
私有静态ReaderWriterLockSlim s_isProtectedLock=new ReaderWriterLockSlim();
/// 
///获取主机进程当前是否受保护。
/// 
公共静电室受到保护
{
得到
{
尝试
{
s_isProtectedLock.enterereadlock();
返回s_受保护;
}
最后
{
s_isProtectedLock.exitredlock();
}
}
}
/// 
///如果不受保护,将使主机进程成为系统关键进程,因此
///无法在不导致整个系统关闭的情况下终止。
/// 
公共静态无效保护()
{
尝试
{
s_isProtectedLock.EnterWriteLock();
如果(!s_受保护)
{
System.Diagnostics.Process.EnterDebugMode();
RtlSetProcessIsCritical(1,0,0);
s_isProtected=真;
}
}
最后
{
s_isProtectedLock.ExitWriteLock();
}
}
/// 
///如果已受保护,则将从主机进程中删除保护,使其不再受保护
///不再是系统关键流程,因此将能够安全关闭。
/// 
公共静态void Unprotect()
{
尝试
{
s_isProtectedLock.EnterWriteLock();
如果(s_受保护)
{
RtlSetProcessIsCritical(0,0,0);
s_isProtected=假;
}
}
最后
{
s_isProtectedLock.ExitWriteLock();
}
}
}
}
<
//Obtaining the process DACL
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool GetKernelObjectSecurity(IntPtr Handle, int securityInformation, [Out] byte[] pSecurityDescriptor, uint nLength, out uint lpnLengthNeeded);
public static RawSecurityDescriptor GetProcessSecurityDescriptor(IntPtr processHandle)
{
    const int DACL_SECURITY_INFORMATION = 0x00000004;
    byte[] psd = new byte[0];
    uint bufSizeNeeded;
    // Call with 0 size to obtain the actual size needed in bufSizeNeeded
    GetKernelObjectSecurity(processHandle, DACL_SECURITY_INFORMATION, psd, 0, out bufSizeNeeded);
    if (bufSizeNeeded < 0 || bufSizeNeeded > short.MaxValue)
        throw new Win32Exception();
    // Allocate the required bytes and obtain the DACL
    if (!GetKernelObjectSecurity(processHandle, DACL_SECURITY_INFORMATION,
    psd = new byte[bufSizeNeeded], bufSizeNeeded, out bufSizeNeeded))
        throw new Win32Exception();
    // Use the RawSecurityDescriptor class from System.Security.AccessControl to parse the bytes:
    return new RawSecurityDescriptor(psd, 0);
}


//Updating the process DACL
[DllImport("advapi32.dll", SetLastError = true)]
static extern bool SetKernelObjectSecurity(IntPtr Handle, int securityInformation, [In] byte[] pSecurityDescriptor);
public static void SetProcessSecurityDescriptor(IntPtr processHandle, RawSecurityDescriptor dacl)
{
    const int DACL_SECURITY_INFORMATION = 0x00000004;
    byte[] rawsd = new byte[dacl.BinaryLength];
    dacl.GetBinaryForm(rawsd, 0);
    if (!SetKernelObjectSecurity(processHandle, DACL_SECURITY_INFORMATION, rawsd))
        throw new Win32Exception();
}


//Getting the current process
[DllImport("kernel32.dll")]
public static extern IntPtr GetCurrentProcess();


//Process access rights
[Flags]
public enum ProcessAccessRights
{
    PROCESS_CREATE_PROCESS = 0x0080, //  Required to create a process.
    PROCESS_CREATE_THREAD = 0x0002, //  Required to create a thread.
    PROCESS_DUP_HANDLE = 0x0040, // Required to duplicate a handle using DuplicateHandle.
    PROCESS_QUERY_INFORMATION = 0x0400, //  Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken, GetExitCodeProcess, GetPriorityClass, and IsProcessInJob).
    PROCESS_QUERY_LIMITED_INFORMATION = 0x1000, //  Required to retrieve certain information about a process (see QueryFullProcessImageName). A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION. Windows Server 2003 and Windows XP/2000:  This access right is not supported.
    PROCESS_SET_INFORMATION = 0x0200, //    Required to set certain information about a process, such as its priority class (see SetPriorityClass).
    PROCESS_SET_QUOTA = 0x0100, //  Required to set memory limits using SetProcessWorkingSetSize.
    PROCESS_SUSPEND_RESUME = 0x0800, // Required to suspend or resume a process.
    PROCESS_TERMINATE = 0x0001, //  Required to terminate a process using TerminateProcess.
    PROCESS_VM_OPERATION = 0x0008, //   Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory).
    PROCESS_VM_READ = 0x0010, //    Required to read memory in a process using ReadProcessMemory.
    PROCESS_VM_WRITE = 0x0020, //   Required to write to memory in a process using WriteProcessMemory.
    DELETE = 0x00010000, // Required to delete the object.
    READ_CONTROL = 0x00020000, //   Required to read information in the security descriptor for the object, not including the information in the SACL. To read or write the SACL, you must request the ACCESS_SYSTEM_SECURITY access right. For more information, see SACL Access Right.
    SYNCHRONIZE = 0x00100000, //    The right to use the object for synchronization. This enables a thread to wait until the object is in the signaled state.
    WRITE_DAC = 0x00040000, //  Required to modify the DACL in the security descriptor for the object.
    WRITE_OWNER = 0x00080000, //    Required to change the owner in the security descriptor for the object.
    STANDARD_RIGHTS_REQUIRED = 0x000f0000,
    PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF),//    All possible access rights for a process object.
}

public Form1()
{
        InitializeComponent();

        //Put it all together to prevent users from killing your service or process
        IntPtr hProcess = GetCurrentProcess(); // Get the current process handle
        // Read the DACL
        var dacl = GetProcessSecurityDescriptor(hProcess);
        // Insert the new ACE
        dacl.DiscretionaryAcl.InsertAce(
        0,
        new CommonAce(
        AceFlags.None,
        AceQualifier.AccessDenied,
        (int)ProcessAccessRights.PROCESS_ALL_ACCESS,
        new SecurityIdentifier(WellKnownSidType.WorldSid, null),
        false,
        null)
        );
        // Save the DACL
        SetProcessSecurityDescriptor(hProcess, dacl);
}