Security

Reset local administrator passwords with VBScript

Perform the password reset task more quickly with this script.

One nice feature of Active Directory is the ability to rename local Administrator accounts on machines using Group Policy. Invariably, when I mention this feature to a client, the next question is: “Can we change the Administrator password too?” As a Group Policy item, the answer is no. You can, however, accomplish this by using a script. An added advantage of using a script is that you can also change the Administrator password on Windows NT 4.0 machines, whereas Group Policy would affect only Windows 2000 or higher.

The script
Essentially, the script reads in a list of computer names from a file called SERVERS.TXT. For each server listed in this file, the script connects to the administrator account on that server and resets the password. All results are posted to a log file (CHANGEPWDSERVERS.LOG), including accounts that the script was unsuccessful in changing.

Downloadable script
Download this VBScript to change administrator passwords. For security reasons, it has been saved with a .txt extension. You must rename this to .vbs before you can execute it.

But just knowing what the script does isn’t enough; most administrators want to know how the script works. After all, maybe you don’t like that it pulls from a file and would rather that it pull information directly from Active Directory. Knowing how the script works allows you to customize it completely to your environment and specific needs. So let’s take a closer look.

Lines 63-80 are the meat of our script. This is where a single computer’s Administrator account gets its password reset.
63: Set objUser = GetObject("WinNT://" & strComputer & "/Administrator, user")
64: If Err.Number <> 0 Then
65:    outFile.writeline Now & vbTab & "Error connecting to " & strComputer & " --- " & Err.Description
66:    Err.Clear
67:    ErrorOccurred = True
68: Else
69:    ' Set the password for the account
70:    objUser.SetPassword newPassword
71:    objUser.SetInfo
72:    If Err.Number <> 0 Then
73:           outFile.writeline Now & vbTab & "Error setting password for " & strComputer & _
74:                  "\Administrator" & " --- " & Err.Description
75:           Err.Clear
76:           ErrorOccurred = True
77:    Else
78:           outFile.writeline (Now & vbTab & "Password set for " & strComputer & "\Administrator")
79:    End If
80: End If

Tip 1
If you’d prefer not to use a log file and would like to have output displayed to the user, replace all occurrences of outFile.writeline with wscript.echo.

Line 63 connects to the Administrator account. If the connection fails for some reason (computer is turned off, account has been renamed, etc.), an error is logged in the log file and the script moves on to the next computer. Lines 70 and 71 actually reset the password on the account. If the password reset fails (maybe the account you’re logged on with doesn’t have sufficient privileges on the remote machine), an error is logged and the script moves on.

Tip 2
If the Administrator account has been renamed, or if you have some other standard account you want to change passwords for, edit line 63 to change Administrator to the appropriate name.

Let’s see what happens when we first invoke the script.
34: On Error Resume Next
35: ErrorOccurred = False
36:
37: ' Insert WARNING here...
38: Msgbox ("WARNING: This script will change the local administrator password for every " & _
39:    "computer listed in SERVERS.TXT.  If any services are running with the local " & _
40:    "administrator credentials, those services must be updated, or they won't " & _
41:    "start on the next boot.  For this script to work, you must have administrative " & _
42:    "privileges on all of the remote computers you are changing the password for.")
43:
44: ' Get new password
45: newPassword = Inputbox ("Please enter the new password.")
46:
47: ' Open the input file and skip the header line
48: Set fsoIn = CreateObject("scripting.filesystemobject")
49: Set inFile = fsoIn.OpenTextFile(inFilename, ForReading, True)
50: inFile.Skipline
51:
52: ' Open the log file (append mode) and timestamp the entry
53: Set fsoOut = CreateObject("scripting.filesystemobject")
54: Set outFile = fsoOut.OpenTextFile(outFilename, ForAppending, True)
55: outFile.writeline (Now & vbTab & "Starting script...")

Line 34 enables us to check for errors when attempting operations. Line 35 is essentially a flag variable; at the end of the script, if this flag is still set to false, we’ll know that the entire script completed without any errors. Lines 38-42 are a warning to the script operator; it’s important to remember that if the local Administrator account is being used as a service account on any of the computers, those services won’t start up again until the service has been updated with the new password as well. Line 45 prompts the user for the new password to use; if you don’t want to be prompted, simply replace everything after the equal sign with the new password enclosed in quotes. Note that I have not implemented any type of masking of the password, so make sure no one is looking over your shoulder.

