Collecting Workstation / Software Inventory Several Ways

Published: 2014-05-15
Last Updated: 2014-05-15 22:12:06 UTC
by Rob VandenBrink (Version: 1)
6 comment(s)

One of the "prepare for a zero day" steps that I highlighted in my story last week was to inventory your network stations, and know what's running on them.  In short, the first 2 points in the SANS 20 Critical Security Controls.  This can mean lots of things depending on your point of view.

Nmap can make an educated guess on the existence of hosts, their OS and active services:
nmap -p0-65535 -O -sV x.x.x.0/24
Good information, but not "take it to the bank" accuracy.  It'll also take a LONG time to run, you might want to trim down the number of ports being evaluated (or not).  Even if you don't take this info as gospel, it's still good supplemental info, for stations that are not in your domain.  You can kick this up a notch with Nessus (Nessus will also login to stations and enumerate software if you have credentials)

If you're running active directory, you can get a list of hosts using netdom, and a list of apps on each host using WMIC:
netdom.exe query / workstation | find /v "List of Workstations" >stations.out

(if you use "server" instead of "workstation", you'll get the server list instead)

and for each station:
wmic product list brief

But having run exactly this recently, this can take a LONG time in a larger domain.  How can we speed this up?  In a word, Powershell.
To inventory a domain:
import-module ActiveDirectory
Get-ADComputer -Filter * -Property * | Format-Table Name,OperatingSystem,OperatingSystemServicePack,OperatingSystemVersion

To inventory the software on a remote workstation:
Get-WmiObject -Class Win32_Product -computername stationnamegoeshere | Select-Object -Property Name

( see here for more info:

I collected this information first using the netdom/wmic way (hours), then using powershell (minutes).  Guess which way I'd recommend?

OK, now we've got what can easily be Megabytes of text.  How do we find out who needs some TLC?  Who's running old or unpatched software?

As an example - who has or does NOT have EMET 4.1 installed?

To check this with WMIC:

"go.cmd" (for some reason all my parent scripts are called "go")  might look like:
@echo off
for /f %%G in (stations.out) do call emetchk.cmd

and emetchk.cmd might look like:
@echo off
echo %1  >> inventory.txt
wmic /node:%1 product where "name like 'EMET%%'" get name, identifyingnumber, InstallDate >> inventory.txt

Or with powershell, the domain enumeration would look like:
import-module ActiveDirectory
Get-ADComputer -Filter * -Property * | Format-Table Name,OperatingSystem,OperatingSystemServicePack,OperatingSystemVersion  > stations.out

Then, to enumerate the actual applications (for each station in stations.out), you could either use the emetchk.cmd script above, or re-do the thing in powershell (I haven't gotten that far yet, but if any of our readers want to add a script in the comments, I'm sure folks would love to see it!) - in this example the

Get-WmiObject -Class Win32_Product -computername stationname | Select-Object -Property Name > stationname.txt


If you run this periodically, you can "diff" the results between runs to see what's changed.  Diff is standard in linux, is part of Windows these days also if you install the SFU (services for unix), or you can get a nice diff report in powershell with :

Compare-Object -ReferenceObject (Get-Content c:\path\file01.txt) -DifferenceObject (Get-Content c:\path\file02.txt)

But what about the stations who aren't in our corporate domain?  Even if your domain inventory is solid, you still must sniff network traffic using tools like PVS (from Tenable) or P0F (open source, from to identify folks who are running old versions of java, flash, air, IE, Firefox (pre-auto update versions mostly) and so on, that aren't in your domain so might get missed in your "traditional" data collection.  Normally these sniffer stations monitor traffic in and out of choke points in the network like firewalls or routers.  We covered this earlier this year here:

I hope this outlines free or close to free solutions to get these tasks done for you.  If you've found other (or better) ways to collect this info without a large cash outlay and/or a multi-week project, please share using our comment form.

Rob VandenBrink

6 comment(s)


I wouldn't trust blindly the "WMIC Product list brief" command. It apparently only shows programs installed with Microsoft Installer. That is ofcourse ok if everything is installed through packaging or with msiexec, but otherwise not everything is found in the list. I found dozens of programs on my Win7 computer's control panel add/remove software -list which were not in the wmic provided list. Some of them were security products..
I've done similar things in the past, be very careful when using the Win32_Product class.

From "This process also initiates a consistency check of packages installed, verifying and repairing the install."

That is, each application detected by the WMI query will perform a consistency check, if it fails, it will initiate an automated repair install. I've found the consistency check also puts very high load on each workstation scanned.

Additionally, Win32_Product only detects applications installed using Windows Installer. Other applications will not be listed.

I've found the best alternative is to query the registry (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall), though this has its own share of challenges and is more difficult to implement than Win32_Product.
Another useful way to do this is using the sysinternals autoruns command. The command line variant, autorunsc, makes this easy to script. It also will output in csv, will make note of whether the configured binary is actually present, (Useful in instances where a binary has been removed - say by AV, without removing the registry startup references) and will hash it for you. There's also an option to eliminate signed and verified Microsoft binaries, which reduces the output size considerably. The only downside is that when it notes a portable executable's compile date (Yes, it even extracts that!) it does so in a non-normalized local format. This can make comparison tricky for enterprises which cover multiple timezones or have multiple language-localized Windows versions.
No argument on not trusting wmic or powershell to report on all executables on a system. But if you are looking to maintain a domain and are trying to identify apps that need updates, these should all show up using either of these methods.
Sure, there are a ton of one-file exe's and other non-standard apps that system admins and security folks use, but it's up to them to maintain those the old fashioned way.
And the malware authors have their own audit and update methods :)
If you have a Windows machine on your network and are looking for a free and painless solution check out Lansweeper. Once it is supplied with the appropriate credentials and IP ranges it will find pretty much everything and figure out what is installed. BTW I am not affiliated with the company in any way; just a very satisfied user of the paid (cheap!) version in the corporate AD environment.
second above - we have found lansweeper a lot more effective in terms of usability and cost than homegrown methods.

Diary Archives