In-Depth

Automate Your Security

Many security-related tasks can be tedious—and, therefore, overlooked. Using these 10 scripts can make your life easier, while simultaneously locking down your network.

Security, of course, has become a lot more important than it used to be in the “old days,” when we were merely concerned about keeping all the servers up and running. Unfortunately, much of security involves routine, repetitive tasks, like backing up event logs, keeping track of service account passwords and so on. There’s a growing market of third-party utilities out there to help manage those tasks, but the concern about security has coincided with reductions in IT budgets, making it difficult to buy every new tool that promises to do the job for you.

Fortunately for the harried administrator, Windows comes with two perfect built-in tools that can handle much of your security automation: Windows Script Host (WSH), and VBScript. While I won’t promise that WSH can stop hackers and take your next certification exam for you, it certainly can remove the monotony out of many security-related tasks. In fact, simply having some automation around makes it more likely that you’ll do these boring tasks to begin with, thereby making your environment that much more secure.

Picking just 10 scripts is a tough job, so I’ve tried to pick ones that are short, easy to understand and adaptable to almost any environment (many even run on Windows NT). More importantly, I’ve tried to pick scripts that can act as examples or building blocks for your own scripts, giving you sort of a mini-library of scripts to start building a collection.

Changing Service Account Passwords
I hate keeping up with service account passwords, so much so that I usually just set them to never expire and forget about them. That’s a bad idea, of course, but while changing the passwords in AD Users & Computers is easy, changing all the passwords in the Services snap-in can be pretty time-consuming. Here’s a quick script that uses every administrator’s friend, Windows Management Instrumentation (WMI), to connect to a remote server and change the password that a particular service will use to log in. You’ll change the actual account password in some other way; this is just changing the service itself to use the new password. You’ll need to have administrative privileges on the remote server, and you’ll want to change the server name, the service name and the new password to suit your environment.

The first two lines of code simply define the remote server’s name and then connect to its WMI provider, which runs as a background service. Next, the script asks the WMI provider to return every instance of the Win32_Service class that has the name “myservice,” or whatever you change the service name to. Of course, only one service will meet that criterion, so the next line of code can simply change the password. You must have all seven commas before the password. These are placeholders for other service attributes that aren’t being changed.

'connect to the computer's WMI provider
sComputer = "server1"
Set oWMIService = GetObject("winmgmts:" _
  & "{impersonationLevel=impersonate}!\\" & _
  sComputer & "\root\cimv2")

'retrieve the MyApp service
Set oService = oWMIService.ExecQuery _
("Select * from Win32_Service WHERE Name" & _
   " = 'myservice'")

   'change the password
   errReturn = oService.Change( , , , , , , _
   , "NeWP@ss#0rD")

Changing Services’ Logon Account
Changing the user account utilized by a service can be painful, too. Sometimes you may want to standardize a particular service to use the same account throughout your domain; other times, you may simply want to find every service using a particular account and change it to something else. That’s what this next script does for you.

This script starts by connecting to a remote server, where you’ll need to have administrative privileges. Next, the script retrieves all of the services installed on that machine by querying the server’s WMI provider. Those services are retrieved into a special structure called a collection, which stores multiple complex objects. The script then uses a “For Each…Next” loop to examine each object—or service—in the collection. An “If…Then” statement examines the service’s StartName property to see if the service is using the local user account “Bob.” You could change this to a domain account by using the domain\username format, or even the user@domain format on Windows XP or Windows Server 2003. For every service using the specified account, the script sets the new startup account to “.\LocalSystem,” which represents the built-in LocalSystem account. Again, you can specify whatever you like for the new account. If you’re not using LocalSystem (which doesn’t require a password), you can combine this script with the previous one to also set the password that the service will use to log on when it starts. You can combine them by adding the new password to the call to oService.Change. There’s no need to run both separate scripts.

