Downloads
103078.zip

You never know when you’ll be called upon to do an immediate scan of your systems for known intrusive files. Even with the best maintained and accurate antivirus applications running, there is always a possibility of something getting through. In general, antivirus updates are only as current as known viruses. Unfortunately, fixes are not available until shortly after a new intrusion has been discovered. So someone is bound to be the unwitting recipient of an attack or intrusion.

I'm sure that most of us have very secure systems and might have never had an intrusion beyond the occasional desktop virus triggered by a user opening an enticing email or downloading questionable files over the Internet. Of course we administrators are ever mindful of such events and help keep our systems safe by avoiding being logged on as administrators when performing non-administrative tasks such as opening our mail and accessing the Internet.

In any event, there is a vital need to have a system in place that can scan your computer systems at a moment’s notice for intrusive files that might have entered your systems via virus attack, worms, hackers, malware, or other means. In many businesses nowadays, there is also the need to comply with security initiatives that require us to scan for specific files on occasion even if we have not necessarily experienced problems. Aside from a very resource-intensive effort to have the IT staff frantically perform manual scans of all systems, not much is available with the major Windows systems that allow you to run these scans easily and effectively across an entire domain.

The Application

I created the Cyber Threat Scanner, which wraps two third-party utilities within a VBScript. I made the choice to use these utilities instead of pure VBScript simply to overcome the lengthy processing time that would be involved if the application were written purely in VBScript.

The first utility is a freeware package from Mythicsoft called Agent Ransack, which is the search engine beneath the Cyber Threat Scanner application's hood that scans for the files you'e looking for. You can download Agent Ransack at www.mythicsoft.com/agentransack/Page.aspx?page=download. The second utility is a public domain utility called MD5deep, which can produce MD5 hashes of files and can perform hash comparisons of the files against a list of known intrusive file hashes. You can download MD5deep.exe at md5deep.sourceforge.net/ .

To actually make this application function quickly and scan many systems at the same time it was necessary to make it a multithreaded application. This is not a true multithreaded application by definition but rather a pseudo-multithreaded application that calls a secondary script multiple times. This secondary script is what actually performs the search activity against multiple servers—and because all the secondary scripts run simultaneously, it’s loosely considered to be multithreaded.

This is an extremely sensitive and important process, and with that comes a good bit of preparation before running the main VBScript file. You must:

  • Define regular expressions of the intrusive filenames
  • Create a list of computers to be scanned
  • Create a hash list file that lists the 32-character strings of the intrusive files

To make this preparation process more streamlined and less stressful, I also created an HTML Application (HTA) called CyberScanPrep.hta that ties these preparation requirements together.Figure 1 is a snapshot of what the prep application looks like, complete with the general Help screen that the application provides. Additionally, each of the individual input areas offers detailed context-sensitive help about the specific entry.

Entering Information

In most cases, you’ll be provided with filenames and associated MD5 hashes of the intrusive files by your security department or management. When hash strings of intrusive files are provided, you can precisely determine whether a file that has the same name of an intrusive file is actually an intrusive file or not and greatly reduce the amount of work you have to perform after the scan is done. I have, however, left the application open to the possibility that you might simply need to search for files without hashes, in which case you would simply check a check box within the prep application. However, this is not the norm; you should, in most cases if not all, receive hash strings with the request to search for particular cyber threat files.

The first input box in the prep application is designed to hold the 32-character hash strings and associated filenames. To avoid mistakes and to overstate the obvious, you should always copy and paste the strings from a document that you received from security or management. After pasting a hash string, add two blank spaces and enter the associated filename. If you have more than one hash string to enter make sure you use a carriage return after each entry and then enter the next one. Continue to do this until you have entered all the hash strings.

Keep in mind that this application is limited to searching for a maximum of nine files (the maximum allowed by the free version of Agent Ransack). I personally have never had to search for more than just a few, but should you be confronted with a request to search for more than nine files, you should have another person set up this application on another machine and run the process to search for the additional files.

If for whatever reason you do not receive hash strings with the list of files to search for, make sure you put a check mark in the Do not use HashList check box. It's important to note that checking or clearing the check box determines whether the application performs a hash check against files found and the hash strings contained within the HashList.txt file. If a hash file is used, only files found that have matching hashes will be considered “Found” intrusive files.

