svchost.exe详细解析,运行过程
svchost.exe详细解析,运行过程
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的注册表选项,在卸载时也最好删除增加的部分。