web-dev-qa-db-ja.com

C#のタスクマネージャーでプロセスを非表示にするにはどうすればよいですか?

タスクマネージャーでプロセスを非表示にする必要があります。イントラネットシナリオ用です。だから、すべてが合法です。 :)

所有しているコード(C#が望ましい)、その他の手法、またはこのルートを使用する際の問題をお気軽に共有してください。

pdate1:ほとんどのユーザーは、一部のレガシーアプリを実行するための管理者権限を持っています。そのため、提案の1つはタスクマネージャで非表示にすることでした。ユーザーがプロセスを強制終了できないようにする他の方法がある場合、それは素晴らしいことです。

pdate2:ルートキットへの参照を削除しています。どういうわけか、この投稿は否定的に見えました。

33
Gulzar Nazim

これを達成するためのサポートされた方法はありません。プロセスリストは、任意の特権レベルで読み取ることができます。管理者でさえプロセスを隠したい場合、これは二重にサポートされていません。

これを機能させるには、カーネルモードルートキットを作成して NtQuerySystemInformation への呼び出しをインターセプトし、SystemProcessInformation情報クラスが非表示プロセスのリストに失敗するようにする必要があります。

システムコールのインターセプトは安全に行うのが非常に難しく、64ビットのWindowsカーネルは 邪魔にならない を実行して、これができないようにします。syscallテーブルを変更しようとすると、インスタントブルースクリーンが表示されます。これらのプラットフォームでは非常に困難になります

ここ は、似たようなことをしようとする(そしていくつかの深刻な問題がある)ルートキットの例です。

45
Chris Smith

殺されないようにしようとしないでください-あなたはそれを管理するつもりはありません。代わりに、定期的にWebサービスのホームを呼び出します。 Webサービスは、クライアントが「サイレント状態になっている」ことに気付いた場合、マシンをpingしてリブートの問題かどうかを確認し、マネージャー(またはだれでも)にメールを送信してプロセスを強制終了した人を懲戒させます。

70
Jon Skeet

ユーザーがタスクマネージャーからプロセスを強制終了できないようにする場合は、プロセスでセキュリティ記述子を使用して、すべてのユーザーへの終了アクセスを拒否できます。管理者は、技術的にはプロセスの所有権を取得してDACLをリセットすることでプロセスを強制終了できますが、タスクマネージャーからこれらのいずれかを実行するためのインターフェイスはありません。 プロセスエクスプローラー にもインターフェイスがあります。

プロセスが開始されたら、現在のプロセスハンドルを使用して、 SetKernelObjectSecurity with DACL_SECURITY_INFORMATIONを使用します。 DACLにゼロのACLを設定します。これにより、タスクマネージャーでプロセスを終了しようとしているユーザーを含む、すべてのユーザーへのすべてのアクセスが拒否されます。

プロセスの所有者も変更する例を次に示します。

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);

残念ながら、効果的ではないようです。プロセスを閉じることはできます(ただし、制限付きユーザーとしてではありません)。おそらく、タスクマネージャーが所有権を取得している、またはプロセスを強制終了するために他の特権を呼び出しているのでしょうか?以前のバージョンのWindows(2003年のテスト中)でこれが機能していることを覚えているようですが、間違えられる可能性があります。

18
Chris Smith

あなたができないことを願っています。

更新:シナリオを考えると、おそらく別の管理者アカウントで実行するのが最善だと思います。これは、プロセスを強制終了してはならないという事実を人々に警告するのに役立ちます。

10
Marcin

または、アプリが実行されているかどうかを確認する小さな「チェッカー」ユーティリティを作成し、そうでない場合は自動的に起動します。次に、アプリにコードを追加して、同じことを行う「チェッカー」ユーティリティをチェックします。このように、一方が終了すると、もう一方がバックアップを開始します。私はウイルスがこれをしているようで、かなり効果的に機能しているようです。

6

ドライバーの作成-ObRegisterCallbacksを使用して、プロセスオブジェクトアクセス通知を登録できます。 DesiredAccessに、プロセスの終了やプロセスメモリへの書き込みなど、好ましくないアクセス権が含まれている場合は、STATUS_ACCESS_DENIEDを返します。

http://msdn.Microsoft.com/en-us/library/windows/hardware/ff558692(v = vs.85).aspx

4
Uriel G.

プロセスを隠すだけで完全に隠す必要がない場合は、winlogon.exeまたはsvchost.exeに名前を変更すると、ユーザーによって無視される可能性があります。しかし、Sergioが述べたように、それはあいまいさによるセキュリティであり、理由には悪い評判があります。

ユーザーが適切な特権を持っている場合、ユーザーがプロセスを強制終了できないようにすることは別の困難です。私が知っている唯一の方法は、互いに監視し、強制終了された監視対象プロセスを再起動する複数のプロセスを持つことです。繰り返しますが、これは日陰の道を進んでいます。

4
Ben Hoffstein

なぜこれがまだ提案されていないのか定かではありませんが、このサイトでの私の最初の答えはここにあります。ユーザーがプロセスを強制終了できないようにする代わりに。 (ルートキットのフックが必要です。)レジストリインプットでのタスクマネージャーの使用を単に無効にすることができます。

public static void ToggleTaskManager(bool toggle)
{
    Microsoft.Win32.RegistryKey HKCU = Microsoft.Win32.Registry.LocalMachine;
    Microsoft.Win32.RegistryKey key = HKCU.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Policies\System");
    key.SetValue("DisableTaskMgr", toggle ? 0 : 1, Microsoft.Win32.RegistryValueKind.DWord);
}
3
Cacoon

