📜 ⬆️ ⬇️

Checking the status of antivirus in the corporate network using VBScript

Foreword


It all started with the fact that the purchased corporate solution for auditing systems did not provide the necessary information on the antivirus product used, and it worked too long, and the control panel used by the antivirus company leaves much to be desired. It was decided to use the “crutch” to collect information about antivirus programs in the domain.

The following script handles the status states of only the antiviruses used in our corporate network.

What exactly is needed and how to do it?


First of all, it was determined what to get from the antivirus and how to do it in a short period of time from the entire domain.

It was necessary to receive:
')
1) Name of the installed anti-virus
2) Is the antivirus active?
3) Are the bases updated on it?

Actually the method was found instantly - use WMI (Windows Management Instrumentation).

I had to immerse myself in the study of the very structure of WMI on a PC, this was helped by a wonderful set of WMI Tools utilities.

After that, it was necessary to decide how to interact with WMI, without hesitation, I decided to write a script in VBScript.

Debriefing


The script processes 3,500 hosts in approximately 1 hour. Actually the script code itself:

Script code
WScript.Interactive = true compid = 0 On Error Resume Next Set objDomain = GetObject("LDAP://DOMAIN/OU=Workstations,DC=DOMAIN") comps = Array() for each objDomainItem in objDomain if objDomainItem.objectClass = "Computer" then idxLast = UBound (comps) ReDim Preserve comps(idxLast + 1) comps(idxLast + 1) = objDomainItem.dNSHostName end if next Set objFS = CreateObject("Scripting.FileSystemObject") Set objNewFile = objFS.CreateTextFile("C:\TEMP\AV_Check\Reports\AV_Status_Scan_is_Running.WAIT") a = "<style>" a = a& "@import ""TableFilter/filtergrid.css"";" a = a& "BODY{background-color:Lavender ;}" a = a& "TABLE{font-size: 10pt; font-family: arial;}" a = a& "TH{background-color: buttonface; }" a = a& "</style>" objNewFile.WriteLine "<html>" objNewFile.WriteLine "<head>" objNewFile.WriteLine "<script language=""javascript"" type=""text/javascript"" src=""TableFilter/tablefilter.js""></script>" objNewFile.WriteLine "<title>AntiVirus status information</title>" objNewFile.WriteLine a & "</head><body>" objNewFile.WriteLine "<h2>AVSI -- Date: " & Now() & "</h2>" objNewFile.WriteLine "<script type=""text/javascript"">" objNewFile.WriteLine "var tableToExcel = (function() {" objNewFile.WriteLine " var uri = 'data:application/vnd.ms-excel;base64,'" objNewFile.WriteLine " , template = '<html xmlns:o=""urn:schemas-microsoft-com:office:office"" xmlns:x=""urn:schemas-microsoft-com:office:excel""><head></head><body><table>{table}</table></body></html>'" objNewFile.WriteLine " , base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) }" objNewFile.WriteLine " , format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) }" objNewFile.WriteLine "return function(table, name) {" objNewFile.WriteLine " if (!table.nodeType) table = document.getElementById(table)" objNewFile.WriteLine " var ctx = {worksheet: name || 'Worksheet', table: table.innerHTML}" objNewFile.WriteLine " window.location.href = uri + base64(format(template, ctx))" objNewFile.WriteLine "}" objNewFile.WriteLine "})()" objNewFile.WriteLine "</script>" objNewFile.WriteLine "<input type=""button"" onclick=""tableToExcel('table1', 'Export data')"" value=""Export data to Excel"">" objNewFile.WriteLine "<table id=""table1"" BORDER=""1"" width=""100%"">" objNewFile.WriteLine "<tr><th width=""2%"">id</th><th>Computer</th><th>AV Name</th><th>AV Status</th><th>AV Bases</th><th>Host Status</th></tr>" for each comp in comps compid = compid + 1 Set WshShell = WScript.CreateObject("WScript.Shell") Ping = WshShell.Run("ping -n 1 " & comp, 0, True) Select Case Ping Case 0 On Error Resume next Set oWMI = GetObject("winmgmts:\\" & comp & "\root\SecurityCenter2") On Error Resume next Set colAVItems = oWMI.ExecQuery("Select * from AntiVirusProduct") If colAVItems.count = 0 Then objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th><font color=""red"">No AntiViruses found</font></th><th><font color=""red"">Disabled</font></th><th><font color=""red"">NOT Up to Date</font></th><th><font color=""green"">Online</font></th></tr>" ElseIf colAVItems.count = 1 Then For Each AntiVirus in colAVItems If (AntiVirus.displayName) <> "Windows Defender" Then AVStatus = hex(AntiVirus.ProductState) If (AVStatus = "61000") _ OR (AVStatus = "51000") _ OR (AVStatus = "41000") Then objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th>" & AntiVirus.displayName & "</th><th><font color=""green"">Active</font></th><th><font color=""green"">Up to Date</font></th><th><font color=""green"">Online</font></th></tr>" ElseIf (AVStatus = "41010") _ OR (AVStatus = "61010") _ OR (AVStatus = "51010") Then objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th>" & AntiVirus.displayName & "</th><th><font color=""green"">Active</font></th><th><font color=""red"">NOT Up to Date</font></th><th><font color=""green"">Online</font></th></tr>" ElseIf (AVStatus = "60000") _ OR (AVStatus = "50000") _ OR (AVStatus = "40000") Then objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th>" & AntiVirus.displayName & "</th><th><font color=""red"">On Access scanning disabled!</font></th><th><font color=""green"">Up to Date</font></th><th><font color=""green"">Online</font></th></tr>" Else objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th>" & AntiVirus.displayName & "</th><th><font color=""purple"">Unknown</font></th><th><font color=""purple"">Unknown</font></th><th><font color=""green"">Online</font></th></tr>" End if End If Next End If Case 1 objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th><font color=""purple"">Unknown</font></th><th><font color=""purple"">Unknown</font></th><th><font color=""purple"">Unknown</font></th><th><font color=""red"">Offline</font></th></tr>" End Select Next objNewFile.WriteLine "</table>" objNewFile.WriteLine "<script language=""javascript"" type=""text/javascript"">" objNewFile.WriteLine "//<![CDATA[" objNewFile.WriteLine "var tableFilters = {" objNewFile.WriteLine " sort_select: true," objNewFile.WriteLine " loader: true," objNewFile.WriteLine " rows_counter: true," objNewFile.WriteLine " col_2: ""select""," objNewFile.WriteLine " col_3: ""select""," objNewFile.WriteLine " col_4: ""select""," objNewFile.WriteLine " col_5: ""select""," objNewFile.WriteLine " on_change: true," objNewFile.WriteLine " display_all_text: "" [ Show all ] ""," objNewFile.WriteLine " alternate_rows: true," objNewFile.WriteLine "}" objNewFile.WriteLine "setFilterGrid( ""table1"",tableFilters);" objNewFile.WriteLine "//]]>" objNewFile.WriteLine "</script>" objNewFile.WriteLine "<h2>End of scan: " & Now() & "</h2>" objNewFile.WriteLine "</body>" objNewFile.WriteLine "</html>" objNewFile.Close objFS.MoveFile "C:\TEMP\AV_Check\Reports\AV_Status_Scan_is_Running.WAIT", "C:\TEMP\AV_Check\Reports\AV_Status_" & Date & "_" & Hour(Now()) & "." & Minute(Now()) & ".htm" 


