it-swarm.com.de

Wie blende ich einen Prozess im Task-Manager in C # aus?

Ich muss einen Prozess im Task-Manager ausblenden. Es ist für ein Intranetszenario. Alles ist also legitim. :) 

Gerne können Sie Ihren Code (vorzugsweise in C #) oder andere Techniken oder Probleme mit dieser Route teilen.

Update1 : Die meisten Benutzer verfügen über Administratorrechte, um einige ältere Apps auszuführen. Also war einer der Vorschläge, es im Task-Manager zu verbergen. Wenn es andere Ansätze gibt, um zu verhindern, dass Benutzer den Prozess beenden, wäre das großartig.

Update2 : Entfernen des Verweises auf Rootkit. Irgendwie sah dieser Beitrag negativ aus.

32
Gulzar Nazim

Es gibt keine unterstützte Möglichkeit, dies zu erreichen. Die Prozessliste kann auf jeder Berechtigungsstufe gelesen werden. Wenn Sie gehofft haben, einen Prozess auch vor Administratoren zu verbergen, wird dies doppelt nicht unterstützt.

Damit dies funktioniert, müssten Sie ein Kernelmodus-Rootkit schreiben, um Aufrufe von NtQuerySystemInformation abzufangen, damit die SystemProcessInformation-Info-Klasse Ihren verborgenen Prozess nicht auflistet.

Das Abfangen von Systemaufrufen ist sehr schwierig, und die 64-Bit-Windows-Kernel gehen aus dem Weg , um dies zu verhindern: Der Versuch, die Syscall-Tabelle zu ändern, führt zu ein sofortiger blauer Bildschirm. Auf diesen Plattformen wird es sehr schwierig

Hier ist ein Beispiel für ein Rootkit, das versucht, etwas Ähnliches zu tun (und mehrere schwerwiegende Probleme hat).

45
Chris Smith

Versuche nicht zu verhindern, dass es getötet wird - du wirst es nicht schaffen. Lassen Sie es stattdessen regelmäßig zu einem Webservice anrufen. Wenn der Webservice feststellt, dass ein Client stummgeschaltet wird, kann er einen Ping-Test durchführen, um zu sehen, ob es sich nur um einen Neustart handelt, und eine E-Mail an einen Manager (oder an wen auch immer) zu senden, um denjenigen zu disziplinieren, der den Prozess abgebrochen hat.

68
Jon Skeet

Wenn Sie verhindern möchten, dass Benutzer den Prozess vom Task-Manager beenden, können Sie einfach eine Sicherheitsbeschreibung für den Prozess verwenden, um den Zugriff für alle Personen zu sperren. Administratoren können den Prozess technisch immer noch abbrechen, indem sie den Prozess übernehmen und die DACL zurücksetzen. Es gibt jedoch keine Schnittstelle, die diese beiden Aufgaben im Task-Manager ausführt. Process Explorer kann jedoch eine Schnittstelle haben.

Wenn Ihr Prozess startet, verwenden Sie SetKernelObjectSecurity mit DACL_SECURITY_INFORMATION und verwenden Sie den aktuellen Prozess-Handle. Legen Sie eine DACL mit null ACLs fest. Auf diese Weise wird jeder Zugriff verweigert, einschließlich derjenigen, die versuchen, Ihren Prozess mit dem Task-Manager zu beenden.

Hier ist ein Beispiel, das auch den Besitzer des Prozesses ändert:

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

Leider scheint es nicht effektiv zu sein. Ich kann den Prozess immer noch schließen (wenn auch nicht als Benutzer mit eingeschränkten Rechten). Vielleicht übernimmt der Task-Manager den Besitz oder ein anderes Privileg, um den Prozess zu beenden? Ich erinnere mich an diese Funktion in früheren Windows-Versionen (ich habe 2003 getestet), aber ich konnte mich irren.

18
Chris Smith

Ich hoffe, dass Sie das nicht könnten.

Update: In Anbetracht des Szenarios denke ich, dass Sie es wahrscheinlich am besten unter einem anderen Admin-Konto ausführen werden. Dies kann helfen, die Leute darauf aufmerksam zu machen, dass sie den Prozess nicht beenden sollten.

10
Marcin

Alternativ können Sie ein kleines "Checker" -Dienstprogramm schreiben, das überprüft, ob die App ausgeführt wird. Ist dies nicht der Fall, wird sie automatisch gestartet. Fügen Sie der App dann Code hinzu, um nach dem Dienstprogramm "checker" zu suchen, das dasselbe tut. Wenn einer auf diese Weise beendet wird, startet der andere ihn wieder. Ich habe den Eindruck, dass Viren dies tun, und es scheint ziemlich effektiv zu funktionieren.

6

Nicht sicher, warum dies noch nicht vorgeschlagen wurde, aber hier ist meine erste Antwort auf dieser Website . Statt zu verhindern, dass der Benutzer einen Prozess beendet. (Erfordert Rootkit-Hooking.) Sie können den Task-Manager einfach für die Verwendung mit einer Registrierungseingabe deaktivieren.

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);
}
4
Cacoon

Treiber schreiben - Mit ObRegisterCallbacks können Sie eine Benachrichtigung über den Zugriff auf Prozessobjekte registrieren. Geben Sie STATUS_ACCESS_DENIED zurück, wenn DesiredAccess Zugriffsrechte enthält, die Sie nicht mögen, z. B. Prozessbeendigung oder Schreiben in den Prozessspeicher. 

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

