Подтвердить что ты не робот

Как скрыть процесс в диспетчере задач на С#?

У меня есть требование скрыть процесс в диспетчере задач. Это для сценария интрасети. Итак, все законно.:)

Пожалуйста, не стесняйтесь делиться любым кодом, который у вас есть (желательно на С#) или другими методами или любыми проблемами при переходе с этого маршрута.

Update1. Большинство пользователей имеют права администратора для запуска некоторых устаревших приложений. Итак, одно из предложений заключалось в том, чтобы скрыть его в диспетчере задач. Если есть другие подходы, чтобы пользователи не убивали процесс, это было бы здорово.

Update2: удаление ссылки на руткит. Как-то это сообщение выглядело отрицательным.

4b9b3361

Ответ 1

Нет поддерживаемого способа выполнить это. Список процессов можно прочитать на любом уровне привилегий. Если вы надеялись скрыть процесс от даже администраторов, то это вдвойне неподдерживается.

Чтобы это сработало, вам нужно написать руткит режима ядра, чтобы перехватить вызовы на NtQuerySystemInformation, чтобы сбой в классе информации SystemProcessInformation чтобы просмотреть скрытый процесс.

Перехват системных вызовов очень сложно сделать безопасно, а 64-битные ядра Windows идут из своего пути, чтобы это не было возможным: попытка изменить таблицу syscall приведет к синему экрану. Это будет очень сложно на этих платформах.

Здесь приведен пример руткита, который пытается сделать что-то подобное (и имеет несколько серьезных проблем).

Ответ 2

Не пытайтесь остановить его от убийства - вы не справитесь. Вместо этого заставьте его регулярно звонить домой в веб-сервис. Когда веб-служба замечает, что клиент "молчал", он может выполнить ping-машину, чтобы проверить, не является ли она просто перезагрузкой, и отправить электронное письмо менеджеру (или кому бы то ни было), чтобы дисциплинировать того, кто убил процесс.

Ответ 3

Если вы хотите, чтобы пользователи не убивали процесс из диспетчера задач, вы можете просто использовать дескриптор безопасности в процессе, чтобы запретить доступ к любому пользователю. Администраторы технически могут все еще убить процесс, взяв на себя ответственность за процесс и сбросив DACL, но нет интерфейса для выполнения любой из этих задач из диспетчера задач. Process Explorer может иметь интерфейс, хотя.

При запуске процесса используйте SetKernelObjectSecurity с помощью 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), но я мог ошибаться.

Ответ 4

Я надеюсь, что вы не сможете.

Обновление:, учитывая сценарий, я думаю, что вам, вероятно, будет лучше всего запускать его под другой учетной записью администратора. Это может помочь предупредить людей о том, что они не должны убивать процесс.

Ответ 5

В качестве альтернативы вы можете написать небольшую утилиту "checker", которая проверяет, работает ли приложение, если оно не запускается автоматически. Затем добавьте код в приложение, чтобы проверить утилиту "checker", которая делает то же самое. Таким образом, если один из них завершен, тогда другой запускает его обратно. Я считаю, что вирус делает это, и кажется, что он работает довольно эффективно.

Ответ 6

Если вам просто нужно замаскировать процесс и не скрывать его полностью, вы можете переименовать его winlogon.exe или svchost.exe, и он, вероятно, будет игнорироваться пользователями. Но, как сказал Серджио, эта безопасность была скрыта, и по какой-то причине она получила плохую репутацию.

Предотвращение убийства процесса пользователями - еще одна сложность, если у них есть соответствующие привилегии. Единственный метод, который я знаю, - это несколько процессов, которые смотрят друг на друга и перезапускают любой наблюдаемый процесс, который убивается. Опять же, это идет по тенистым путям.

Ответ 7

Для этого нет простого или поддерживаемого способа. Даже если вы написали руткит, чтобы сделать это, это может быть очень легко сломано будущим обновлением, которое было сделано, чтобы подключить это отверстие. Я бы пересмотрел то, что вы хотите сделать.

Ответ 8

Как упоминалось выше, лучшим методом является 2 задачи, контролирующие друг друга, Я понимаю, что вы не хотите тратить процессор, поэтому лучший способ - установить событие между задачами, которые будут запускаться при закрытии.

Я не совсем уверен, как настроить крючок, но тогда вы не используете цикл while, который отбрасывает процессор.

Ответ 9

Записать драйвер. Вы можете использовать ObRegisterCallbacks для регистрации уведомления о доступе к объекту процесса. Верните STATUS_ACCESS_DENIED, когда DesiredAccess содержит права доступа, которые вам не нравятся, например, завершение процесса или запись в память процесса.

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

Ответ 10

Не знаю, почему это еще не было предложено, но вот мой первый ответ на этом сайте. вместо того, чтобы запретить пользователю убивать процесс. (Требуется подключение руткитов.) Вы можете просто отключить диспетчер задач от использования с входом в реестр.

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

Ответ 11

Вы смотрели, как написать услугу? Таким образом, служба работает как локальная система, и приложение запускается в контексте пользователя, и служба может гарантировать, что все еще выполняется по мере необходимости, и приложение является просто интерфейсом к этой службе. Убивание приложения приведет к тому, что пользователь не увидит никаких уведомлений, значков в системном трее и т.д., Но служба все еще выполняет свою работу.

Ответ 12

Многие могут знать, как это сделать, но просто не опубликуйте его здесь. Очень опасно размещать вредоносный код в Интернете. Кто знает, что может оказаться в опасности. Спросите какого-нибудь инженера-вычислителя Я покажу вам структуру программы.

Просто вставьте свою DLL-программу в explorer.exe.

Ваш процесс не будет отображаться только потому, что он не работает как программа, а запускается в программе (explorer.exe). Пользователь просто не увидит этот процесс, даже если он использует любой диспетчер задач.

Ответ 13

Как насчет того, что вы просто попросите пользователя не убивать процесс? Сколько времени вы потратите на это, для поведения, которое явно детски относится к сотрудникам в одной компании.

Ответ 14

чтобы остановить процесс от непрерывного уничтожения, первое, что нужно сделать процессу, это вызвать "atexit()" и запустить функцию atexit() для процесса

Ответ 15

Я знаю, что этот вопрос старый, но я ответил на дублирующий вопрос некоторое время назад, в котором содержится какая-то приятная информация, которая здесь отсутствует, поэтому я подумал, что буду ссылаться на нее. См. Мой ответ на дублированный вопрос. Также, если ваша истинная цель - остановить пользователей от убийства процесса, то то, что я знаю, было очень легко работать, хотя это бит хаки, и я не знаю, работает ли это по-прежнему, просто называть ваше приложение lsass.exe, а диспетчер задач не позволит даже пользователю администратора закрыть этот процесс. для этого метода не имеет значения, какой пользователь запустил этот процесс или где исполняемый файл находится в файловой системе, кажется, что окна просто проверяют, называется ли процесс указанным, а затем не позволяют завершить его.

Обновление: я просто попытался сделать трюк lsass.exe в Windows 7, и он, похоже, исправлен, но я предполагаю, что он все еще работает на windows xp и, возможно, даже на ранних версиях пакетов версии xp. Хотя это уже не работает во время написания этого письма, я думал, что включу его в любом случае как забавный факт.

Ответ 16

Я видел ответ @Chris Smith, и я решил преобразовать его в С#.

Вот код, взятый из здесь, для простого приложения Winform:
Вариант С#:

   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, чтобы закрыть ее без администратора, но также ее можно удалить.

Результат:

введите описание изображения здесь

Вариант 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
}
#>