2008-10-09 93 views
31

我有要求在任務管理器中隱藏進程。這是針對Intranet的場景。所以,一切都是合法的。 :)如何在C#中的任務管理器中隱藏進程?

請隨意分享您擁有的任何代碼(最好使用C#)或任何其他技術或使用此路線的任何問題。

更新1:大多數用戶擁有管理員權限才能運行一些舊版應用程序。所以,其中一個建議是隱藏在任務管理器中。如果還有其他方法可以防止用戶殺死進程,那就太好了。

Update2:刪除對rootkit的引用。不知何故,這篇文章看起來很消極。

+0

它是如何被Intranet上的一個合法的情景? 不要給他們的管理權限... – 2008-10-09 16:20:04

+0

這就是問題所在。大多數用戶擁有管理員權限來支持一些舊版應用程序。 – 2008-10-09 16:22:20

+14

如果用戶具有管理員權限,他們擁有機器,故事結束。 – 2008-10-09 16:34:47

回答

42

有沒有支持的方式來實現這一點。進程列表可以在任何特權級別讀取。如果您希望即使是管理員也隱藏一個進程,那麼這是雙重不受支持的。

爲了使這個工作,你需要編寫一個內核模式rootkit來攔截對NtQuerySystemInformation的調用,以便SystemProcessInformation信息類無法列出你的隱藏進程。

攔截系統調用非常難以安全執行,而64位Windows內核去out of their way以防止這種情況發生:嘗試修改syscall表導致即時藍屏。這將是非常困難的那些平臺上

Here是一個rootkit的嘗試做類似(並有幾個嚴重的問題)的例子。

10

我希望你不能。

更新:考慮到這種情況,我認爲您可能最好在不同的管理帳戶下運行它。這可能有助於提醒人們注意他們不應該殺死這個過程。

+0

我明白你的觀點。 – 2008-10-09 16:27:05

4

如果你只是簡單地僞裝進程而不是完全隱藏進程,你可以將其重命名爲winlogon.exe或svchost.exe,用戶可能會忽略它。但正如塞爾吉奧所說,這是安全的,因爲一個原因,它的名聲很差。

防止用戶殺死進程是另一個困難,如果他們有適當的權限。我知道的唯一方法是讓多個進程相互監視並重新啓動任何被監視的進程並被殺死。再次,這是一個陰暗的道路。

+0

我討厭這麼說,但是由於用戶具有管理員權限來僞裝這個過程可能是他最好的選擇。但請注意:防病毒軟件可能會將其視爲惡意行爲,並阻止該程序。 – 2008-10-09 16:35:50

3

有沒有簡單或支持的方式來做到這一點。即使你編寫了一個rootkit來完成它,那麼未來的更新可能會很容易被打破。我會重新審視這是否是你想要做的事。

64

不要試圖阻止它被殺 - 你不會去管理它。相反,定期打電話給家裏的web服務。當網絡服務通知客戶「保持沉默」時,它可以ping機器以查看是否僅僅是重新啓動問題,並且發送電子郵件給經理(或任何人)以約束殺死流程的人。

18

如果您想阻止用戶從任務管理器中終止進程,您只需在進程上使用安全描述符來拒絕終止對每個人的訪問。管理員在技術上仍然可以通過取得進程的所有權並重置DACL來終止進程,但是沒有任何界面可以從任務管理器執行這些任務。 Process Explorer可能有一個接口。

當你的進程啓動時,使用當前進程句柄使用SetKernelObjectSecurityDACL_SECURITY_INFORMATION。設置具有零ACL的DACL。這將拒絕所有人的訪問,包括那些試圖用任務管理器結束你的進程的人。

下面是一個例子也改變進程的所有者:

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),但我可能會誤解。

6

或者,你可以寫一個小「檢查器」工具,來檢查,如果應用程序正在運行,如果它不是,它會自動啓動它。然後將代碼添加到應用程序以檢查執行相同操作的「檢查器」實用程序。這樣,如果一個人被終止,那麼另一個人開始備份。我似乎病毒做到了這一點,而且它似乎工作得非常有效。

1

你怎麼樣只是要求用戶在不殺死進程?你會花多少時間去做,因爲同一家公司的員工顯然是幼稚的行爲。

3

正如上面提到的,最好的方法是2個任務,互相監視,我知道你不想浪費CPU,所以最好的方法是在任務之間建立一個事件,當一個任務被觸發時關閉。

我不是如何建立掛鉤完全肯定,但你不使用while循環,其不浪費CPU。

2

你看過寫一個服務嗎?這種方式服務作爲本地系統運行,並且應用程序在用戶的上下文中運行,服務可以確保事情仍然按需完成,而應用程序只是該服務的接口。殺死應用程序只會導致用戶看不到任何通知,系統托盤圖標等,但該服務仍在執行其工作。

3

不知道爲什麼,這已處理不當還建議,但我的繼承人在這個網站的第一個答案。而不是阻止用戶殺死一個進程。 (需要Rootkit掛接。) 您可以簡單地禁用任務管理器與註冊表輸入一起使用。

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

許多人可能知道如何去做,但不會在這裏發佈。在互聯網上發佈惡意代碼是非常危險的。誰知道你可能有危險。問一些電腦工程師。儘管如此,我會給你這個程序的結構。

只需將您的程序的DLL注入explorer.exe即可。

你的過程將不只是顯示出來,因爲它沒有運行的程序,但在程序(資源管理器正在運行。可執行程序)。即使他使用任何類型的任務管理器,用戶也不會看到該過程。

0

停止從永久殺死的過程中,有過程做的第一件事就是打電話「的atexit()」,並具有的atexit()函數啓動過程

0

我知道這個問題是舊的,但我前段時間回答了一個重複的問題,其中包含一些不在這裏的好消息,所以我想我會鏈接到它。 See My answer to the duplicate question.另外,如果您的真正目標是阻止用戶殺死進程,那麼我所知道的工作非常容易,儘管它有點駭人,而且我不知道這是否仍然有效,只是簡單地命名您的應用程序lsass。 exe和任務管理器甚至不允許管理員用戶關閉該進程。對於這種方法,哪個用戶啓動進程或者可執行文件駐留在文件系統的哪個位置並不重要,似乎windows只是檢查進程是否被命名,然後不允許它結束。

更新:我只是試圖在Windows 7上執行lsass.exe技巧,它似乎已得到修復,但我的猜測是它仍然可以在Windows XP上運行,甚至可能是xp之外的早期版本的服務包。儘管在寫這篇文章的時候這已經不起作用了,但我仍然認爲我會把它作爲一個有趣的事實加以考慮。

0

我看到@Chris Smith的答案,我決定將其轉換爲C#。

下面是代碼,從here採取一個簡單的WinForm應用程序:
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 
} 
#> 
相關問題