在 http://yangye.blog.51cto.com/922715/200444这篇文章中我提到过使用脚本结合调用runas命令来给客户端安装exe文件。如果做过测试的人会发现,这个脚本并不是很完美。
其一,当脚本未运行结束时不能被其他进程所打断,否则将会出现输入密码的黑框。会对用户造成干扰,也需要花费一些口舌和用户解释。
其二,runas命令的脚本必然会在其中写出密码部分,造成安全隐患,换句话说只要找到了这个vbs的文件就能找到password。当然你可以使用Windows Script Encoder将其加密成vbe的文件,但这还是不够安全(其实根本谈不上安全),我这里有个网页工具,将你的vbe代码放入试试?代码如下,复制并另存为VBE-Decode.html
- <html>
- <head>
- <META http-equiv=Content-Type content="text/html; charset=utf-8">
- <title>VBscript.Encode Decode</title>
- </head>
- <body>
- <center>
- <table cellPadding=3 bgcolor=#e7e7e7>
- <tr>
- <td bgcolor=#336699>
- <div align=center><font color=#ffffff size=3><strong>VBscript.Encode Decode</strong></font></div></td></tr>
-
- <tr>
- <td align=middle height=80>
- <script language=JScript>
- var STATE_COPY_INPUT = 100
- var STATE_READLEN = 101
- var STATE_DECODE = 102
- var STATE_UNESCAPE = 103
- var pick_encoding = new Array(
- 1, 2, 0, 1, 2, 0, 2, 0, 0, 2, 0, 2, 1, 0, 2, 0,
- 1, 0, 2, 0, 1, 1, 2, 0, 0, 2, 1, 0, 2, 0, 0, 2,
- 1, 1, 0, 2, 0, 2, 0, 1, 0, 1, 1, 2, 0, 1, 0, 2,
- 1, 0, 2, 0, 1, 1, 2, 0, 0, 1, 1, 2, 0, 1, 0, 2
- )
- var rawData = new Array(
- 0x64,0x37,0x69, 0x50,0x7E,0x2C, 0x22,0x5A,0x65, 0x4A,0x45,0x72,
- 0x61,0x3A,0x5B, 0x5E,0x79,0x66, 0x5D,0x59,0x75, 0x5B,0x27,0x4C,
- 0x42,0x76,0x45, 0x60,0x63,0x76, 0x23,0x62,0x2A, 0x65,0x4D,0x43,
- 0x5F,0x51,0x33, 0x7E,0x53,0x42, 0x4F,0x52,0x20, 0x52,0x20,0x63,
- 0x7A,0x26,0x4A, 0x21,0x54,0x5A, 0x46,0x71,0x38, 0x20,0x2B,0x79,
- 0x26,0x66,0x32, 0x63,0x2A,0x57, 0x2A,0x58,0x6C, 0x76,0x7F,0x2B,
- 0x47,0x7B,0x46, 0x25,0x30,0x52, 0x2C,0x31,0x4F, 0x29,0x6C,0x3D,
- 0x69,0x49,0x70, 0x3F,0x3F,0x3F, 0x27,0x78,0x7B, 0x3F,0x3F,0x3F,
- 0x67,0x5F,0x51, 0x3F,0x3F,0x3F, 0x62,0x29,0x7A, 0x41,0x24,0x7E,
- 0x5A,0x2F,0x3B, 0x66,0x39,0x47, 0x32,0x33,0x41, 0x73,0x6F,0x77,
- 0x4D,0x21,0x56, 0x43,0x75,0x5F, 0x71,0x28,0x26, 0x39,0x42,0x78,
- 0x7C,0x46,0x6E, 0x53,0x4A,0x64, 0x48,0x5C,0x74, 0x31,0x48,0x67,
- 0x72,0x36,0x7D, 0x6E,0x4B,0x68, 0x70,0x7D,0x35, 0x49,0x5D,0x22,
- 0x3F,0x6A,0x55, 0x4B,0x50,0x3A, 0x6A,0x69,0x60, 0x2E,0x23,0x6A,
- 0x7F,0x09,0x71, 0x28,0x70,0x6F, 0x35,0x65,0x49, 0x7D,0x74,0x5C,
- 0x24,0x2C,0x5D, 0x2D,0x77,0x27, 0x54,0x44,0x59, 0x37,0x3F,0x25,
- 0x7B,0x6D,0x7C, 0x3D,0x7C,0x23, 0x6C,0x43,0x6D, 0x34,0x38,0x28,
- 0x6D,0x5E,0x31, 0x4E,0x5B,0x39, 0x2B,0x6E,0x7F, 0x30,0x57,0x36,
- 0x6F,0x4C,0x54, 0x74,0x34,0x34, 0x6B,0x72,0x62, 0x4C,0x25,0x4E,
- 0x33,0x56,0x30, 0x56,0x73,0x5E, 0x3A,0x68,0x73, 0x78,0x55,0x09,
- 0x57,0x47,0x4B, 0x77,0x32,0x61, 0x3B,0x35,0x24, 0x44,0x2E,0x4D,
- 0x2F,0x64,0x6B, 0x59,0x4F,0x44, 0x45,0x3B,0x21, 0x5C,0x2D,0x37,
- 0x68,0x41,0x53, 0x36,0x61,0x58, 0x58,0x7A,0x48, 0x79,0x22,0x2E,
- 0x09,0x60,0x50, 0x75,0x6B,0x2D, 0x38,0x4E,0x29, 0x55,0x3D,0x3F
- )
- var transformed = new Array()
- for (var i=0; i<3; i++) transformed[i] = new Array()
- for (var i=31; i<=126; i++) for (var j=0; j<3; j++) transformed[j][rawData[(i-31) * 3 + j]] = (i==31) ? 9 : i
-
- var digits = new Array()
- for (var i=0; i<26; i++)
- {
- digits["A".charCodeAt(0)+i] = i
- digits["a".charCodeAt(0)+i] = i+26
- }
- for (var i=0; i<10; i++) digits["0".charCodeAt(0)+i] = i+52
- digits[0x2b] = 62
- digits[0x2f] = 63
- function unescape(char)
- {
- var escapes = "#&!*$"
- var escaped = "\r\n<>@"
- if (char.charCodeAt(0) > 126) return char
- if (escapes.indexOf(char) != -1) return escaped.substr(escapes.indexOf(char), 1)
- return "?"
- }
-
- function decodeBase64(string)
- {
- var val = 0
- val += (digits[string.substr(0,1).charCodeAt(0)] << 2)
- val += (digits[string.substr(1,1).charCodeAt(0)] >> 4)
- val += (digits[string.substr(1,1).charCodeAt(0)] & 0xf) << 12
- val += ((digits[string.substr(2,1).charCodeAt(0)] >> 2) << 8)
- val += ((digits[string.substr(2,1).charCodeAt(0)] & 0x3) << 22)
- val += (digits[string.substr(3,1).charCodeAt(0)] << 16)
- return val
- }
- function strdec(encodingString)
- {
-
- var marker = "#@~^"
- var stringIndex = 0
- var scriptIndex = -1
- var unEncodingIndex = 0
- var char = null
- var encodingLength = unEncodinglength = 0
- var state = STATE_COPY_INPUT
- var unEncodingString = ""
- var re, arr
-
- while(state)
- {
- switch (state)
- {
- case (STATE_COPY_INPUT) :
- scriptIndex = encodingString.indexOf(marker, stringIndex)
- if (scriptIndex != -1)
- {
- unEncodingString += encodingString.substring(stringIndex, scriptIndex)
- scriptIndex += marker.length
- state = STATE_READLEN
- }
- else
- {
- stringIndexstringIndex = stringIndex==0 ? 0 : stringIndex
- unEncodingString += encodingString.substr(stringIndex, encodingString.length)
- state = 0
- }
- break
-
- case (STATE_READLEN) :
- encodingLength = encodingString.substr(scriptIndex, 6)
- unEncodinglength = decodeBase64(encodingLength)
- scriptIndex += (6 + "==".length)
- state = STATE_DECODE
- break
-
- case (STATE_DECODE) :
- if (!unEncodinglength)
- {
- stringIndex = scriptIndex + "DQgAAA==^#~@".length
- unEncodingIndex = 0
- state = STATE_COPY_INPUT
- break
- }
- char = encodingString.substr(scriptIndex, 1)
- if (char == "@") state = STATE_UNESCAPE
- else
- {
- if (char.charCodeAt(0) < 0xFF)
- {
- unEncodingString += String.fromCharCode(transformed[pick_encoding[unEncodingIndex%64]][char.charCodeAt(0)])
- unEncodingIndex++
- }
- else
- {
- unEncodingString += char
- }
- scriptIndex++
- unEncodinglength--
- break
- }
-
- case STATE_UNESCAPE:
- unEncodingString += unescape(encodingString.substr(++scriptIndex, 1))
- scriptIndex++; unEncodinglength -=2
- unEncodingIndex++
- state = STATE_DECODE
- break
- }
- }
-
- re = new RegExp("(JScript|VBscript).encode", "gmi")
- while(arr = re.exec(unEncodingString)) unEncodingString = RegExp.leftContext + RegExp.$1 + RegExp.rightContext
- return unEncodingString
- }
-
- </script>
-
- <textarea id=encodeHTML rows=20 cols=80></textarea> <br><br>
- <div align=center><button onclick=encodeHTML.innerText=strdec(encodeHTML.innerText)>Decode
- </button></div></td></tr></table></td></tr></table></td></tr></table>
- </body>
- </html>
针对这些不足,特写了此篇续章。
解决此问题最理想的就是最好能够用计算机开机脚本,毕竟是给计算机安装程序,而不是用户。Vbs可以做到将远程的程序复制到本地,但是不能做到开机脚本安装exe程序(未报错)。Bat可以做到调用本地的exe文件安装,但是不能作为开机脚本从远程拷贝文件。最后想出了3套脚本完美解决此问题。
1.用vbs检测客户端版本并复制远程wsusagent程序到本地。
2.用bat进行本地安装exe文件,安装完毕并删除源程序。
3.生成报告。
请按照顺序将三个脚本添加到GPO的开机脚本中,然后下派给客户端计算机。做之前养成先测试的好习惯,并仔细check权限等问题。
1)复制文件代码,复制并另存为AgentCopy.vbs
- On Error Resume Next
- Const WINDOWS = &H24&
- Const OverwriteExisting = True
- Set objShell = CreateObject("Shell.Application")
- Set objFolder = objShell.Namespace(WINDOWS)
- Set objFolderobjFolderItem = objFolder.Self
- strWinPath = objFolderItem.Path
- strDrvPath = Mid(strWinPath, 1, 3)
- strWinLen = Len(strWinPath)
- strNum = strWinLen - 3
- strWinName = Mid(strWinPath, 4, strNum)
- Set objFSO = CreateObject("Scripting.FileSystemObject")
- strFullAgentpath = strDrvPath & "\" & strWinName & "\\system32\\wuaueng.dll"
- strComputer = "."
- Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
- Set colFiles = objWMIService.ExecQuery("SELECT * FROM CIM_DataFile where name = '" & strFullAgentpath & "'")
- For Each objFile in colFiles
- strVer = objFile.Version
- Next
- strVerCur = Mid(strVer, 1, 12)
- strVerNew = "7.2.6001.788"
- If strVerCur >= strVerNew Then
- Wscript.Quit
- Else
- Set objFSO = CreateObject("Scripting.FileSystemObject")
- objFSO.CopyFile "\\Filesrv\WSUS\WsusAgent30.exe" , "C:\", OverwriteExisting 'Change your Source File Location
- End If
2)程序安装代码,就一个bat,很简单,复制另存为AgentInstall.bat
c:\wsusagent30.exe /quiet /norestart
del c:\WsusAgent30.exe
3)生成报告代码(包括系统分区文件系统,系统分区剩余空间,依赖服务等检测结果),复制并另存为WsusResult.vbs
- On Error Resume Next
- '================
- 'Define constants
- '================
- Const WINDOWS = &H24&
- Const ForReading=1
- Const ForWriting=2
- Const ForAppending=8
- '========================
- 'check wsus agent version
- '========================
- Set objShell = CreateObject("Shell.Application")
- Set objFolder = objShell.Namespace(WINDOWS)
- Set objFolderobjFolderItem = objFolder.Self
- strWinPath = objFolderItem.Path
- strDrvPath = Mid(strWinPath, 1, 3)
- strDrvID = Mid(strWinPath, 1, 2)
- strWinLen = Len(strWinPath)
- strNum = strWinLen - 3
- strWinName = Mid(strWinPath, 4, strNum)
- Set objFSO = CreateObject("Scripting.FileSystemObject")
- strFullAgentPath = strDrvPath & "\" & strWinName & "\\system32\\wuaueng.dll"
- strComputer = "."
- Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
- Set colFiles = objWMIService.ExecQuery("SELECT * FROM CIM_DataFile where name = '" & strFullAgentPath & "'")
- For Each objFile in colFiles
- strVer = objFile.Version
- Next
- strVerCur = Mid(strVer, 1, 12)
- '===========
- 'Get Pc Name
- '===========
- strComputer = "."
- Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
- Set colComputers = objWMIService.ExecQuery("Select * from Win32_ComputerSystem")
- For Each objComputer in colComputers
- strPCname = UCase(objComputer.Name)
- Next
- '===============
- 'Get FileSystem
- '===============
- strComputer = "."
- Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
- Set colDisks = objWMIService.ExecQuery ("Select * from Win32_LogicalDisk where name = '" & strDrvID & "'")
- For Each objDisk in colDisks
- strFileSystem = objDisk.FileSystem
- Next
- '==============================
- 'Get System Patition Free Space
- '==============================
- Dim fso, drv
- Set fso = CreateObject("Scripting.FileSystemObject")
- Set drv = fso.GetDrive(fso.GetDriveName(strDrvID))
- strFreeNum = FormatNumber(drv.FreeSpace / 1024 / 1024 /1024, 3)
- strFreeSpace = strFreeNum & "GB"
- '============================
- 'Check WSUS Relation Services
- '============================
- strComputer = "."
- Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
- Set colRunningServices = objWMIService.ExecQuery ("Select * from Win32_Service where Name='wuauserv'")
- For Each objService in colRunningServices
- strState1 = objService.State
- strMode1 = objService.StartMode
- strstatus1 = strState1 & "(" & strMode1 & ")"
- Next
- strComputer = "."
- Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
- Set colRunningServices = objWMIService.ExecQuery ("Select * from Win32_Service where Name='bits'")
- For Each objService in colRunningServices
- strState2 = objService.State
- strMode2 = objService.StartMode
- strstatus2 = strState2 & "(" & strMode2 & ")"
- Next
- '=============
- 'Create Report
- '=============
- strVerErr = "7.0.0000.000"
- strVerNew = "7.2.6001.788"
- If strVerCur=strVerNew and strMode1="Auto" and strFreeNum>1 Then
- strFileName = "(ok)" & strPCname & ".csv"
- Elseif strVerCur<strVerErr or strFreeNum<1 or strMode1="Disabled" then
- strFileName = "(Err)" & strPCname & ".csv"
- Else
- strFileName = strPCname & ".csv"
- End If
- Set WshShell = CreateObject("WScript.Shell")
- Set WshFso = CreateObject("Scripting.FileSystemObject")
- strDstPath = "\\FileSrv\WSUS_Report\Result\" 'Change your Export File Location
- strDstFilePath = WshFso.BuildPath(strDstPath, strFileName)
- Set WshLogFile = WshFso.OpenTextFile(strDstFilePath,ForWriting,True)
- WshLogFile.WriteLine ("ComputerName,CurrentVersion,DriverType,FreeSpace,AutoUpdate,BITS")
- WshLogFile.WriteLine (strPCname & "," & strVerCur & "," & strFileSystem & "," & strFreeSpace & "," & strstatus1 & "," & strstatus2)
接下来的工作就是等着看报告结果
PS:已附上代码附件提供下载!