'Connect to the remote computer
sComputer = "Server2"
Set oWMIService = GetObject("winmgmts:" _
  & "{impersonationLevel=impersonate}!\\" _
  & sComputer & "\root\cimv2")

'Retrieve all services
Set cServices = oWMIService.ExecQuery _
  ("Select * from Win32_Service")

'Examine each service one at a time
For Each oService in cServices

  'If the service uses the account "Bob,"
  'then change it to LocalSystem.
  If oService.StartName = ".\Bob" Then
     errServiceChange = oService.Change _
     ( , , , , , , ".\LocalSystem" , "")
  End If
Next

Do as I Say

To conserve space and keep these scripts easy to read, I’ve done a couple of things my high school programming teacher wouldn’t approve of. To begin with, I haven’t specifically declared any of the script variables I use. VBScript isn’t picky and lets me get away with it, but it can make script troubleshooting and maintenance a lot harder. I’ve also shorted the generally-accepted variable naming conventions to use just a single letter to designate objects, strings, collections, and so forth. While it makes the script a bit harder for a programmer to read, it also keeps the scripts short. None of my shortcuts should affect how these scripts run, so hopefully you’ll forgive me and not live by my example in your own scripts.

Also note that, due to space limitations, not all of the scripts have been included in their entirety. Sometimes I’ll just pull out the sections that do the legwork and explain what’s going on. However, you can download all of the scripts in the online edition of this article.

—Don Jones

Disabling a Service
Some services don’t deserve a new password or a new account. They deserve to be shut down entirely. The Messenger service (the built-in one, not the Windows Messenger or MSN Messenger applications) is a good example, due mainly to the amount of annoying pop-up spam I get from it. You might also want to shut down services that use a particular service account, for security reasons.

This time, I’ve created a script that takes its input from a text file. This file should simply list one computer name per line, allowing the script to contact each of those computers and disable the offending services.

The script starts by creating a special object known as the FileSystemObject, which is built into WSH and provides access to files and folders. Next, the script uses the FileSystemObject to open a text file named c:\computers. txt (you can substitute something appropriate when you run it). Inside the script, this text file is now represented by something called a text stream, or TextStream object, which makes sense because a text file is basically a stream of characters. The script’s “Do…Loop” construct will repeat once for each line of text in the file.

For each computer mentioned in the text file, the script will reach out and connect to its WMI provider. You’ll need to have administrative privileges on each machine, which generally means you’ll have to run the script against domain members while using a Domain Admin account. For each computer, the script retrieves a list of all services set to use a specified domain account, “Domain\ServiceAcct.” Having retrieved all of the services I want to disable, I have the script use a “For…Next” loop to set each service’s startup attribute to “Disabled.” Once the TextStream reaches its end, the script will end. VBScript is smart enough to close the text file when the script ends, although it’s not a bad idea to explicitly do so yourself by adding the following to the end of the script:

oTS.Close

You could also retrieve—and disable—the Messenger service or any other service, by name, by changing the query to read:

Set cServiceList = oWMIService.ExecQuery _
  ("Select * from Win32_Service where " & _
  " Name = 'Messenger'")

For information on other attributes provided by the Win32_Service class (and every other WMI class), hop over to msdn.microsoft.com/library; in the left-hand pane look for “Setup and System Administration” | Windows Management Instrumentation” | WMI Reference | WMI Classes and drill down into Win32 Classes.

'Create a FileSystemObject
Set oFS = CreateObject("Scripting.FileSystemObject")

'Open a text file of computer names
'with one computer name per line
Set oTS = oFS.OpenTextFile("c:\computers.txt")

'go through each computer name
Do Until oTS.AtEndOfStream

  'read the next computer name
  sComputer = oTS.ReadLine
  
  'connect to its WMI provider
  Set oWMIService = GetObject("winmgmts:" _
  & "{impersonationLevel=impersonate}!\\" & _
  sComputer & "\root\cimv2")
  
  'get a list of all services set to use the
  'domain account "ServiceAcct"
  Set cServiceList = oWMIService.ExecQuery _
  ("Select * from Win32_Service where " & _
  " StartName = 'Domain\ServiceAcct'")
  
  'disable each matching service
  For Each oService in cServiceList
    errReturnCode = oService.Change( , , , , "Disabled")
  Next