What actually happens? And that's exactly what happens:

1) We connect to the domain and go to the Workstations directory:

Connecting to a domain using LDAP
 Set objDomain = GetObject("LDAP://DOMAIN/OU=Workstations,DC=DOMAIN") 


2) Create an empty array in which users' PCs with the appropriate Computer class will be added:

Creating and populating an array
 for each objDomainItem in objDomain if objDomainItem.objectClass = "Computer" then idxLast = UBound (comps) ReDim Preserve comps(idxLast + 1) comps(idxLast + 1) = objDomainItem.dNSHostName end if next 


3) Create a report file. It was decided to form the report in the .htm format and accordingly form the page in the script itself:

Formation htm page
 Set objFS = CreateObject("Scripting.FileSystemObject") Set objNewFile = objFS.CreateTextFile("C:\TEMP\AV_Check\Reports\AV_Status_Scan_is_Running.WAIT") a = "<style>" a = a& "@import ""TableFilter/filtergrid.css"";" a = a& "BODY{background-color:Lavender ;}" a = a& "TABLE{font-size: 10pt; font-family: arial;}" a = a& "TH{background-color: buttonface; }" a = a& "</style>" objNewFile.WriteLine "<html>" objNewFile.WriteLine "<head>" objNewFile.WriteLine "<script language=""javascript"" type=""text/javascript"" src=""TableFilter/tablefilter.js""></script>" objNewFile.WriteLine "<title>AntiVirus status information</title>" objNewFile.WriteLine a & "</head><body>" objNewFile.WriteLine "<h2>AVSI -- Date: " & Now() & "</h2>" objNewFile.WriteLine "<script type=""text/javascript"">" objNewFile.WriteLine "var tableToExcel = (function() {" objNewFile.WriteLine " var uri = 'data:application/vnd.ms-excel;base64,'" objNewFile.WriteLine " , template = '<html xmlns:o=""urn:schemas-microsoft-com:office:office"" xmlns:x=""urn:schemas-microsoft-com:office:excel""><head></head><body><table>{table}</table></body></html>'" objNewFile.WriteLine " , base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) }" objNewFile.WriteLine " , format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) }" objNewFile.WriteLine "return function(table, name) {" objNewFile.WriteLine " if (!table.nodeType) table = document.getElementById(table)" objNewFile.WriteLine " var ctx = {worksheet: name || 'Worksheet', table: table.innerHTML}" objNewFile.WriteLine " window.location.href = uri + base64(format(template, ctx))" objNewFile.WriteLine "}" objNewFile.WriteLine "})()" objNewFile.WriteLine "</script>" objNewFile.WriteLine "<input type=""button"" onclick=""tableToExcel('table1', 'Export data')"" value=""Export data to Excel"">" objNewFile.WriteLine "<table id=""table1"" BORDER=""1"" width=""100%"">" objNewFile.WriteLine "<tr><th width=""2%"">id</th><th>Computer</th><th>AV Name</th><th>AV Status</th><th>AV Bases</th><th>Host Status</th></tr>" { ... } objNewFile.WriteLine "</table>" objNewFile.WriteLine "<script language=""javascript"" type=""text/javascript"">" objNewFile.WriteLine "//<![CDATA[" objNewFile.WriteLine "var tableFilters = {" objNewFile.WriteLine " sort_select: true," objNewFile.WriteLine " loader: true," objNewFile.WriteLine " rows_counter: true," objNewFile.WriteLine " col_2: ""select""," objNewFile.WriteLine " col_3: ""select""," objNewFile.WriteLine " col_4: ""select""," objNewFile.WriteLine " col_5: ""select""," objNewFile.WriteLine " on_change: true," objNewFile.WriteLine " display_all_text: "" [ Show all ] ""," objNewFile.WriteLine " alternate_rows: true," objNewFile.WriteLine "}" objNewFile.WriteLine "setFilterGrid( ""table1"",tableFilters);" objNewFile.WriteLine "//]]>" objNewFile.WriteLine "</script>" objNewFile.WriteLine "<h2>End of scan: " & Now() & "</h2>" objNewFile.WriteLine "</body>" objNewFile.WriteLine "</html>" objNewFile.Close 