Lines 47-55 open our data and log files. You might notice that I didn’t add any error checking here. The program at this point assumes that a valid data file exists in the current directory, and that you have the ability to create and/or edit the log file. If any of this is not true, and an error occurs, the program will crash. One could certainly add the error checking and exit the program more gracefully; however, all it adds is grace, so I left it out. The error checking in other parts of the program is crucial, as the program needs to continue on after a failed computer.

Why did I skip the first line of data in line 50? To answer that question, let’s look at a convenient way to create our SERVERS.TXT data file, which is the file that lists all of the computers on which we want to reset the Administrator password. One possible way of creating this file is by manually typing in all the computer names. However, this is prone to typos, and quite cumbersome for a large number of computers. After all, would you really be looking at this script if you only had five PCs? So, a better alternative is to use the Active Directory Users and Computers snap-in. Select the Computers container, or any other container or organizational unit where you’ve stored your computer accounts. Now, right-click the container and select Export List, as shown in Figure A.

Figure A


Save the list as SERVERS.TXT, and you have your data file. The file will look similar to the following:
Name          Type          Description  
PC2           Computer      Bob’s Computer
LAPTOP        Computer      Bill’s Laptop
XPWORKSTATION Computer      Betty’s Computer

As you can see, the first line is just header information. If you choose to create your data file manually, you’ll need to either remove line 50 from the script, or add a bogus header line to the top of the data file.

Now let’s look at the part of the code where we start reading data from the file.
57: While Not inFile.AtEndOfStream
58:    arrComputerNames = Split(inFile.Readline, vbTab, -1, 1)
59:    ' arrComputerNames(0) contains the computer name
60:    strComputer = arrComputerNames(0)

Line 57 starts our loop; as long as there is another computer record in the file, we’ll continue going through the loop. Line 58 does a number of things. First, inFile.Readline reads an entire line of data from the file and returns the full string. The split function then takes the string and delimits (separates) all the data, using the tab character as the delimiter. Each piece of data is stored in a cell of an array variable called arrComputerNames. Of course, the only piece of data we’re concerned about is the first piece of data (the computer name), which is in arrComputerNames(0). This value is stored in the strComputer variable (line 60) for ease of use and understanding.

Finally, let’s look at the end of the script, when all the computers have been processed.
81: Wend
82:
83: ' Clean up the environment
84: outFile.writeline (Now & vbTab & "Ending script...")
85: inFile.close
86: outFile.close
87:
88: If ErrorOccurred Then
89:    msgbox "Script completed with errors.  Please check the log file."
90: Else
91:    MsgBox "Script completed successfully."
92: End If

Line 81 ends the loop. Line 84 makes one last entry in the log file. Line 85 and 86 close our data and log files, so they don’t get left open and potentially become corrupt. Lines 88-92 tell the user that the script is now complete, and whether errors occurred.

Note
Depending on the number of computer accounts in the data file, the script could take awhile to complete. Even though you won’t see the script doing anything, it will be working in the background. It’s important that you don’t attempt to open the files in question until you see the final message box appear.

If you do have errors, you’ll now need to go through the log file to find the computers that failed. These will have to be addressed or attempted at another time.

Tools and other information
If you haven’t done much with VBScript yet, you’re probably wondering where you can find out more about it, and what tools you should have to work with it. Your first source for VBScript is unequivocally the Microsoft TechNet Script Center. Here you will find tons of code samples, tools for automatically generating code, the scripting guide, and so much more.

Next, while Notepad works perfectly well for editing scripts, once you get serious, you’ll want an editor tailored for scripting. If you’re willing to shell out some money, the best VBScript editor available is PrimalScript. If you’re a miser like me, there’s an excellent freeware program available called VBSEditor by Koan Software. While many network administrators loathe writing code, VBScript is simple enough for everyone, yet powerful enough to make learning to write the code more than worth your time.
0 comments

Editor's Picks