svchost.exe是什么?
- svchost.exe 是從動態鏈接庫(DLL)中運行的服務的通用主機進程名稱,本身只是作為服務宿主,並不實現任何服務功能,提供條件讓其他服務在這里被啟動,需要svchost.exe啟動的服務以動態鏈接庫形式實現,在安裝這些服務時,把服務的可執行程序指向svchost.exe,啟動這些服務時由svchost.exe調用相應服務的動態鏈接庫來啟動服務。
- svchost.exe文件定位在系統的%systemroot%\system32文件夾下 %systemroot%是系統的環境變量 指的是系統的根目錄
我的svchost.exe文件就在 C:\Windows\System32目錄下
svchost.exe工作過程
- 系統的大部分服務是運行 動態鏈接庫(dll)形式實現的。如果需要使用Svchost來啟動某個DLL形式實現的服務,該DLL的載體Loader指向Svchost,在啟動服務的時候由Svchost調用該服務的DLL來實現啟動的目的。使用Svchost啟動某個服務的DLL文件是由注冊表中的參數來決定的,在需要啟動服務的注冊表項下都有一個“Parameters”子項,其中的“ServiceDll”鍵值表明該服務由哪個DLL文件負責,並且這個DLL文件必須導出一個ServiceMain()函數,為處理服務任務提供支持
在系統啟動的時候,svchost.exe檢查注冊表中的位置來構建需要加載的服務列表。這就會使多個svchost.exe在同一時間運行。一般地,通過在任務管理器,我們可以看到Windows系統中存在多個“svchost”進程。
這些svchost進程提供多種系統服務,如:rpcss服務(remote procedure call)、dmserver服務(logical disk manager)、dhcp服務(dhcp client)等。
以常見的,讓人討厭的windows Update 服務為例子
其中,C:\Windows\System32\svchost.exe-k netsvcs -p 這個路徑當然就是啟動服務的關鍵信息,但是,后邊的這個-k netsvcs參數並不是在告訴svchost.exe啟動哪個服務,而是在告訴你wuauserv是屬於netsvcs這個組,正是由於采用了分組機制,系統中才會有多個svchost.exe進程,每個進程代表一個組,而這個服務的名稱叫wuauserv並不是顯示的Windows Update,哪個服務對應哪個dll,都是保存在注冊表里的,路徑是計算機\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services
就拿上邊的wuauserv服務來說,在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services路徑下有一個wuauserv項,名字和服務名字一樣(也就是說,有多少個服務,這個路徑下就有多少個項,和服務名稱相對應),這個項里里邊又有一個Parameters子項,Parameters子項里有一個名字叫ServiceDll的鍵,它的值就是需要運行的動態鏈接庫文件(dll)的路徑。如圖:
啟動wuauserv服務的運行命令在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\wuauserv ,在項中找到類型為“reg_expand_sz”的鍵“Imagepath”的值為%systemroot%\system32\svchost.exe -k netsvcs -p,這就是wuauserv服務的運行命令,然后在重溫一遍 這個-k netsvcs參數並不是在告訴svchost.exe啟動哪個服務,而而是告訴你wuauserv是屬於netsvcs這個組
這樣一來,svchost.exe根據服務名稱找到相應的鍵值,就找到要啟動的dll了,然后在運行它
如果服務不通過svchost.exe啟動,那么就更簡單,直接在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services路徑下找到和服務名稱一樣的項,項中有一個叫ImagePath的鍵,這個鍵的值就是服務exe文件的路徑和啟動參數。如圖:
接着繼續分析
svchost的分組
要注意的是,並不是啟動一個相關服務就增加一個svchost進程的,而是根據命令參數分組,一般是一組服務就有一個svchost進程(上面提到過的)。也就是說,每個svchost.exe會話可以包含一組服務,可以根據svchost.exe的啟動方式和位置的不同運行不同的服務。 svchost.exe組的鍵值是: HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\svchost 在其中,我們可以找到上面的例子,就是在netsvcs組下的
svchost原理總結
- svchost本身只是作為服務宿主,並不實現任何服務功能,需要svchost啟動的服務以動態鏈接庫形式實現,在安裝這些服務時,把服務的可執行程序指向svchost,啟動這些服務時由svchost調用相應服務的動態鏈接庫來啟動服務。
- 那么svchost如何知道某一服務是由哪個動態鏈接庫負責呢?這不是由服務的可執行程序路徑中的參數部分提供的,而是服務在注冊表中的參數設置的,注冊表中服務下邊有一個Parameters子鍵其中的ServiceDll表明該服務由哪個動態鏈接庫負責。並且所有這些服務動態鏈接庫都必須要導出一個ServiceMain()函數,用來處理服務任務。
例如netsvcs(Windows Update) 在注冊表中的位置是: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\netsvcs,它的參數子鍵Parameters里有這樣一項: "ServiceDll"=REG_EXPAND_SZ:"%SystemRoot%\system32\wuaueng.dll" 當啟動netsvcs服務時,svchost就會調用wuaueng.dll,並且執行其ServiceMain()函數執行具體服務。 既然這些服務是使用共享進程方式由svchost啟動的,為什么系統中會有多個svchost進程呢?微軟把這些服務分為幾組,同組服務共享一個svchost進程,不同組服務使用多個svchost進程,組的區別是由服務的可執行程序后邊的參數決定的。就是這個
svchost的所有組和組內的所有服務都在注冊表的如下位置: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\svchost,我的電腦上組內服務最多的就是 netsvcs,在啟動一個svchost.exe負責的服務時,服務管理器如果遇到可執行程序內容ImagePath已經存在於服務管理器的映象庫中,就不再啟動第2個進程svchost,而是直接啟動服務。這樣就實現了多個服務共享一個svchost進程。
要通過svchost調用來啟動的服務,就一定要在
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost下有該服務名,這可以通過如下方式來實現:
(1) 添加一個新的服務組,在組里添加服務名;
(2) 在現有組里添加服務名;
(3) 直接使用現有服務組里的一個服務名,但本機沒有安裝的該服務;
(4) 修改現有服務組里的現有服務,把它的ServiceDll指向自己。
前兩種可以被正常服務使用,如使用第1種方式,啟動其服務要創建新的svchost進程;第2種方式如果該組服務已經運行,安裝后不能立刻啟動服務,因為svchost啟動后已經把該組信息保存在內存里,並調用API StartServiceCtrlDispatcher() 為該組所有服務注冊了調度處理函數,新增加的服務不能再注冊調度處理函數,需要重啟計算機或者該組的svchost進程。 后兩種可能被后門使用,尤其是最后一種,沒有添加服務,只是改了注冊表里一項設置,從服務管理控制台又看不出來,如果作為后門還是很隱蔽的。比如EventSystem服務,缺省是指向es.dll,如果把ServiceDll改為EventSystem.dll就很難發現。 服務的安裝除了調用CreateService()創建服務之外,還需要設置服務的ServiceDll,如果使用前2種還要設置svchost的注冊表選項,在卸載時也最好刪除增加的部分。