Entering Regular Expressions

The second input box is for the list of files you want to search for. Agent Ransack allows for a great deal of flexibility when searching for files letting you enter regular expressions of the files you're looking for. For those with experience with regular expressions, this should be pretty straightforward. Just enter a regular expression for each file you want to search for. Remember that you're limited to nine entries.

For those not experienced with entering regular expressions, take a look at the example that is just above the input box. You’ll see that it starts with a caret character, followed by an open parenthesis, the filename, a forward slash, a period, the file extension, a closing parenthesis, and the dollar sign.v

The main points to understand here are:

  • The caret, which means “Begins with”
  • The open and closing parenthesis, which mean look for this phrase within the parentheses
  • The backslash is an escape character; because the period, which separates the filename and extension, holds significant functionality in regular expressions, the backslash simply means use the period literally, not as a regular expression identifier.
  • The dollar sign at the end means “Ends with”

For the most part you'll be asked to look for specific filenames, so you won’t have to have an extensive knowledge of regular expressions. Simply follow the example of entering caret, parenthesis, filename, backslash, period, file extension, close parenthesis, and dollar sign. If you do have to come up with a more complex regular expression, you can launch AgentRansack.exe and use the “Expression Builder” to establish the correct regular expression.

The next entry on the prep application requires that you create a server list. Then click the radio button indicating that you have done so.

Finally, click Perform readiness check. If you have not completed the required preparation, you'll be alerted as to what you need to do. If you have completed the preparation, you'll receive an All Set notification and you can then run the main VBScript file (MultiThreadSearch.vbs) which .Web Listing 1 shows. I don't run the scan directly from the prep application for two reasons. First, HTAs aren't well behaved when they run long processes; they are like blobs on the screen that you can't do anything with until the process completes. Second, I prefer to do a last-minute spot check of key files before launching the MultiThreadSearch script. The prep app takes care of creating the HashList.txt file that contains the hash strings and it also takes care of creating the SearchList.txt file that contains the regular expressions Agent Ransack will use.

The default multithread setting is 20, meaning it will scan up to 20 servers at a time. You can easily change this setting by editing MultiThreadSearch.vbs and adjusting the TotalThreads variable. Keep this number between 15 and 30.

The application is designed to use and create all the necessary files within one parent folder. So be sure you create an appropriate folder and copy all the downloadable files from this article into that folder. You must also download and copy AgentRansack.exe and MD5deep.exe into this same folder before running the MultiThreadSearch.vbs script.

The Process

The first phase of the process uses Agent Ransack to produce log files of files found on every drive of every server contained within the ServerList.txt file. It writes these log files to the RansackLogs folder. If one or more files is found on a server that matches the search criteria (regular expression) contained within the SearchList.txt file, the log file will have a size greater than zero. If no files are found, the log file will have a file size of zero.

The second phase steps through each of the Agent Ransack-produced log files (those with file size greater than zero), reads the filename within the text file and runs the MD5deep utility to produce a hash for the file found, compares that with the hash strings within the HashList.txt file, and writes the file size, hash string, and the filename to a hash results log file in the HashLogs folder if a matching hash string is found.

After all the Agent Ransack log files have been read and all the hash results log files have been written, the final stage of the process reads all the hash results logs, compiles all the data found within the hash results logs, and produces the Results.txt file. This is the file you'll use to determine if any intrusive files were found. If files are found, the results text files will show the server and complete paths of the files in question.

When the process finishes it creates .sav files of all significant files involved. These are copies of major contributing setup files involved with the search. A copy of the following files will be made with a .sav extension:

  • ServerList.txt
  • SearchList.txt
  • HashList.txt
  • MD5batch.cmd
  • ErrorFile.txt
  • Results.txt

When the main process is run again to do a new search, the .sav files are moved to archive folders along with the major log files from the HashLogs folder and the RansackLogs folder that were produced from the previous run, in effect producing archives of all your scans.

The archive folders are named with specific dates that coincide with the original run date. When you're considering how to construct your list of servers to scan, you can create your own ServerList.txt file or you can create a server list automatically by running another utility script I created called CreateServerList.vbs, which .Web Listing 2 shows.