4
Uriel G.

Wenn Sie den Prozess lediglich verkleiden und nicht vollständig ausblenden müssen, können Sie ihn in winlogon.exe oder svchost.exe umbenennen, was wahrscheinlich von den Benutzern ignoriert wird. Aber wie Sergio erwähnt hat, ist dies Sicherheit durch Unklarheit und es hat einen schlechten Ruf aus einem bestimmten Grund.

Zu verhindern, dass Benutzer einen Prozess beenden, ist eine weitere Schwierigkeit, wenn sie über die erforderlichen Berechtigungen verfügen. Die einzige Methode, die ich kenne, ist, mehrere Prozesse zu haben, die sich gegenseitig beobachten und jeden beobachteten Prozess neu zu starten, wodurch er beendet wird. Dies ist wieder ein schattiger Pfad.

4
Ben Hoffstein

Es gibt keinen einfachen oder unterstützten Weg, dies zu tun. Selbst wenn Sie dafür ein Rootkit geschrieben haben, könnte dies sehr leicht durch ein zukünftiges Update, das dieses Loch stopfen sollte, beschädigt werden. Ich würde noch einmal prüfen, ob Sie etwas tun wollen.

3
StubbornMule

Wie oben erwähnt, besteht die beste Methode aus zwei Aufgaben, die sich gegenseitig überwachen. Ich verstehe, dass Sie keine CPU verschwenden möchten. Daher ist es am besten, ein Ereignis zwischen den Aufgaben zu erstellen, das beim Schließen ausgelöst wird.

Ich bin nicht ganz sicher, wie man den Hook aufstellt, aber dann benutzt man keine while-Schleife, die CPU verschwendet.

3
eitama

Hast du beim Schreiben eines Dienstes nachgesehen? Auf diese Weise wird der Dienst als lokales System ausgeführt, und die Anwendung wird im Kontext des Benutzers ausgeführt. Der Dienst kann sicherstellen, dass die erforderlichen Schritte ausgeführt werden. Die Anwendung ist lediglich eine Schnittstelle zu diesem Dienst. Das Beenden der Anwendung würde lediglich dazu führen, dass dem Benutzer keine Notizen, das Symbol in der Taskleiste usw. angezeigt werden, der Dienst jedoch seine Aufgabe erfüllt.

2
Rick

Viele Leute wissen vielleicht, wie es geht, aber es wird hier nicht veröffentlicht. Es ist sehr gefährlich, schädlichen Code im Internet zu veröffentlichen. Wer weiß, dass Sie in Gefahr sind. Fragen Sie einen Computeringenieur. Ich gebe Ihnen jedoch die Struktur des Programms.

Fügen Sie einfach die DLL Ihres Programms in Explorer.exe ein.

Ihr Prozess wird nicht nur angezeigt, weil er nicht als Programm ausgeführt wird, sondern in einem Programm (Explorer.exe) ausgeführt wird. Der Benutzer sieht den Prozess nicht, auch wenn er einen Task-Manager verwendet.

2
ABCDWHAT

Ich sah die Antwort von @Chris Smith und entschied mich, sie in C # umzuwandeln. 

Hier ist der Code aus here für eine einfache Winform-Anwendung:
C # -Variation: 

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

Nachdem ich es als eingeschränkten Benutzer ausgeführt habe, kann ich es nicht mehr vom Task-Manager, sondern nur als Administrator beenden.
Ich habe die X-Taste verlassen, um sie ohne Admin schließen zu können, aber es ist auch möglich, sie zu entfernen. 

Das Ergebnis: 

 enter image description here

Powershell-Variante: 

$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

Was ist, wenn Sie den Benutzer bitten, den Prozess nicht zu beenden? Wie viel Zeit verbringen Sie damit, für ein Verhalten, das von Mitarbeitern im selben Unternehmen eindeutig kindisch ist.

1
pmlarocque

Ich weiß, dass diese Frage alt ist, aber ich habe vor einiger Zeit eine doppelte Frage beantwortet, die einige Informationen von Nice enthält, die nicht hier sind. Also dachte ich, ich würde einen Link dazu setzen. Siehe Meine Antwort auf die doppelte Frage. Auch wenn Ihr eigentliches Ziel darin besteht, die Benutzer daran zu hindern, den Prozess abzubrechen, funktionierte das, was ich weiß, sehr leicht, obwohl es ein bisschen hackig ist und ich nicht weiß, ob dies noch funktioniert .exe und der Task-Manager erlauben nicht einmal einem Admin-Benutzer, den Prozess zu schließen. Für diese Methode spielt es keine Rolle, welcher Benutzer den Prozess gestartet hat oder wo sich die ausführbare Datei im Dateisystem befindet. Es scheint, dass Windows nur prüft, ob der Prozess einen Namen hat, und dies nicht zulässt.

Update: Ich habe gerade versucht, den lsass.exe-Trick unter Windows 7 auszuführen, und er scheint behoben worden zu sein. Ich vermute jedoch, dass er immer noch unter Windows XP und möglicherweise sogar den früheren Service Packs der Versionen über XP hinaus funktioniert. Obwohl dies zum Zeitpunkt dieses Schreibens nicht mehr funktioniert, dachte ich, ich würde es trotzdem als eine lustige Tatsache beifügen.

0
MitchellKrenz

wenn der Prozess nicht dauerhaft abgebrochen werden soll, muss der Prozess zunächst 'atexit ()' aufrufen und die Funktion atexit () den Prozess starten

0
user3629249