转贴自http://hi.baidu.com/mikeoldyang/blog/item/3ce1dd458dda7f4b510ffe99.html
我想这个是很多做网管的需要干的事情,禁用USB存储。
前提是我们不能从BIOS里面禁用,一个是容易破解(拔电池),主要还是因为我们还需要使用USB鼠标以及Bitlocker,所以只能从系统里面动脑筋。
首先是KB555324,http://support.microsoft.com/kb/555324/zh-cn 这里介绍的方法需要自定义一个组策略,看上去好像很好很强大,很简单,可是有一个致命的问题,谁也无法保证那个OU下就一定没有Server的计算机帐号,此时就容易误杀,比不上用Script可以先判断一下。或者你会说可以用WMI筛选,不过就我们的环境目前没权限设这个,而且也不太会写。另外就是到底效果咋样,能否禁掉还未可知。这位看客可能要说了,KB说的还有假?不错,我相信KB,但是有时会不适用。何出此言?请继续往下看
然后就是KB823732,http://support.microsoft.com/kb/823732/zh-cn 这个方法应该是很好,很根本了(Microsoft Service所言),然后我又借用http://www.cnitblog.com/joyclear/archive/2008/05/10/43525.html 所说的用Xcacls来设权限,可是在XPSP2以及之前的版本中都没有Xcacls这个命令,只有Cacls这个命令,而Cacls的问题是不带/y参数,所以又找了http://support.microsoft.com/kb/135268/zh-cn 来实现,有看官可能要说了,你可以使用网络共享的Xcacls来啊,唉,这不是有本地自带的命令,就尽量用本地的了吗。
好,万事俱备,开始脚本吧,好像很简单,也就3~4行的批处理啊,XP是OK,可是在Vista下就有问题了,如果插入新设备,Vista总是还能找到,如果是旧设备,在计算机管理中卸载掉再插入闪存,Vista还是能够使用。而且会把HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/UsbStor 下面的Start的值自动改回到3,真是见鬼了。按照KB的说法,在拒绝INF和PNF文件后,装新设备时会由于没有权限读这两个文件,导致安装失败,可是好像Vista就是有办法。个天杀的,把老子搞得一点脾气没有,小事变成大事了。搞不定啊。
个NND,你不是会把注册表改回来吗,老子把注册表的权限也给你Deny掉,看你咋整?后来发现(无数次实验),只要在上述健的位置,把SYSTEM帐号给Deny掉,就真的可以在Vista下也禁用掉USB了,连那两个INF和PNF文件都不要做任何修改,这可是微软都不知道的哦。可是问题来了,鼠标点点改注册表权限是方便的,用脚本或者命令该咋办呢?翻便微软网站也只找到一个Regini命令,可是要命的是看了半天帮助,也没找到可以设置Deny权限的选项。找到SETACL这个超级权限管理工具,我用的是0.904版的,用法比较简单, http://www.helge.mynetcologne.de/setacl/program/setacl0.904/setacl.exe 现在新的是2.0版本的,功能超强,参数众多,当然用的也比较累了。http://sourceforge.net/project/showfiles.php?group_id=69165
这下基本技术就解决了,下面是写脚本和部署了,因为客户端没有管理员权限,所以脚本必须要用在计算机策略中的开机脚本中,然而很显然公司里面肯定还是有人要使用USB存储的,比如说老板们,当他们填写申请单来要求开通的时候,helpdesk 怎样才能很方便的来为他们解除限制呢?而解除限制是分两块的,一个是把注册表权限给改回来,另外一个是让组策略以后不能再次生效。前者可以写一个Restore的脚本,后者就通过组策略的安全设置喽。建一个组,然后在GPMC中设置那个组策略中这个组被拒绝。然后在Restore的脚本中加入将计算机帐号加入到这个组的功能。
关于Restore的脚本,还有一个问题就是,如果就是一个很简单的脚本,没有任何安全措施,一旦将来这个脚本流传出去(很有可能),那么每个人都可以Run一下来解除限制,到那时这个限制也就是一个摆设了。所以首先脚本要加密,其次要在Run的时候验证用户身份,只有特定帐号才可以使用。
好了,整个技术和管理思路就是这样了,下面就是两个脚本。最好还要说一下就是,我发现Vista和XP在usbstor.inf 和usbstor.pnf 上最大的不同是,XP下这两个文件的Owner是Administrators,而在Vista下的owner是System,而为USB安装驱动经实验是使用的System帐号,并不是之前想当然的觉得是当前登录的帐号,所以KB823732在Vista下不能生效的原因就是虽然Deny了system帐号去读这两个文件,可是由于owner是system,所以system照样可以读到,就照样可以安装USB存储,然后再自动的把start的值改回3.
哈哈,我的解释是不是很有说服力啊。
' ----------------------------------------------------------------------------
' DisableUSB.vbs
' VBScript program to RestoreUSB
' Date: 12/10/2008
' Version: 3.0 - remove other limit
' By: Mike Yang at AMD Suzhou
' ----------------------------------------------------------------------------
' -------------------------
' Get OS
' -------------------------
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!//" & strComputer & "/root/cimv2")
Set colOperatingSystems = objWMIService.ExecQuery _
("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colOperatingSystems
OS = objOperatingSystem.Caption
If InStr(OS, "XP") > 0 Then
OSType = 0
Elseif InStr(OS, "2000 Professional") > 0 Then
OSType = 0
Elseif InStr(OS, "2000 Server") > 0 Then
OSType = 1
Elseif InStr(OS, "2000 Advance Server") > 0 Then
OSType = 1
Elseif InStr(OS, "2003") > 0 Then
OSType = 1
Elseif InStr(OS, "Vista") > 0 Then
OSType = 0
Elseif InStr(OS, "2008") > 0 Then
OSType = 1
Else
OSType = 0
End if
Windir = objOperatingSystem.WindowsDirectory
Next
'Wscript.echo OSType
If OSType = 1 Then
Wscript.quit
End if
'Wscript.echo Windir
' -------------------------
' Copy SetACL
' -------------------------
Source = "//amd.com/SysVol/amd.com/Policies/{C6178A2D-90FC-4663-AB81-0B9B737C11A0}/Machine/Scripts/Startup/SetACL.exe"
Destination = Windir & "/system32/"
SetACL = Windir & "/system32/SetACL.exe"
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(SetACL) Then
'--------------------------------------
'Check size
'--------------------------------------
Set objFile1 = objFSO.GetFile(SetACL)
If objFile1.Size <> 163840 Then
objFSO.CopyFile Source, Destination, OverwriteExisting
End If
Else
objFSO.CopyFile Source, Destination, OverwriteExisting
End If
' -----------------------------------------------
' Modify registry
' -----------------------------------------------
const HKEY_LOCAL_MACHINE = &H80000002
'strComputer = "."
Set StdOut = WScript.StdOut
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!//" &_
strComputer & "/root/default:StdRegProv")
strKeyPath = "SYSTEM/CurrentControlSet/Services/USBSTOR"
strValueName = "Start"
dwValue = 4
oReg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,dwValue
strKeyPath1 = "SYSTEM/CurrentControlSet/Control/StorageDevicePolicies"
strValueName1 = "WriteProtect"
dwValue1 = 1
oReg.CreateKey HKEY_LOCAL_MACHINE,strKeyPath1
oReg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath1,strValueName1,dwValue1
Wscript.Sleep 1000
' -----------------------------------------------
' Deny system permission on registry
' -----------------------------------------------
Set Wwsh = CreateObject("WScript.Shell")
ExecRun1 = "cmd /c " & SetACL & " MACHINE/System/CurrentControlset/Services/usbstor /registry /deny system /full"
Set wExec1 = Wwsh.Exec(ExecRun1)
Rcode = wExec1.StdOut.ReadAll
下面RestorUSB的脚本需要配合一个password.htm文件来使用,这个文件的作用就是验证身份,并且隐藏密码。这个RestoreUSB的脚本功能还是很强大的,
1. 验证身份
2. 验证是否在域中
3. 把计算机帐号加到组中(需要运行帐号有AD中相应的权限)
4. 恢复注册表权限
5. 如果在Restore的时候发生错误,会自动把log发出来。
看官可以自己看是否有必要搞得这么复杂,毕竟各自的环境不同。
' ----------------------------------------------------------------------------
' RestoreUSB.vbs
' VBScript program to RestoreUSB
' Date: 12/10/2008
' Version: 3.0
' By: Mike Yang at AMD Suzhou
' ----------------------------------------------------------------------------
On Error Resume Next
' ###########################################################################
' Get privilege account, e.g admin_xxx or acct_xxx
' ###########################################################################
' Dim Shell
Dim oShell
Set oShell = WScript.CreateObject ("WSCript.shell")
' -------------------------
' Get User & Password
' -------------------------
Set objExplorer = WScript.CreateObject _
("InternetExplorer.Application", "IE_")
objExplorer.Navigate "file:/ssuzfile22/helpdesk$/RestoreUSB/Password.htm"
objExplorer.ToolBar = 0
objExplorer.StatusBar = 0
objExplorer.Width = 620
objExplorer.Height = 420
objExplorer.Left = 100
objExplorer.Top = 100
objExplorer.Visible = 1
Do While (objExplorer.Document.Body.All.OKClicked.Value = "")
Wscript.Sleep 250
Loop
' --------------------------------------------------------------
strUserName = objExplorer.Document.Body.All.UserName.Value
strUser = "amd/" & strUserName
strPassword = objExplorer.Document.Body.All.UserPassword.Value
strASRNo = objExplorer.Document.Body.All.ASRNo.Value
' --------------------------------------------------------------
strButton = objExplorer.Document.Body.All.OKClicked.Value
objExplorer.Quit
Wscript.Sleep 250
If strButton = "Cancelled" Then
Wscript.Quit
End If
If strUsername = "" or strPassword = "" or strASRNo = "" Then
Wscript.Quit
End If
' -------------------------
' Check input User
' -------------------------
adminxxx = Left(strUser,10)
'Wscript.echo adminxxx
acctxxx = Left(strUser,9)
'Wscript.echo acctxxx
err.clear
TASRN0 = Int(strASRNo)
If err <> 0 Then
err.clear
Wscript.echo "" _
& "Your input is error, the ASR number must be number."
run8 = "//ssuzfile22/helpdesk$/RestoreUSB/RestoreUSB.vbe"
'Wscript.echo run8
oShell.run run8,true
Wscript.quit
Elseif Len(strASRNo) <> 6 Then
Wscript.echo "" _
& "Your input is error, the ASR number must have 6 numbers"
run8 = "//ssuzfile22/helpdesk$/RestoreUSB/RestoreUSB.vbe"
'Wscript.echo run8
oShell.run run8,true
Wscript.quit
End if
If adminxxx <> "amd/admin_" and acctxxx <> "amd/acct_" and strUser <> "amd/amdhelpdesk" Then
Mailto = "mike.yang@amd.com"
MailSubject = "Input error name: " & struser
MailTextbody = "Input error name: " & struser
SendMail Mailto,MailSubject,MailTextbody
Wscript.echo "" _
& "Error!! You must use acct_xxx, admin_xxx or amdhelpdesk to run the tools. " & chr(10) & chr(13) _
& "And you must use minuscule to inpute,like acct_yjay , please input again."
run8 = "//ssuzfile22/helpdesk$/RestoreUSB/RestoreUSB.vbe"
'Wscript.echo run8
oShell.run run8,true
Wscript.quit
End If
' -------------------------
' Authenticate User
' -------------------------
Const ADS_SECURE_AUTHENTICATION = 1
Const ADS_USE_ENCRYPTION = 2
strPath = "OU=Suzhou,dc=amd,dc=com"
Set root = GetObject("LDAP:")
Set objOU = root.OpenDSObject("LDAP://SSUZDC3/" & strPath, strUser, strPassword, _
ADS_USE_ENCRYPTION AND ADS_SECURE_AUTHENTICATION)
SuzDN = objOU.distinguishedName
If err = 424 then
Mailto = "mike.yang@amd.com"
MailSubject = "Logon failure: " & struser
MailTextbody = "Logon failure: " & struser
SendMail Mailto,MailSubject,MailTextbody
Wscript.echo "" _
& "Logon failure: unknown user name or bad password, please input again."
run8 = "//ssuzfile22/helpdesk$/RestoreUSB/RestoreUSB.vbe"
'Wscript.echo run8
oShell.run run8,true
wscript.quit
ElseIf err <> 0 Then
Mailto = "mike.yang@amd.com"
MailSubject = "Get Suzhou OU failure: " & struser
MailTextbody = "Get Suzhou OU failure: " & struser
SendMail Mailto,MailSubject,MailTextbody
Wscript.echo "" _
& "failed,please contack with Mike Yang (37890)"
run8 = "//ssuzfile22/helpdesk$/RestoreUSB/RestoreUSB.vbe"
'Wscript.echo run8
oShell.run run8,true
Wscript.quit
End If
' ###########################################################################
' Get privilege account, e.g admin_xxx or acct_xxx
' ###########################################################################
' ------------------------------
' Copy SetACL
' ------------------------------
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!//" & strComputer & "/root/cimv2")
Set colOperatingSystems = objWMIService.ExecQuery _
("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colOperatingSystems
Windir = objOperatingSystem.WindowsDirectory
Next
'Wscript.Echo windir
Source = "//amd.com/SysVol/amd.com/Policies/{C6178A2D-90FC-4663-AB81-0B9B737C11A0}/Machine/Scripts/Startup/SetACL.exe"
Destination = Windir & "/system32/"
SetACL = Windir & "/system32/SetACL.exe"
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(SetACL) Then
'--------------------------------------
'Check size
'--------------------------------------
Set objFile1 = objFSO.GetFile(SetACL)
If objFile1.Size <> 163840 Then
objFSO.CopyFile Source, Destination, OverwriteExisting
End If
Else
objFSO.CopyFile Source, Destination, OverwriteExisting
End If
' ------------------------------
' Get Computername
' ------------------------------
Set objNetwork = CreateObject("WScript.Network")
ComputerName = objNetwork.ComputerName
UserDomain = objNetwork.userdomain
UserName = objNetwork.username
LogonName = UserDomain & "/" & UserName
Mailto = "mike.yang@amd.com"
MailSubject = LogonName & " run the RestoreUSB script on the " & ComputerName & " by " & strUser
MailTextbody = LogonName & " run the RestoreUSB script on the " & ComputerName & " by " & strUser
SendMail Mailto,MailSubject,MailTextbody
' ------------------------------
' Check if it is in the domain
' ------------------------------
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!//" & strComputer & "/root/cimv2")
Set objWMI = GetObject("winmgmts://./root/cimv2")
Set colComputer = objWMI.ExecQuery("select DomainRole from win32_computersystem",,48)
For Each objComputer in colComputer
role = objComputer.DomainRole
Next
' role = 1 (in the domain)
If role <> 0 and role <> 2 Then
err.clear
' -------------------------------------
' search AD to find the account
' -------------------------------------
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Properties("User ID") = strUser
objConnection.Properties("Password") = strPassword
objConnection.Properties("Encrypt Password") = True
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000
objCommand.CommandText = "<LDAP://ssuzdc3/dc=amd,dc=com>;" & _
"(&(objectCategory=computer)(objectClass=user)(Name=" & ComputerName & "));" & _
"distinguishedName,name;Subtree"
Set objRecordSet = objCommand.Execute
ComDN = objRecordSet.Fields("distinguishedName").Value
' -------------------------------------
' If the account is lost in the AD
' -------------------------------------
If err <> 0 Then
err.clear
Mailto = "mike.yang@amd.com"
MailSubject = "The " & ComputerName & " 's account is lost in the domain. The script quits."
MailTextbody = "The " & ComputerName & " 's account is lost in the domain. The script quits."
SendMail Mailto,MailSubject,MailTextbody
Wscript.echo "" _
& "The computer is in the domain, but seems it has lost the account in the AD, " & chr(10) & chr(13) _
& "Please run joindomain script to fix the problem and then run the tool again."
Wscript.quit
End If
Else
Mailto = "mike.yang@amd.com"
MailSubject = "The " & ComputerName & " is out of domain. The script quits."
MailTextbody = "The " & ComputerName & " is out of domain. The script quits."
SendMail Mailto,MailSubject,MailTextbody
Wscript.echo "" _
& "The computer is out of domain. " & chr(10) & chr(13) _
& "Please run joindomain script to fix the problem and then run the tool again."
Wscript.quit
End if
' -------------------------------------
' Add computer account into group
' -------------------------------------
err.clear
Const ADS_PROPERTY_APPEND = 3
GroupDN = "CN=SZ_No_Disable_USB,OU=Groups,OU=Suzhou,DC=amd,DC=com"
Set root = GetObject("LDAP:")
Set objGroup = root.OpenDSObject("LDAP://SSUZDC3/" & GroupDN, strUser, strPassword, 200)
objGroup.PutEx ADS_PROPERTY_APPEND, "member", Array(ComDN)
objGroup.SetInfo
if err = 0 then
Mailto = "mike.yang@amd.com"
MailSubject = "Join the: " & ComputerName & " into the group is OK."
MailTextbody = "Join the: " & ComputerName & " into the group is OK."
SendMail Mailto,MailSubject,MailTextbody
Elseif err = -2147019886 then
Err.clear
Mailto = "mike.yang@amd.com"
MailSubject = ComputerName & " had been into the group"
MailTextbody = ComputerName & " had been into the group"
SendMail Mailto,MailSubject,MailTextbody
Else
Mailto = "mike.yang@amd.com"
MailSubject = "Join the: " & ComputerName & " into the group is failed."
MailTextbody = LogonName & " run the script failed when he join the " & ComputerName & " into the Group by " & strUser
SendMail Mailto,MailSubject,MailTextbody
Wscript.echo "Join the computer into the group is failed, please contact Mike Yang and click OK to quit the script."
Wscript.quit
End if
' -----------------------------------------
' Define temp file
' -----------------------------------------
Const ForReading = 1
Const ForWriting = 8
logfile = "temp.txt"
Set objFSO1 = CreateObject("Scripting.FileSystemObject")
If objFSO1.FileExists(logfile) Then
objFSO1.DeleteFile(logfile)
End If
Set go = objFSO1.OpenTextFile(logfile, ForWriting, True)
' -----------------------------------------
' Restore registry permission
' -----------------------------------------
Set Wwsh = CreateObject("WScript.Shell")
ExecRun1 = "cmd /c Setacl MACHINE/System/CurrentControlset/Services/usbstor /registry /grant system /full"
Set wExec1 = Wwsh.Exec(ExecRun1)
Rcode1 = wExec1.StdOut.ReadAll
'Wscript.Echo Rcode1
go.Writeline(Rcode1)
Wscript.Sleep 1000
ExecRun2 = "cmd /c Setacl MACHINE/System/CurrentControlset/Services/usbstor /registry /revoke system /full"
Set wExec2 = Wwsh.Exec(ExecRun2)
Rcode2 = wExec2.StdOut.ReadAll
'Wscript.Echo Rcode2
go.Writeline(Rcode2)
Wscript.Sleep 1000
Set objTextFile = objFSO1.OpenTextFile(logfile, ForReading)
' -------------------------
' loop to verify result
' -------------------------
CONT = 0
Do Until objTextFile.AtEndOfStream
Rcode = objTextFile.ReadLine
If InStr(Rcode, "SUCCESS") > 0 Then
CONT = CONT + 1
End if
Loop
'Wscript.Echo CONT
objTextFile.Close
go.close
objFSO1.DeleteFile(logfile)
Set Wwsh = Nothing
Set wExec1 = Nothing
Set wExec2 = Nothing
'Wscript.sleep 1000
' -----------------------------------------
' Restore registry value
' -----------------------------------------
const HKEY_LOCAL_MACHINE = &H80000002
'strComputer = "."
Set StdOut = WScript.StdOut
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!//" &_
strComputer & "/root/default:StdRegProv")
strKeyPath = "SYSTEM/CurrentControlSet/Services/USBSTOR"
strValueName = "Start"
dwValue1 = 3
oReg.SetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,dwValue1
strKeyPath1 = "SYSTEM/CurrentControlSet/Control/StorageDevicePolicies"
oReg.DeleteKey HKEY_LOCAL_MACHINE,strKeyPath1
Wscript.sleep 1000
' -----------------------------------------
' Analyse value
' -----------------------------------------
oReg.GetDWORDValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,dwValue
'Wscript.echo dwValue
Wscript.sleep 1000
If dwValue = 3 and CONT = 2 Then
'Mailto = "mike.yang@amd.com"
Mailto = "dl.NTadm-sz@amd.com;dl.suzhelpdesk@amd.com"
MailSubject = "ASR " & strASRNo & " - " & strUser & " has restore the USB feature on the " & ComputerName & " successfully!"
MailTextbody = "ASR " & strASRNo & " - " & strUser & " has restore the USB feature on the " & ComputerName & " successfully!"
SendMail Mailto,MailSubject,MailTextbody
Wscript.Echo "The " & ComputerName & " has already been restore the USB feature successfully!"
Else
'Mailto = "mike.yang@amd.com"
Mailto = "dl.NTadm-sz@amd.com;dl.suzhelpdesk@amd.com"
MailSubject = "ASR " & strASRNo & " - " & strUser & " restored the USB feature on the " & ComputerName & " failed!"
MailTextbody = "ASR " & strASRNo & " - " & strUser & " restored the USB feature on the " & ComputerName & " failed!"
SendMail Mailto,MailSubject,MailTextbody
Mailto = "mike.yang@amd.com"
'Mailto = "dl.NTadm-sz@amd.com;dl.suzhelpdesk@amd.com"
MailSubject = "ASR " & strASRNo & " - " & strUser & " restored the USB feature on the " & ComputerName & " failed! -- Only Mike"
MailTextbody = "" _
& "ASR " & strASRNo & " - " & strUser & " restored the USB feature on the " & ComputerName & " failed!" & chr(10) & chr(13) & chr(10) & chr(13) _
& Rcode1 & chr(10) & chr(13) & chr(10) & chr(13) _
& Rcode2 & chr(10) & chr(13) & chr(10) & chr(13) _
& "Start = " & dwValue
SendMail Mailto,MailSubject,MailTextbody
Wscript.Echo "The " & ComputerName & " restored the USB feature failed"
End if
' -------------------------
' Send mail
' -------------------------
Sub SendMail(Mailto,MailSubject,MailTextbody)
'Mailto = "mike.yang@amd.com"
'MailSubject = strUser & " has joined " & strComputer & " into " & strOU & " sucessfully!"
'MailTextbody = strUser & " has joined " & strComputer & " into " & strOU & " sucessfully!"
'MailAttachment = "c:/log.txt"
Set objEmail = CreateObject("CDO.Message")
objEmail.From = "SUZ_RestoreUSB@amd.com"
objEmail.To = Mailto
objEmail.cc = Mailcc
objEmail.bcc = Mailbcc
objEmail.Subject = MailSubject
objEmail.Textbody = MailTextbody
'objEmail.AddAttachment MailAttachment
objEmail.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objEmail.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserver") = _
"SUZSMTP"
objEmail.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objEmail.Configuration.Fields.Update
objEmail.Send
End Sub