You receive an email message alert about a new exploit that's hitting machines worldwide. You have a good corporate firewall and are fairly confident that your virus-definition files and OS service packs and hotfixes are current. However, a corporate executive whose laptop software isn't up-to-date has taken the laptop home, worked on it there, and picked up the virus. When the executive plugs his infected laptop into the corporate network the next day, the laptop soon locates other machines that are missing the proper updates—despite your best efforts—and these too become victims and carriers of the exploit. The lesson is that no matter which deployment tool or techniques you use, your corporate network might still have a few computers without the most recent virus-definition files or hotfixes. What you need is a way to check all the computers in your environment to get a "second opinion" on their readiness to fend off the next exploit.

I've written several articles about scripting the capture of virus-definition file dates and hotfix levels on servers and desktop PCs. Although these scripts do an effective job of capturing information about servers and other "always on" nodes, they aren't as helpful with desktop PCs and laptops that are turned on and off and might not be on the network when you perform a test run. Many companies, trying to conserve electricity, encourage their employees not only to turn their PCs off at night but to turn them off at lunch and any other time the user will be away from his or her desk for any length of time. Add the number of PCs that are turned off because users have flexible work hours or are on vacation and the laptops that aren't connected because users are on a plane or visiting customers, and you might have only a moderate percentage of PCs online to be tested at any one time. You could merge the results of several tests performed over several days to try to get a more complete picture, but you still might miss some systems. A better approach is to use an active database that reflects the most recent condition of the nodes. I show you how to create such a database through the creative use of domain local groups and a computer-startup shell script.

A Creative Use for Security Groups
Traditionally, administrators associate security groups with user resource-access control. However, in Windows 2000 and later versions, security groups can contain not just users but computers. Thus, you can use security groups as a "database" to maintain computer virus-definition and hotfix information. For example, I've written a computer-startup script named RPC-PC-Condition.bat that determines whether a computer has a recent remote procedure call (RPC) hotfix and puts the computer account into one of two local security groups depending on the computer's status. The security-group approach has several advantages:

  • You can easily count the members in the OK and deficient groups to discover how many nodes need to be upgraded.
  • Using a computer-startup script ensures that the group membership results are pretty accurate for at least all the nodes that have been rebooted recently.
  • You can use Group Policy to push out a hotfix to or perform almost any other action on the deficient group's PCs at start-up.

The Computer-Startup Script
Computer-startup scripts, available in Windows Server 2003, Windows XP, and Win2K, are powerful. They can accomplish tasks such as resetting Administrator passwords, deleting unauthorized user accounts from groups on a machine, and a host of other operations that you can't perform in Windows NT 4.0. In NT 4.0, you can run logon scripts for users, but you can't run scripts automatically on a machine or group of machines upon reboot.