Loop

Changing the Local Administrator Password
Enough with services and service accounts. Another tedious task is periodically changing the local Administrator password on every computer in your company. You know you should do it, but who has that kind of time? Scripts do! Once again, start with an input text file that lists one computer per line. In case you’re wondering, it’s also possible to retrieve a list of computers from AD, an NT domain or even a database, with a little bit of extra programming.

This script starts out similarly to the last, by opening a text file and using a “Do…Loop” construct to iterate through each line of the file. However, this script doesn’t connect to a WMI provider on each computer. It relies on the Active Directory Scripting Interface, or ADSI, to connect. Wait a sec—ADSI? Does this only work on 200x domain controllers? Nope, this script will run against everything from NT 4.0 on up, including NT Workstation, 2000 Pro, and XP Pro, because all NT-based operating systems have an NT domain-like Security Accounts Manager (SAM). Notice how the ADSI connection uses the “WinNT://” moniker, which tells ADSI to stay NT-compatible.

The ADSI connection specifically queries a user account named “Administrator,” and then changes its password and saves the change back to the SAM. You can run this script on a monthly basis, if you like, with a word of warning: As written, the script doesn’t include any error handling, so it will crash if one of the specified computers isn’t available at the time. A quick and dirty way to bypass the crash is to add:

On Error Resume Next

As the first line of script code. This will cause the script to ignore any errors and try the next computer in sequence. If you want to be a bit more thorough, you could save the failed computer names to a new text file, which could be used to run the script again the next day.

'Create a FileSystemObject
Set oFS = CreateObject("Scripting.FileSystemObject")

'Open a text file of computer names
'with one computer name per line
Set oTS = oFS.OpenTextFile("c:\computers.txt")

'go through the text file
Do Until oTS.AtEndOfStream

  'get the next computer name
  sComputer = oTS.ReadLine

  'retrieve that computer's local Admin
  Set oUser = GetObject("WinNT://" & _
  sComputer & "/Administrator, user")

  'reset the password
  oUser.SetPassword "New!Ad3in"

  'save the change
  oUser.SetInfo
Loop

'close the text file
oTS.Close

Creating User Accounts
A major security problem in many environments is that user accounts aren’t created consistently. To help one of my customers, I created a script that reads new user information from an Excel spreadsheet and creates the appropriate user accounts in the domain. Note that you have to have the spreadsheet (a sample is included with the downloadable, complete script), and an ODBC DSN named “Excel” that points to the spreadsheet file. You can create a DSN by using the ODBC utility in the Administrative Tools folder.

In section 1 (which starts with “Dim oCN”), the script uses ActiveX Data Objects (ADO) to open the Excel spreadsheet and retrieve the rows. Much of the script should look familiar. It uses ADSI to connect to an NT PDC or the AD PDC Emulator, and opens an output text file to save users’ new passwords. In section 2 (sUserID = oRS(“UserID”)), the script retrieves information from the current row of the spreadsheet, giving it the user name and other useful data. In section 3 (sPassword = Left), a new password is created using pieces of the current date and time—not the strongest password, of course, and you can add something more complex if you like. Section 4 (Set oUserAcct = oDomain.Create) actually creates the user account and sets most of its initial properties. The script saves the new password to the output file, and in section 5 (sGroupList = Split) adds the users to the specified groups. The group list must be comma-delimited, and the script breaks this list into an array of group names, and then adds the user to each group one at a time. The script wraps up in section 6 (oRS.Close) by closing the Excel spreadsheet connection, the output file with passwords, and a final closing message letting you know that it’s done.