これを行う簡単な方法やサポートされている方法はありません。それを行うためのルートキットを作成した場合でも、その穴を塞ぐために行われた将来の更新によって非常に簡単に破損する可能性があります。それがあなたがやりたいことかどうかを再検討します。

3
StubbornMule

上記の人々が言っ​​たように、最善の方法は2つのタスク、お互いを監視することです。CPUを無駄にしたくないことを理解しています。

フックの設定方法については完全にはわかりませんが、CPUを浪費するwhileループは使用しません。

3
eitama

サービスの作成を見ましたか?このように、サービスはローカルシステムとして実行され、アプリケーションはユーザーのコンテキストで実行されます。サービスは、必要に応じて処理が確実に行われ、アプリケーションはこのサービスへの単なるインターフェイスになります。アプリケーションを強制終了すると、ユーザーには通知やシステムトレイアイコンなどが表示されなくなりますが、サービスは引き続き機能します。

2
Rick

多くの人はそれを行う方法を知っているかもしれませんが、ここには投稿しません。悪意のあるコードをインターネットに投稿することは非常に危険です。あなたが危険にさらされているかもしれないことを誰が知っています。コンピューターエンジニアに問い合わせてください。ただし、プログラムの構造を説明します。

プログラムのdllをExplorer.exeに挿入するだけです。

プロセスはプログラムとして実行されているのではなく、プログラム(Explorer.exe)で実行されているため、表示されません。ユーザーは、どんな種類のタスクマネージャーを使用しても、プロセスを見ることができません。

2
ABCDWHAT

@Chris Smithの回答を見たので、C#に変換することにしました。

以下に、単純なWinformアプリケーションの here から取ったコードを示します。
C#バリエーション:

   using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Security.AccessControl;
    using System.Security.Principal;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;

namespace Hide2
{
    public partial class Form1 : Form
    {
        [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);
        }

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool SetKernelObjectSecurity(IntPtr Handle, int securityInformation, [In] byte[] pSecurityDescriptor);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetCurrentProcess();

        [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 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();
        }

        public Form1()
        {
            InitializeComponent();

            // Get the current process handle
            IntPtr hProcess = GetCurrentProcess();
            // 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);
        }
    }
}

制限付きユーザーとして実行した後、管理者としてのみタスクマネージャーから削除することはできません。
Xボタンを残して、管理者なしで閉じることができるようにしましたが、削除することもできます。

結果:

enter image description here

Powershellバリエーション:

$source = @"
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Security.Principal;

namespace Hide2
{
    public class myForm
    {
        [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);
        }

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool SetKernelObjectSecurity(IntPtr Handle, int securityInformation, [In] byte[] pSecurityDescriptor);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetCurrentProcess();

        [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 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();
        }

        public static void ProtectMyProcess()
        {
            // Get the current process handle
            IntPtr hProcess = GetCurrentProcess();
            // 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);

        }
    }
}
"@

Add-Type -TypeDefinition $Source -Language CSharp  

[ScriptBlock]$scriptNewForm = {
    Add-Type -AssemblyName System.Windows.Forms

    $Form = New-Object system.Windows.Forms.Form
    $Form.Text = "PowerShell form"
    $Form.TopMost = $true
    $Form.Width = 303
    $Form.Height = 274

    [void]$Form.ShowDialog()
    $Form.Dispose()
}



$SleepTimer = 200
$MaxResultTime = 120
$MaxThreads = 3

$ISS = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
$RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads, $ISS, $Host)
$RunspacePool.Open()

$Jobs = @()

$PowershellThread = [powershell]::Create().AddScript($scriptNewForm)
$PowershellThread.RunspacePool = $RunspacePool
$Handle = $PowershellThread.BeginInvoke()
$Job = "" | Select-Object Handle, Thread, object
$Job.Handle = $Handle
$Job.Thread = $PowershellThread
$Job.Object = $computer
$Jobs += $Job

[Hide2.myForm]::ProtectMyProcess()

<#
ForEach ($Job in $Jobs){
    $Job.Thread.EndInvoke($Job.Handle)
    $Job.Thread.Dispose()
    $Job.Thread = $Null
    $Job.Handle = $Null
}
#>
1
E235

プロセスを強制終了しないようにユーザーに要求するだけですか?同じ会社の従業員から明らかに幼稚な行動のために、あなたはそれをするのにどれくらいの時間を費やすでしょう。

1
pmlarocque

私はこの質問が古いことを知っていますが、少し前に、ここにはないニースの情報を含む重複した質問に答えたので、私はそれにリンクしたいと思いました。 重複した質問への私の答えを参照してください。 また、あなたの本当の目標がユーザーがプロセスを殺すのを止めることである場合、私が知っていることは非常に簡単に機能していましたが、それは少しハック的でありませんこれがまだ機能するかどうかを知るには、単にアプリケーションにlsass.exeという名前を付けるだけで、タスクマネージャーは管理者ユーザーでさえプロセスを閉じることを許可しません。この方法では、どのユーザーがプロセスを開始したか、または実行可能ファイルがファイルシステムのどこにあるかは関係ありません。Windowsは、プロセスの名前がthisであるかどうかを確認し、終了を許可しないようです。

更新:Windows 7でlsass.exeトリックを実行しようとしましたが、修正されているようですが、Windows XPおよびXP以降のバージョンの以前のサービスパックでも動作する可能性があります。この記事の執筆時点ではこれは機能していませんが、とにかく面白い事実として含めると思いました。

0
MitchellKrenz

プロセスが永続的に強制終了されるのを止めるには、プロセスが最初に行うことは、 'atexit()'を呼び出し、atexit()関数にプロセスを開始させることです。

0
user3629249