After you create a policy in Windows 2003, XP, or Win2K, you can create a computer-startup script that's associated with that policy. My RPC-PC-Condition computer-startup script checks an XP or Win2K computer's registry for the hotfix described in the Microsoft article "MS03-039: A Buffer Overrun in RPCSS Could Allow an Attacker to Run Malicious Programs" ( You could use the same approach and a similar script to query the registry for a different hotfix or to test for a particular virus-definition file version. Other possibilities include checking for the existence of a file, folder, or local user account that indicates the presence of a particular type of infection or exploit.

After RPC-PC-Condition determines whether the RPC hotfix registry entry exists, the batch file uses the Net Localgroup command or the cusrmgr.exe utility from the Microsoft Windows 2000 Resource Kit to put the computer account into one of two security groups based on the query outcome. If the hotfix has been installed on or removed from the node since the last query, the batch file removes the computer from its current group and places it in the other group.

The code at callout A in Listing 1 checks for the RPC hotfix KB824146 in several versions of Windows. Several versions of the reg.exe utility exist and have different command syntaxes. Computer-startup scripts run locally, and if you have the same Reg version on all nodes, you can point to the local Reg copy. If you aren't sure that all the nodes have Reg or the same Reg version, you can have RPC-PC-Condition point to a server-located copy to which Authenticated Users have Read permission. The syntax I've used is for the Win2K resource kit version of Reg. If you want to use another version of Reg, you'll need to modify the syntax.

You can use either the Net Localgroup command or the Cusrmgr utility to add the computer to the local Success or Fail group. The code in Listing 1 shows how to use Net Localgroup; the code in Listing 2 shows how to use Cusrmgr.

The advantage of using the Net Localgroup command is that it's built into Windows, so the computer doesn't need network access to a utility at a share point. Net Localgroup's main limitations are that it must run locally and it can't use computer names that are longer than 20 characters. The Net Localgroup code worked fine in my native-mode environment. However, if you encounter problems with Net Localgroup, use Cusrmgr instead. Just remember that you need to put Cusrmgr on a share point or in the same location as the script because Cusrmgr won't exist on machines unless the resource kit is installed on them. Cusrmgr is smaller than 80KB, so its network overhead should be minimal.

Computer-startup scripts add to the bootup delay that users experience when they turn on their machines. You might be able to minimize the delay by having the scripts run asynchronously (i.e., the user can log on while the scripts are running instead of having to wait until they're done). Use simple code in your computer-startup scripts, and avoid network connections if possible. In general, use computer-startup scripts strategically and sparingly. They can be an efficient way to accomplish a variety of tasks if you don't overuse them. For example, you might use RPC-PC-Condition for a week or a month to gather information, then disable it until you need to retool it to check for another hotfix.

After you get RPC-PC-Condition working, you'll want to be able to quickly display the number of Success and Fail nodes. The RPC-Metrics.bat script that Listing 3, page 4, shows uses the local.exe resource kit utility to report this information. If you need a list of the nodes in each group, the Local utility can output the group membership to the console or to a file.

Putting RPC-PC-Condition to Work
To make RPC-PC-Condition or RPC-PC-Condition-Cusrmgr work in your environment, first download the script code from the Windows Scripting Solutions Web site. (Column widths in the printed publication force us to wrap code lines, which might cause the printed code to run incorrectly.) After downloading the code, perform the following steps:

  1. If you plan to use a remote version of Reg, point to the Reg location that you want to use and set the Read permission for Authenticated Users.
  2. Create the Success and Fail Domain Local security groups.
  3. Give the Authenticated Users group Add/Remove Self as a Member permission so that the computer can add itself to or remove itself from the security groups when the computer runs the startup script. (Remember that by default, computers are members of the Authenticated Users group.) To give Authenticated Users this permission, select this group in the Microsoft Management Console (MMC) Active Directory Users and Computers snap-in, select View, and enable Advanced Features (if not already enabled) so that you can view the group's Security Properties. Then, right-click one of the two security groups you created in Step 2, select Properties, go to the Security tab, and grant Authenticated Users the ability to Add/Remove Self from the security group. Repeat this procedure for the second security group.

  4. Modify RPC-PC-Condition or RPC-PC-Condition-Cusrmgr for your environment and create a policy that has RPC-PC-Condition or RPC-PC-Condition-Cusrmgr as a computer-startup script.
  5. Link the new policy to an organizational unit (OU) that contains your test machines.
  6. Test the results by rebooting your test nodes and checking that the computers were put into one of the two security groups you created.
  7. Modify RPC-Metrics for your environment and test that it's working correctly.
  8. Deploy RPC-PC-Condition or RPC-PC-Condition-Cusrmgr and RPC-Metrics to production as needed.

RPC-PC-Condition, RPC-PC-Condition-Cusrmgr, and RPC-Metrics complement the deployment tools and techniques you already have in place and should help give you a better handle on facing exploits in the future. When you face future threats, you can quickly modify the code, set up a couple of groups, and begin to gather the information you need to protect your environment from the guys in black hats.