It's important to note that the ServerList.txt file produced by this script will:

  1. Include cluster servers but not cluster resources
  2. Include domain controllers (DCs)
  3. Gather from hard-coded organizational units (OUs), so you'll need to edit the script and adjust this to the appropriate OU
  4. Gather any Active Directory (AD) computer where operatingSystem contains Server

The CreateServerList.vbs file will also produce a file called NoPingResponseServers.txt, which will contain any servers that could not be pinged. These servers will not be included in the ServerList.txt file. The main process (MultiThreadSearch.vbs) will also produce an ErrorFile.txt file; if any servers cannot be accessed via the script, they will be written to this file.

If you’d rather not use the prep application, it's import to note that you'll need to pay particular attention to the MD5batch.cmd file and edit it appropriately before you begin the search. The cmd file includes clear comments on which line needs to be open and which line needs to be commented out. Basically, the command file can produce an output file containing the hash string of any file passed to it. However, the cmd file contains one command that will compare the hash of a given file with a list of given hashes contained within the HashList.txt file. The cmd file also contains another command that will not compare the hash with the HashList.txt file. You can use only one of these command lines; the other must be commented out.

If the MD5batch.cmd file is set to use the HashList.txt file, be sure that you remove any previous hashes and enter the new hash or hashes into the HashList.txt file. Each hash line must start with the 32-character hash and be followed by two spaces and the filename that is associated with that hash.

Note that If you specify that you want to use a HashList.txt file within the MD5deep.cmd file, the Results.txt file will contain only file information of files that have matching hash strings. In other words, even if you find a matching filename, if the hashes don’t match, you'll not see it reported in the Results.txt file. If you do not specify that you want to use the HashList.txt file, hash strings will appear in the Results.txt file for all files found matching the filename search criteria.

If you decide not to use the prep application, you'll also need to manually create the SearchList.txt file. This file will contain the list of filenames that you want to search for; they must be expressed in the form of regular expressions. Remember, there’s a limitation of nine entries.

Depending on the machine you run the solution on and how many threads you want to spawn at one time, this application could be very resource and process intensive. You might want to set it up to run on a more powerful segregated computer. Also, be aware that the application could run for a very long time depending on how many servers you have, how many files were found, and the size of the files found.

I hope you won’t have to use this application very often. However, if you do, I’m certain that it will help make the experience more tolerable and your day at work a whole lot less stressful.

Web Listing 1
MultiThreadSearch.vbs
'*******************************************************************<br> ****************************************************** <br>
'***       !!!READ THIS BEFORE RUNNING THIS SCRIPT!!! <br>
'***<br>
'*** MultiThreadSearch.vbs - Jim Turner - Multi-threaded app to search <br> for Cyber Threat files or any files for that matter. <br>
'***<br>
'*** You must perform some prep work before running this! <br>
'***<br>
'*** Set the number of Threads you want to run at one time by modifying <br> the TotalThreads variable value. <br>
'***<br>
'*** The quickest and easiest way to do the prep work before running this <br> script is to run the CyberScanPrep.hta<br>
'*** When you have all of the data entered you can Perform the Readiness <br> Check.  When you receive the 'All Set' message<br>
'*** you can then run this script. <br>
'************************************************************************<br> *************************************************<br>
CONST ForReading = 1<br>
CONST ForWriting = 2<br>
On Error Resume Next<br><br>
TotalThreads = 20<br><br>
'*** Check for existance of MD5Deep application<br>
CheckDeep = "md5deep.exe -help"<br>
Set ShellCheck = CreateObject("WSCript.shell")<br>
ShellCheck.Run CheckDeep,2<br>
If Err.number  0 Then<br>
 Msgbox "MD5Deep.exe is not in your PATH... Terminating script!" <br>
 Wscript.Quit<br>