' PART 1: Open up the Excel spreadsheet
' using ActiveX Data Objects
Dim oCN
Set oCN = CreateObject("ADODB.Connection”)
oCN.Open "Excel"

Dim oRS
Set oRS = oCN.Execute("SELECT * FROM [Sheet1$]")

' PART 2: Get a reference to the
' Windows NT domain using ADSI
Dim oDomain
Set oDomain = GetObject("WinNT://MyPDC")

' PART 3: Open an output text file
' to store users' initial passwords
Dim oFSO, oTS
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oTS = oFSO.CreateTextFile("c:\passwords.txt",True)

' PART 4: For each record in the recordset, add the user,
‘ set the correct user properties, and add the user to the
' appropriate groups

' create the necessary variables
Dim sUserID, sFullName, sDescription
Dim sGroups
Dim sPassword, oUserAcct, oFolder
Dim sGroupList, iTemp, oGroup

' now go through the recordset one row at a time
Do Until oRS.EOF

  ' get the user information from this row
  sUserID = oRS("UserID")
  sFullName = oRS("FullName")
  sDescription = oRS("Description")
  sGroups = oRS("Groups")

  ' make up a new password
  sPassword = Left(sUserID,2) & DatePart("n",Time) & _
  DatePart("y",Date) & DatePart("s",Time)

  ' create the user account
  Set oUserAcct = oDomain.Create("user",sUserID)

  ' set account properties
  oUserAcct.SetPassword sPassword
  oUserAcct.FullName = sFullName
  oUserAcct.Description = sDescription

   ' save the account
  oUserAcct.SetInfo

   ' get a reference to the new account
  ' this gets us a valid SID & other info
  Set oUserAcct = GetObject("WinNT://NT4PDC/" & _
  sUserID & ",user")

   ' write password to file
  oTS.Write sUserID & "," & sPassword & vbCrLf

  ' PART 4A: Add user account to groups
  ' use the Split function to turn the
  ' comma-separated list into an array
  sGroupList = Split(sGroups, ",")

  ' go through the array and add the user to each group
  For iTemp = 0 To uBound(sGroupList) - 1

    ' get the group
    Set oGroup = GetObject("WinNT://NT4PDC/" & _
    sGroupList(iTemp) & ",group")

    ' add the user account
    oGroup.Add oUserAcct.ADsPath

    ' release the group
    Set oGroup = Nothing

  Next
  ' move to the next row in the recordset
  oRS.MoveNext

Loop

' PART 6: Final clean up, close down
oRS.Close
oTS.Close
WScript.Echo "Passwords have been written to" & _
" c:\passwords.txt."

Disabling Inactive User Accounts
How helpful would it be to have a script that could disable any user accounts that hadn’t been used for six weeks or some other specified period of time?

This script has a lot in common with some of the previous scripts, so I’ll concentrate on a few specific areas of interest. First, in section A (‘Point to group), I used ADSI to connect to a user group in the domain. Note that I used the “WinNT://” moniker, which means this script will run on NT and later domains, including AD. In section B (dDate = oUser.get), I retrieve the current user’s last login date. The domain supplies that plus the time all in one string, so I also save just the leftmost eight characters, which compose the date part. Finally, in section C (If iDiff >= 6 Then), I actually look at the user’s disabled status. If the difference between today’s date and the user’s last login date is six weeks or more, then the script sets the user’s flags to have a “Disabled” flag, unless the user is already disabled. The script uses SetInfo to save the information back to the directory.

One caveat: Prior to Windows 2003, domain controllers don’t reliably remember the last time a user logged in; in fact, that was a specific new feature for Windows 2003. Be sure to try this script in your test environment before you unleash it in production, so that you’ll know whether or not it’s going to be useful for you.

Dim dDate, oUser, oObject, oGroup
Dim iFlags, iDiff, iResult
Const UF_ACCOUNTDISABLE = &H0002

'Point to group containing users to check
Set oGroup = GetoObject("WinNT://MyDomain/Domain Users")
'Enable error trapping

On error resume Next

'for each user object in the group...
For each oObject in oGroup.Members
  'ensure the user isn't a computer account!
  If (oObject.Class="User") And _
  (InStr(oObject.Name, "$") = 0) Then
     'retrieve the user object
     Set oUser = GetoObject(oObject.ADsPath)
     'get the last login Date from the domain
     'and strip off the time portion
     '(just need the date)
     dDate = oUser.get("LastLogin")
     dDate = Left(dDate,8)
     dDate = CDate(dDate)

     'calculate how long ago that was in weeks
     iDiff = DateDiff("ww", dDate, Now)
     'more than six weeks since last login?
     If iDiff >= 6 Then
        'yes - get the user's flags
        iFlags = oUser.Get("UserFlags")

         'is the account already disabled?
        If (iFlags AND UF_ACCOUNTDISABLE) = 0 Then
           'no - disable it!
           oUser.Put "UseriFlags", iFlags OR UF_
           ’ ACCOUNTDISABLE
           oUser.SetInfo
        End If
     End If
  End If
Next
WScript.Echo "All done!"

Dumping the Security Event Log
Here’s a great way to archive off your servers’ security logs. This is a script you can run under Task Scheduler once a day, or manually, if you like. It will dump each server’s security log into a text file and then clear the log for you. Obviously, you’ll need the necessary permissions on the servers. If you set this up to run under Task Scheduler, make sure the task runs under an appropriate user account.

This script starts like many others, by reading in a text file with one server name per line. For each server, it connects to the WMI provider and queries the security log by using a WMI query. The script then asks each log to back itself up to a local file. Notice that the BackupEventLog method returns a value, which is stored in the errBackupError variable. Some of the previous scripts have used this technique, but this is the first time I’ll actually check to see if an error occurred.

Also notice that the filename used to save the log is dynamically generated, and includes both the server’s name and the current date. This technique allows the script to be run every day without overwriting the files. You can create your own naming scheme, of course.

An “If…Then” construct checks to see if the errBackupError variable contains something other than zero: If it does, an error occurred and a message is displayed. If not, then the backup was successful and the log is cleared out. The bit that displays the error message—WScript.Echo—needs to be removed if using this script under Task Scheduler. That’s because Task Scheduler can’t respond to the error message and won’t display it so that you can respond manually. The script will be locked up in the background until the computer or the Task Scheduler service is restarted.

‘Create a FileSystemObject
Set oFS = CreateObject(“Scripting.FileSystemObject”)

‘Open a text file of computer names
‘with one computer name per line
Set oTS = oFS.OpenTextFile(“c:\computers.txt”)

‘go through the text file
Do Until oTS.AtEndOfStream

 ‘get next computer
 sComputer = oTS.ReadLine

 ‘connect to the WMI provider
 Set oWMIService = GetObject(“winmgmts:” _
 & “{impersonationLevel=impersonate,(Backup)}!\\” & _
 sComputer & “\root\cimv2”)

 ‘query the Security logs
 Set cLogFiles = oWMIService.ExecQuery _
 (“Select * from Win32_NTEventLogFile where “ & _
 “LogFileName=’Security’”)

 ‘go through the collection of logs
  For Each oLogfile in cLogFiles

   ‘back up the log to a file
   errBackupError = objLogFile.BackupEventLog _
   (“c:\logfiles\” & sComputer & Date() & “.evt”)

   ‘see if an error occurred
   If errBackupError <> 0 Then

    ‘one did - display an error
    Wscript.Echo “Couldn’t get log from “ & sComputer

   Else


   ‘no error - safe to clear the Log
   oLogFile.ClearEventLog()

   End If
  Next
Loop

‘close the input file
oTS.Close

Show the Latest Service Pack
Ever need a quick rundown of which computers were on the latest service pack? WMI to the rescue, again! This next script uses my now-familiar technique of reading computer names from a text file, giving you complete control over which machines are checked. I use this script to quickly check by key servers after a planned service pack deployment, just to see if any were missed. The script is kind of a poor person’s Systems Management Server, providing basic inventory information about the operating system service pack level. With service packs providing the basis for so many security features—including bugfixes, new security defaults, and new security capabilities—ensuring that servers are up-to-date is a critical task.

This script actually uses two text files: One input file for server names, and an output file listing each server checked and its reported service pack version. As with many of the previous scripts, it connects to each server’s WMI provider, queries the necessary WMI class (starting to see a pattern to this WMI stuff?), and writes the desired information to a file.

I did one other new thing in this script: Notice the last line of code, which displays a simple “All done!” message. This message is a great thing to add to the end of all of your scripts, especially those that might not seem to do anything, even when they’re working perfectly. This message will often be your only indication that the script finished successfully; WSH’s default behavior upon completing a script is to do nothing, which often leaves you wondering if the script actually ran or just vanished into a black hole.

‘Create a FileSystemObject
Set oFS = CreateObject(“Scripting.FileSystemObject”)
‘Open a text file of computer names
‘with one computer name per line
Set oTS = oFS.OpenTextFile(“c:\computers.txt”)

‘Now open an output text file
Set oReport = oFS.CreateTextFile(“C:\results.txt”)
‘go through the text file
Do Until oTS.AtEndOfStream

 ‘get the next computer
 sComputer = oTS.ReadLine

‘connect to WMI
 Set oWMIService = GetObject(“winmgmts:” _
 & “{impersonationLevel=impersonate}!\\” & _
 sComputer & “\root\cimv2”)
 ‘query the Win32_OperatingSystem class
 ‘(there’s usually only one instance)
 Set cOperatingSystems = oWMIService.ExecQuery _
 (“Select * from Win32_OperatingSystem”)
 ‘check each instance returned
 For Each oOperatingSystem in cOperatingSystems
  ‘write the report
  oReport.WriteLine sComputer “ is at SP “ & _
  oOperatingSystem.ServicePackMajorVersion _
  & “.” & oOperatingSystem.ServicePackMinorVersion
 Next
Loop
‘close the input and output files
oTS.Close
oReport.Close

WScript.Echo “All done!”

Creating Computer Accounts
Deploying new computers can be a pain, especially when they all have to be joined to the domain. Here’s a script that can make the task a bit easier, by pre-creating computer accounts in a specified container (or organizational unit) within AD. This time, I’ll use ADSI again, rather than WMI.

I’ve still used an input file that lists the computer names I want to create. For each computer, I connect to the AD root by using an ADSI “LDAP://” moniker. I could have used the “WinNT://” moniker that I used in the last ADSI script, but doing so wouldn’t have provided access to organizational units; all computer accounts would be created in the default container. By using LDAP, I can access the full capabilities of AD. Once I connect to the root of the directory, the script connects to the destination container. In this case, I specified the default Computers container; you could obviously specify any location you wanted, including an organizational unit.

Next the script creates the new account, at the same time retrieving a reference to it. That’s because new accounts still need a couple of settings changed before they’re really usable. In fact, the script handles that next, setting both the computer’s SAM account name and two flags indicating that no password is required and that the account is for a computer, not a user. Notice the two flag names, ADS_UF_ PASSWD_NOTREQD and ADS_UF_WORKSTATION_ TRUST_ACCOUNT: These flags actually represent numeric (hexadecimal, actually) values, which are defined in the beginning of the script by using the CONST keyword. Once all the desired settings have been changed, SetInfo saves the information back to AD and the account is finished.

You can use a substantially similar script to create Contact objects, users, and other AD objects. For users, of course, you might set a variety of other settings, such as their initial password, display name, address and phone number, and more.

‘Create a FileSystemObject
Set oFS = CreateObject(“Scripting.FileSystemObject”)
‘Open a text file of computer names
‘with one computer name per line
Set oTS = oFS.OpenTextFile(“c:\computers.txt”)

‘go through the text file
Do Until oTS.AtEndOfStream

 ‘get the next computer to create
 sComputer = oTS.ReadLine

 ‘define constants
 Const ADS_UF_PASSWD_NOTREQD = &h0020
 Const ADS_UF_WORKSTATION_TRUST_ACCOUNT = &h1000
 ‘retrieve the root directory level
 Set oRootDSE = GetObject(“LDAP://rootDSE”)
 ‘retrieve the destination container
 Set oContainer = GetObject(“LDAP://cn=Computers,” & _
 oRootDSE.Get(“defaultNamingContext”))
 ‘create a computer and retrieve the
 ‘newly-created object
  Set oComputer = oContainer.Create( _
 “Computer”, “cn=” & sComputer)
 ‘save the computer’s name
 oComputer.Put “sAMAccountName”, sComputer & “$”
 ‘save the password and account attributes
 oComputer.Put “userAccountControl”, _
 ADS_UF_PASSWD_NOTREQD Or ADS_UF_WORKSTATION_TRUST_ACCOUNT
 ‘write the information to AD
 oComputer.SetInfo

Loop
‘close the input file
oTS.Close
WScript.Write “All done!”

WSH Security
I’ll wrap up with a two-for-one offer designed to illustrate how the latest version of WSH (version 5.6, available as a free download from www.microsoft.com/scripting) includes built-in security to prevent untrusted scripts—including viruses—from running. The first script is a simple Registry hack to set the WSH trust policy to execute only trusted scripts. You can use this as a logon script for Win9x machines, although regular users don’t have the necessary permissions to the registry in NT, 2000, and XP. However, since this is just a Registry hack, you can also deploy it via System Policy or Group Policy to all of your client computers.

‘create a shell object
Set oShell = CreateObject(“WScript.Shell”)
‘write the registry key
oShell.RegWrite(“\HKCU\SOFTWARE\Microsoft\” & _

 “Windows Script Host\Settings\TrustPolicy”, 2)

Once set, WSH will only execute scripts that have been signed by using a digital certificate, and it’ll only accept certificates that have been issued by a trusted certification authority or CA. Keep in mind that most commercial CAs—VeriSign, Thawte and so on—are trusted by default, and that you can use Group Policy to deploy different trust arrangements to 2000 and XP clients. Of course, you’ll need to sign your own scripts in order for them to execute, and WSH gives you a way. Here’s your bonus eleventh script, which will use a locally-installed code-signing certificate named “IT Department” to sign a script file named “C:\MyScript.vbs.” The certificate must be installed to the current user’s default certificate store, as is usually the case with code-signing certificates.

Set oSigner = WScript.CreateObject(“Scripting.Signer”)
oSigner.SignFile “C:\MyScript.vbs”, “IT Department”

Scripts, Zipped
To download all the scripts from this article in one file, click here: http://mcpmag.com/downloads/2003/0204mcp_scripts.zip or right click the link and "Save As." Having problems downloading the script? Send e-mail to Michael Domingo, editor, MCPmag.com at [email protected] with "Scripting" in the subject line of your message and he'll send it to you.

Looking for More?
The Web holds a zillion more scripts that have a direct security purpose, and even more that can be adapted to help meet your security needs. For starters, check out my site, www.adminscripting.com. Microsoft’s TechNet Scripting Center is also a great resource, and can be found at www.microsoft.com/technet/treeview/default.asp?
url=/technet/scriptcenter/Default.asp
. If you’re looking for the VBScript or WSH documentation, look no further than www.microsoft.com/scripting. Above all, experiment a bit. You’ll find that scripting will come more naturally as you work with it. Set up a small test lab or use software like VMware or Microsoft Virtual PC to set up a virtual test workstation where your test scripts won’t be able to do any harm. Scripting can be a great way to cut down on tedious administrative tasks and to create a more secure environment.

Featured