For convenience, the HTML Table Filter Generator was used, which generates filters upon completion of the script on the generated table with the fields id, Computer, AV Name, AV Status, AV Bases.

Also added is a button for uploading a table to Excel, which I found on some forum (to be honest with it, I didn’t even bother with it and left it as it is, it works crookedly and, as practice has shown, only under FireFox).

4) The array we have formed and is stored in memory, now consider the filling of the report table. First of all, we set the counter to assign an id to each host in the array. After that we call the Shell script to check the availability of the host by sending a 1 icmp package to it. We create conditions for processing the response, Case 0 - the host is available and execute the data collection script to populate the table, Case 1 - output to the table the information that the host is not available:

Host availability check
 for each comp in comps compid = compid + 1 Set WshShell = WScript.CreateObject("WScript.Shell") Ping = WshShell.Run("ping -n 1 " & comp, 0, True) Select Case Ping Case 0 { ... } Case 1 objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th><font color=""purple"">Unknown</font></th><th><font color=""purple"">Unknown</font></th><th><font color=""purple"">Unknown</font></th><th><font color=""red"">Offline</font></th></tr>" End Select Next 


5) Check whether we have errors, and if there is, then just go to the next host. Information on Antivirus, Anti-Spyware, and Firewalls in WMI is stored in the \ root \ SecurityCenter2 directory, so we connect to it and create a WQL query, which actually pulls out the information we need about the product. We check if there is an antivirus on the host at all, and if there is, then we check if it is not Windows Defender, and even if it is, then just ignore it. Each antivirus has its own status code, I found out about it on the forum :