End If<br><br>
'*** This was originally set to test if agentransack.exe was present<br>
'*** However, it opens a splash window if the application is present. <br>
'*** It does Not effect this application, but it could cause some <br> confusion. <br>
'CheckSack = "agentransack.exe -h"<br>
'Set ShellCheck = CreateObject("WSCript.shell")<br>
'ShellCheck.Run CheckSack,2<br>
'If Err.number  0 Then<br>
' Msgbox "AgentRansack.exe is not in your PATH... Terminating script!" <br>
' Wscript.Quit<br>
'End If<br><br>
path = WScript.ScriptFullName : path = Left(path,InstrRev(path,"\")) <br><br>
Set FSO1 = CreateObject("Scripting.FileSystemObject")<br><br>
If Not FSO1.FileExists(Path & "serverlist.txt") Then<br>
 Msgbox "ServerList.txt cannot be found... Terminating script!" <br>
 Wscript.Quit<br>
End If<br><br>
'*** If MD5batch.cmd file is set to use Hashlist.txt<br>
'*** Check to make sure HashList.txt exists<br>
Set MD5cmdFile = FSO1.OpenTextFile("MD5batch.cmd",ForReading,False) <br><br>
cmdlist = MD5cmdFile.ReadAll<br>
MD5cmdFile.Close<br>
MD5cmdArray = Split(cmdList,VBCRLF) <br><br>
For Each cmdItem In MD5cmdArray<br>
 If Trim(cmdItem)  "" Then<br>
  If Instr(Ucase(cmdItem),"REM") = 0 Then<br>
   If Instr(Ucase(cmdItem),"HASHLIST.TXT")  0 Then<br>
    If Not FSO1.FileExists(Path & "Hashlist.txt") Then<br>
     Msgbox "HashList.txt cannot be found... Terminating script!" <br>
     Wscript.Quit<br>
    End If<br>
   End If<br>
  End If<br>
 End If<br>
Next<br><br>
'*** AgentRansack has limit of 9 regular expressions in its search<br>
'*** Terminate process if more than 9 exist<br>
Set SearchListFile = FSO1.OpenTextFile("SearchList.txt",ForReading,False) <br><br>
Srchlist = SearchListFile.ReadAll<br>
SearchListFile.Close<br>
SrchListArray = Split(SrchList,VBCRLF) <br>
SrchCount = 0<br><br>
For Each SrchItem In SrchListArray<br>
 If Trim(SrchItem)  "" Then<br>
  If Left(SrchItem,1)  ";" Then<br>
   SrchCount = SrchCount + 1<br>
  End If<br>
 End If<br>
Next<br><br>
If SrchCount > 9 Then<br>
 Msgbox "Too Many Regular Expressions in SearchList.txt... Limit of 9 <br> uncommented regular expressions.  Terminating Script!" <br>
 Wscript.Quit<br>
End If<br><br>
If SrchCount = 0 Then<br>
 Msgbox "No Regular Expressions in SearchList.txt. You must have at least <br> one... Terminating Script!" <br>
 Wscript.Quit<br>
End If<br><br>
'*** Set up temp db for sorting results list later on<br>
Set DRS = CreateObject("ADODB.Recordset")<br>
DRS.Fields.Append "Size",201,256,adFldIsNullable<br>
DRS.Fields.Append "Hash",201,256,adFldIsNullable<br>
DRS.Fields.Append "File",201,256,adFldIsNullable<br>
DRS.Open<br><br>
'*** Set up error listing file to capture general errors. <br>
Set ErrorFile = FSO1.CreateTextFile(Path & "\ErrorFile.txt",True) <br>
ErrorFile.Close<br><br>
'*** Setup Archive folder to store Previous Run Data<br>
'*** If RansackLogs and or HashLogs Folders exists rename them and move <br> them To Archive folder<br>
If Not FSO1.FolderExists(Path & "Archive") Then<br>
 Set newfolder = FSO1.CreateFolder(Path & "Archive")<br>
End If<br><br>
ArcDateFolder = ""<br>
If FSO1.FolderExists(Path & "RansackLogs\") Then<br>
 Set objFolder = FSO1.GetFolder(Path & "RansackLogs\")<br>
 FolderDate = objFolder.DateCreated<br>
 DateTime = Replace(FolderDate,"/","-") <br>
 DateTime = Replace(DateTime,":","-") <br><br>
 ArcDateFolder = Path & "Archive\Archive" & DateTime<br>
 Set newfolder = FSO1.CreateFolder(ArcDateFolder) <br><br>
 NewFolder2 = Path & "RansackLogs" & DateTime<br>
 FSO1.MoveFolder Path & "RansackLogs",NewFolder2        'Rename<br>
 FSO1.MoveFolder NewFolder2, ArcDateFolder & "\"        'Move<br><br>
'*** Move previous run settings files to Archive<br>
 If FSO1.FileExists(Path & "SearchList.sav") Then<br>
  FSO1.MoveFile Path & "*.sav",newfolder<br>
 End If<br><br>
End If<br><br>
FolderDate = ""<br>
DateTime = ""<br><br>
If FSO1.FolderExists(Path & "HashLogs\") Then<br>
 Set objFolder = FSO1.GetFolder(Path & "HashLogs\")<br>
 FolderDate = objFolder.DateCreated<br>
 DateTime = Replace(FolderDate,"/","-") <br>
 DateTime = Replace(DateTime,":","-") <br>
 NewFolder1 = Path & "HashLogs" & DateTime<br>
 FSO1.MoveFolder Path & "HashLogs",NewFolder1<br>
 FSO1.MoveFolder NewFolder1, ArcDateFolder & "\"<br>
End If<br><br>
'*** Create Log folders<br>
If Not FSO1.FolderExists(Path & "RansackLogs") Then<br>
 Set newfolder = FSO1.CreateFolder(Path & "RansackLogs")<br>
End If<br><br>
If Not FSO1.FolderExists(Path & "HashLogs") Then<br>
 Set newfolder = FSO1.CreateFolder(Path & "HashLogs")<br>
End If<br><br>
set SeverListFile = FSO1.OpenTextFile("serverlist.txt")<br><br>
Srvlist = SeverListFile.ReadAll<br>
SeverListFile.Close<br>
SrvListArray = Split(SrvList,VBCRLF) <br><br>
For Each SrvItem In SrvListArray<br>
 If Trim(SrvItem)  "" Then<br>
  ThreadAvailable = False<br>
  Do Until ThreadAvailable = True<br>
   Set Processes = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select <br> * From Win32_Process Where name ='cscript.exe'")<br>
   If Processes.Count
    cmd1 = "cscript.exe Ransack-It.vbs " & SrvItem<br>
    Set Shell1 = CreateObject("WSCript.shell")<br>
    Shell1.Run cmd1,2<br>
    ThreadAvailable = True<br>
   Else<br>
    Wscript.Sleep 5000<br>
   End If<br>
   set Processes = Nothing<br>
  Loop<br>
 End If<br>
Next<br><br>
'*** Wait until all cscript tasks are complete<br>
ThreadsDone = False<br>
Do Until ThreadsDone<br>
 Set Processes = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select * <br> from Win32_Process Where name ='cscript.exe'")<br>
 If Processes.Count = 0 Then<br>
  ThreadsDone = True<br>
 Else<br>
  Set Processes = Nothing<br>
  Wscript.Sleep 5000<br>
 End If<br>
Loop<br><br>
'*** Read Log files and run Hash-It process for each file found in <br> Ransack log files<br>
DataPath = Path & "RansackLogs\"<br>
Set objFolder = FSO1.GetFolder(DataPath) <br>
number = 0<br>
For Each objFile In objfolder.Files<br>
 Linearray = ""<br>
 FilePath = DataPath & objFile.Name<br>
 If objfile.size  0 Then<br>
  Set fsoRead = fso1.OpenTextFile(FilePath,ForReading,False) <br>
  Ransackinfo = fsoRead.ReadAll<br>
  fsoRead.Close<br>
  LineArray = Split(Ransackinfo,VBCRLF) <br>
  For Each line in LineArray<br>
   If Trim(line)  "" Then<br>
    FieldArray = Split(Line,VBTab) <br>
    RansackFile = FieldArray(0) <br><br>
    ThreadAvailable = False<br>
    Do Until ThreadAvailable = True<br>
     Set Processes = <br> GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select * From <br> Win32_Process Where name ='cscript.exe'")<br>
     If Processes.Count
      number = number + 1<br>
      Num = cstr(number) <br>
      cmd1 = "cscript.exe Hash-It.vbs " & " " & Chr(34) & RansackFile & <br> Chr(34) & " " & Num<br>
      Set Shell1 = CreateObject("WSCript.Shell")<br>
      Shell1.Run cmd1,2<br>
      ThreadAvailable = True<br>
     Else<br>
      Wscript.Sleep 1000<br>
     End If<br>
     Set Processes = Nothing<br>
    Loop<br>

   End If<br>
  Next<br>
 End If<br>
Next<br><br>
'*** Wait until all cscript tasks are complete<br>
ThreadsDone = False<br>
Do Until ThreadsDone<br>
 Set Processes = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("Select *<br>  from Win32_Process Where name ='cscript.exe'")<br>
 If Processes.Count = 0 Then<br>
  ThreadsDone = True<br>
 Else<br>
  Set Processes = Nothing<br>
  Wscript.Sleep 5000<br>
 End If<br>
Loop<br><br>
'*** Go Thru HashLogs and write data to text file. <br>
'*** Note, if HashList.txt is used, many of the hashlist log files will <br> contain no data. <br><br>
Set OutPutFile = FSO1.OpenTextFile(Path & "Results.txt",ForWriting,True) <br>
OutPutFile.WriteLine "File Size" & Space(3) & "Hash" & Space(30) & "File <br> Path"<br>

HashPath = Path & "HashLogs\"<br>
Set objFolder = FSO1.GetFolder(HashPath) <br>
For Each objFile In objfolder.Files<br>
 FilePath = HashPath & objFile.Name<br>
 If objfile.size  0 Then<br>
  Set fsoRead = fso1.OpenTextFile(FilePath,ForReading,False) <br>
  Hashinfo = fsoRead.Readline<br>
  FileSize = Left(Hashinfo,12) <br>
  Hash = Mid(Hashinfo,13,32) <br>
  FileString = Mid(Hashinfo,47,Len(Hashinfo)-46) <br>
  If Trim(Hashinfo)  "" Then<br>
   '*** Write data to temp db - then sort data for output to results.txt<br>  file<br>
   DRS.AddNew<br>
   DRS("Size") = FileSize<br>
   DRS("Hash") = Hash<br>
   DRS("File") = FileString<br>
   DRS.Update<br>
  End If<br>
  fsoRead.Close<br>
 End If<br>
Next<br><br>
'*** To Sort by File and then Hash<br>
'DRS.Sort = "File ASC,Hash ASC"<br><br>
'*** To Sort by Hash and then File<br>
DRS.Sort = "Hash ASC,File ASC"<br><br>
If DRS.RecordCount > 0 Then<br>
 DRS.MoveFirst<br>
End If<br>
Do while Not DRS.EOF<br>
 SizeStr = DRS.Fields.Item("Size")<br>
 HashStr = DRS.Fields.Item("Hash")<br>
 FileStr = DRS.Fields.Item("File")<br>
 OutPutFile.WriteLine SizeStr & hashstr & "  " & filestr<br>
 DRS.MoveNext <br>  
Loop<br><br>
OutPutFile.Close<br>
DRS.Close<br><br>
'*** Copy settings files to .sav files<br>
'*** These will be moved to a specific archive when process is run for a <br> new scan<br>
Const OverwriteExisting = True<br>
FSO1.CopyFile Path & "Results.txt",Path & "Results.sav",OverwriteExisting<br>
FSO1.CopyFile Path & "md5batch.cmd",Path & <br> "md5batch.sav",OverwriteExisting<br>
FSO1.CopyFile Path & "HashList.txt",Path & <br> "HashList.sav",OverwriteExisting<br>
FSO1.CopyFile Path & "SearchList.txt",Path & <br> "SearchList.sav",OverwriteExisting<br>
FSO1.CopyFile Path & "ServerList.txt",Path & <br> "ServerList.sav",OverwriteExisting<br>
FSO1.CopyFile Path & "ErrorFile.txt",Path & <br> "ErrorFile.sav",OverwriteExisting<br><br>
CreateObject("WScript.Shell").Run "Notepad " & Path & "Results.txt"

Web Listing 2
CreateServerList.vbs
'*** CreateServerList.vbs<br>
'*** Create Server List from specified OU<br>
'*** Includes Cluster servers themselves and Domain Controllers<br>
'*** but excludes Cluster Resource servers<br>
On Error Resume Next<br>
Const ForWriting = 2<br>
Const ADS_SCOPE_SUBTREE = 2<br>
Const dictKey  = 1<br>
Const dictItem = 2<br>

path = WScript.ScriptFullName : path = Left(path,InstrRev(path,"\")) <br>

strMessage = "ServerList.txt will appear in folder when process is done." <br>
strScriptName = "Creating Server List"<br>
CreateObject("WScript.Shell").Popup strMessage,7,strScriptName,vbInformation<br>

'!!! Modify the line below to point the your OU<br>

QStr = "SELECT cn FROM 'LDAP://OU=xxx,OU=xxx,DC=xxx,DC=xxx' Where <br>
objectcategory='computer' AND objectclass='computer'"<br>


Set RedAlert = CreateObject("Scripting.Dictionary")<br>


Set objNet = CreateObject("WScript.NetWork")<br>

Domain = objNet.UserDomain<br>


txtname = "ServerList"<br>

DomainServerListFile = Path & txtname & ".txt"<br>
NoPingResponseServers = Path & "NoPingResponseServers.TXT"<br>

Set objConnection = CreateObject("ADODB.Connection")<br>
Set objCommand = CreateObject("ADODB.Command")<br>
objConnection.Provider = "ADsDSOObject"<br>
objConnection.Open "Active Directory Provider"<br>
Set objCommand.ActiveConnection = objConnection<br>
objCommand.Properties("Page Size") = 1000<br>
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE<br>

objCommand.CommandText = QStr<br>
Set objRecordSet = objCommand.Execute<br>
objRecordSet.MoveFirst<br>

Do Until objRecordset.EOF<br>
 SvrName = ""<br>
 SvrName = objRecordSet.Fields("CN").Value<br>
 Set objWMIService3 = nothing<br>
 Set colItems3 = nothing<br>
 Set objWMIService3 = GetObject("winmgmts:\\.\root\CIMV2")<br>
 Set colItems3 = objWMIService3.ExecQuery _<br>

  ("Select * From Win32_PingStatus Where Address = '" & SvrName & "'")<br>
 For Each objItem3 In colItems3<br>
  If objItem3.StatusCode = 0 Then<br>
   Set objWMIService2 = Nothing<br>
   Set colItems2 = Nothing<br>
   strComputer2 = ""<br>
   Set objWMIService2 = GetObject("winmgmts:" <br>_
    & "\{impersonationLevel=impersonate\}!\\" & SvrName & "\root\cimv2")<br>

   Set colItems2 = objWMIService2.ExecQuery("Select Name from <br>
Win32_ComputerSystem",,48) 'Get Computer Name<br>
   For each objItem2 in colItems2<br>
    strComputer2 = objItem2.name 'Get Computer Name<br>

   Next<br>
   Set objWMIService2 = Nothing<br>
   Set colItems2 = Nothing<br>

   If Trim(Lcase(SvrName)) = Trim(Lcase(strComputer2)) Then<br>
    RedAlert.Add <br>
objRecordSet.Fields("CN").Value,objRecordSet.Fields("CN").Value<br>
   End If<br>
  Else<br>
   RedAlert.Add objRecordSet.Fields("CN").Value & " No <br>
Ping",objRecordSet.Fields("CN").Value & " No Ping"<br>
  End If<br>
 Next<br>
 objRecordset.MoveNext<br>
Loop<br>


'*** Domain Controllers<br>
Set objRootDSE = GetObject("LDAP://RootDSE")<br>
ConfigNC = objRootDSE.Get("configurationNamingContext")<br>

objCommand.CommandText = "SELECT ADsPath FROM 'LDAP://" & ConfigNC & "' <br>
WHERE objectClass='nTDSDSA'"  <br>
Set objRecordSet = objCommand.Execute<br>
objRecordSet.MoveFirst<br>
Do Until objRecordSet.EOF<br>
 Set objDC = GetObject(GetObject(objRecordSet.Fields("AdsPath")).Parent) <br>
 Set objSite = GetObject(GetObject(objDC.Parent).Parent) <br>
 RedAlert.Add objDC.cn,objDC.cn<br>
 objRecordSet.MoveNext<br>
Loop<br>


'*** Other servers in different OUs<br>

DNC = GetObject("LDAP://RootDSE").Get("defaultNamingContext")<br>
QStr = "SELECT cn FROM 'LDAP://" & DNC & "' Where objectcategory='computer' <br>
AND operatingSystem='*server*'"<br>

Set objConnection = CreateObject("ADODB.Connection")<br>
Set objCommand = CreateObject("ADODB.Command")<br>
objConnection.Provider = "ADsDSOObject"<br>
objConnection.Open "Active Directory Provider"<br>
Set objCommand.ActiveConnection = objConnection<br>
objCommand.Properties("Page Size") = 1000<br>
objCommand.Properties("Sort On") = "CN"<br>
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE<br>
objCommand.CommandText = QStr<br>
Set objRecordSet = objCommand.Execute<br>
objRecordSet.MoveFirst<br>


Do Until objRecordset.EOF<br>
 SvrName = ""<br>
 SvrName = objRecordSet.Fields("CN").Value<br>
 Set objWMIService3 = nothing<br>
 Set colItems3 = nothing<br>
 Set objWMIService3 = GetObject("winmgmts:\\.\root\CIMV2")<br>
 Set colItems3 = objWMIService3.ExecQuery _<br>

  ("Select * From Win32_PingStatus Where Address = '" & SvrName & "'")<br>

 For Each objItem3 In colItems3<br>
  If objItem3.StatusCode = 0 Then<br>
   Set objWMIService2 = Nothing<br>
   Set colItems2 = Nothing<br>
   strComputer2 = ""<br>

   Set objWMIService2 = GetObject("winmgmts:" _<br>
    & "\{impersonationLevel=impersonate\}!\\" & SvrName & "\root\cimv2")<br>
   Set colItems2 = objWMIService2.ExecQuery("Select Name from <br>
Win32_ComputerSystem",,48) 'Get Computer Name<br>

   For each objItem2 in colItems2<br>
    strComputer2 = objItem2.name 'Get Computer Name<br>

   Next<br>
   Set objWMIService2 = Nothing<br>
   Set colItems2 = Nothing<br>
   If Trim(Lcase(SvrName)) = Trim(Lcase(strComputer2)) Then<br>

    RedAlert.Add <br>
objRecordSet.Fields("CN").Value,objRecordSet.Fields("CN").Value<br>
   End If<br>
  Else<br>

   RedAlert.Add objRecordSet.Fields("CN").Value & " No <br>
Ping",objRecordSet.Fields("CN").Value & " No Ping"<br>
  End If<br>

 Next<br>
 objRecordset.MoveNext<br>
Loop<br>


SortDictionary RedAlert,dictItem<br>
arrKeys = RedAlert.Keys()<br>

Set fso = CreateObject("Scripting.FileSystemObject")<br>
Set txt = fso.OpenTextFile(DomainServerListFile,ForWriting,True) <br>
Set txt2 = fso.OpenTextFile(NoPingResponseServers,ForWriting,True) <br>

For i = 0 To RedAlert.Count - 1<br>
 If Instr(arrKeys(i),"No Ping") = 0 Then<br>
  txt.WriteLine arrKeys(i) <br>
 Else<br>
  txt2.WriteLine arrKeys(i) <br>
 End If<br>

Next<br>
objConnection.Close<br>
txt.Close<br>
txt2.Close<br>
MsgBox "Done Creating " & DomainServerListFile<br>

Function SortDictionary(objDict,intSort) <br>

 Dim strDict()<br>
 Dim objKey<br>
 Dim strKey,strItem<br>
 Dim X,Y,Z<br>
 Z = objDict.Count<br>
 If Z > 1 Then<br>
  ReDim strDict(Z,2) <br>
  X = 0<br>
  For Each objKey In objDict<br>
   strDict(X,dictKey)  = CStr(objKey) <br>
   strDict(X,dictItem) = CStr(objDict(objKey)) <br>
   X = X + 1<br>

  Next<br>
  For X = 0 to (Z - 2) <br>
   For Y = X to (Z - 1) <br>
    If StrComp(strDict(X,intSort),strDict(Y,intSort),vbTextCompare) > 0 Then<br>
     strKey  = strDict(X,dictKey) <br>
     strItem = strDict(X,dictItem) <br>
     strDict(X,dictKey)  = strDict(Y,dictKey) <br>
     strDict(X,dictItem) = strDict(Y,dictItem) <br>
     strDict(Y,dictKey)  = strKey<br>
     strDict(Y,dictItem) = strItem<br>
    End If<br>
  Next<br>
  Next<br>
  objDict.RemoveAll<br>
  For X = 0 to (Z - 1) <br>
   objDict.Add strDict(X,dictKey), strDict(X,dictItem) <br>
  Next<br>
 End If<br>

End Function