Checking the status of the Anti-Virus and filling the table
 On Error Resume next Set oWMI = GetObject("winmgmts:\\" & comp & "\root\SecurityCenter2") On Error Resume next Set colAVItems = oWMI.ExecQuery("Select * from AntiVirusProduct") If colAVItems.count = 0 Then objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th><font color=""red"">No AntiViruses found</font></th><th><font color=""red"">Disabled</font></th><th><font color=""red"">NOT Up to Date</font></th><th><font color=""green"">Online</font></th></tr>" ElseIf colAVItems.count = 1 Then For Each AntiVirus in colAVItems If (AntiVirus.displayName) <> "Windows Defender" Then AVStatus = hex(AntiVirus.ProductState) If (AVStatus = "61000") _ OR (AVStatus = "51000") _ OR (AVStatus = "41000") Then objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th>" & AntiVirus.displayName & "</th><th><font color=""green"">Active</font></th><th><font color=""green"">Up to Date</font></th><th><font color=""green"">Online</font></th></tr>" ElseIf (AVStatus = "41010") _ OR (AVStatus = "61010") _ OR (AVStatus = "51010") Then objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th>" & AntiVirus.displayName & "</th><th><font color=""green"">Active</font></th><th><font color=""red"">NOT Up to Date</font></th><th><font color=""green"">Online</font></th></tr>" ElseIf (AVStatus = "60000") _ OR (AVStatus = "50000") _ OR (AVStatus = "40000") Then objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th>" & AntiVirus.displayName & "</th><th><font color=""red"">On Access scanning disabled!</font></th><th><font color=""green"">Up to Date</font></th><th><font color=""green"">Online</font></th></tr>" Else objNewFile.WriteLine "<tr><th>" & compid & "</th><th>" & comp & "</th><th>" & AntiVirus.displayName & "</th><th><font color=""purple"">Unknown</font></th><th><font color=""purple"">Unknown</font></th><th><font color=""green"">Online</font></th></tr>" End if End If Next End If 


Bonus


Well, as a bonus code in Python. It creates a text file that can be used for uploading to Excel (in the form of a tab delimiter). Unfortunately, I didn’t manage to unload the list of hosts through LDAP, and when using a large list, the script crashes, maybe someone will refine it for their needs:

Code itself
 import wmi import codecs import os with open('Comp_list.txt','r') as list: file = codecs.open('text.txt', 'w', 'utf-8') file.write("Computer" + " AV Name" + " Host Status" + " AV Status" + " AV Bases\n") for comp in list: response = os.system("ping -n 1 " + comp) if response == 0: path = '//%s/root/SecurityCenter2' % comp c = wmi.WMI(moniker=path) wql = "Select * from AntiVirusProduct" wql = c.query(wql) if wql == []: file.write(comp + " no AntiVirus found" + " Online" + " Unknown" + " Unknown\n") else: for AntiVirus in wql: ProductState_in_hex = str(hex(AntiVirus.ProductState)) check_install = ProductState_in_hex[0:3] check_state = ProductState_in_hex[3:5] check_updates = ProductState_in_hex[5:7] if check_state == "10" and check_updates == "00": file.write(comp + " " + AntiVirus.displayName + " Online" + " Active" + " Up to Date\n") elif check_state == "10" and check_updates == "10": file.write(comp + " " + AntiVirus.displayName + " Online" + " Active" + " NOT Up to Date\n") elif check_state == "00" and check_updates == "00": file.write(comp + " " + AntiVirus.displayName + " Online" + " On Access scanning disabled!" + " Up to Date\n") elif check_state == "00" and check_updates == "00": file.write(comp + " " + AntiVirus.displayName + " Online" + " On Access scanning disabled!" + " NOT Up to Date\n") else: file.write(comp + " " + AntiVirus.displayName + " Online" + " Unknown state\n" + " " + check_install) else: file.write(comp + " Unknown" + " Offline" + " Unknown" + " Unknown\n") file.close() 

Source: https://habr.com/ru/post/279049/


All Articles