-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathGet-ComputerInventoryToCSV.ps1
245 lines (213 loc) · 11.1 KB
/
Get-ComputerInventoryToCSV.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
Function Get-Inventory
{
<#
.Synopsis
Script for gathering computer inventory information.
.DESCRIPTION
Script for gathering ComputerName, Serial Number, Current User, Manufacturer, Model, MAC Address, Compliance Status, and IP Address from a list of computers.
An optional Microsoft patch KB name can be specified to check for update compliance.
Requires the WinRM service to be running on each remote computer, however works locally without.
To scan a remote machine without WinRM, use the -DCOM flag.
.EXAMPLE
Get-ComputerInventoryToCSV.ps1 -ComputerName Example-Comp1 -ComplianceKB KB4534276 -Verbose
.EXAMPLE
Get-ComputerInventoryToCSV.ps1 .\Computers.txt
.EXAMPLE
Get-ADComputer -Filter * -SearchBase "OU=TestOU,DC=TestDomain,DC=com" | Select -Property Name | Get-ComputerInventoryToCSV.ps1
.INPUTS
-ComputerName <computer name>
Input a list of computer names, either piped in as an object or a text file file with one computer name per line.
-ComplianceKB <KB number>
Input a single Microsoft KB number related to the specific patch you want to check compliance for.
.OUTPUTS
This script exports a text file in column format, and as a CSV with headers.
Format for output files is below:
"./ComputerInfo_yyyymmdd_HHMM.csv"
Computer_Name,Serial_Number,Current_User,Manufacturer,Model,MAC_Address,Compliance_Status,IP_Address
Example-Comp1,2TK45784PJ,DOMAIN\jane.doe,HP,HP ProBook 650 G2,DE:AD:BE:EF:B5:BF,Patch KB4534276 Compliant,10.10.10.01
Example-comp2,2TK34684GQ,DOMAIN\john.doe,HP,HP ProBook 650 G2,DE:AD:BE:AF:00:70,Patch KB4534276 Compliant,10.10.10.02
"./ComputerInfo_yyyymmdd_HHMM.txt"
[ ] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [ ]
Realtek Gaming 2.5GbE Family Controller : 10.10.10.3
1 IP addresses found on this system
[+] Example-Comp3 | 2TK43856ZP | DOMAIN\jose.gonzalez | Hewlett-Packard | HP ProDesk 600 G1
[ ] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [ ]
Realtek Gaming 2.5GbE Family Controller : 10.10.10.4
1 IP addresses found on this system
[+] Example-Comp4 | 2TK82744ZH | DOMAIN\bob.barker | HP | HP ProBook 650 G4
.NOTES
Authors: Beery, Christopher (https://github.com/zweilosec) & Winchester, Cassius (https://github.com/cassiuswinchester)
Created: 6 Mar 2020
Last Modified: 27 Jul 2022
.FUNCTIONALITY
Computer inventory enumeration tool
#>
#Enable -Verbose output, piping of input from other comdlets, and more
[CmdletBinding()]
#List of input parameters
Param
(
#List of ComputerNames to process
[Parameter(ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[alias('Name')] #Allows for piping in of computers by name from Active Directory (Get-ADComputer)
[string[]]
$ComputerName = $env:COMPUTERNAME,
#Specific patch to check for compliance. Use Microsoft's KB number.
#Default is "None Specified"
[string]
$ComplianceKB = "None Specified",
[Switch]
$DCOM = $false
)
#Check to make sure the user specified a ComputerName to scan, then print usage if not
#This check could be obviated if a default value of "$env:COMPUTERNAME" is used for $ComputerName above
Begin {
If (!$ComputerName)
{
Write-Host -ForegroundColor Yellow "Please specify a computername or an input file with a list of computer names to search for."
"Syntax: {0} -ComputerName <Computer Name>" -f $MyInvocation.MyCommand.Name # $MyInvocation.MyCommand.Name is used to get the script's filename as run, in case it is renamed
Write-Host "Try Get-Help {0} for more detailed help." -f $MyInvocation.MyCommand.Name
Write-Host -ForegroundColor Yellow "Requires WinRM service to be running!"
Break
}
$CSVLogFile = "./ComputerInventory_$(Get-Date -Format yyyyMMdd_HHmm).csv"
$TXTLogFile = "./ComputerInventory_$(Get-Date -Format yyyyMMdd_HHmm).txt"
[int]$ComputerCount = 0
#Set the color of the -Verbose output messages
$host.PrivateData.VerboseForegroundColor = "Cyan"
}
Process {
Write-Verbose "Getting Serial Number, Current User, Manufacturer, Model, MAC Address, Compliance Status, and IP_Address for each ComputerName"
foreach ($Computer in $ComputerName)
{
Write-Verbose "Testing if $Computer is online..."
If (Test-Connection -ComputerName $Computer -Count 2 -Quiet)
{
Write-Verbose "[+] $Computer is online."
#Add 1 to number of computers scanned
$ComputerCount ++
Write-Verbose "Beginning scan of $Computer"
#Parameter list that will be fed to Get-CimInstance
$CimParameters = @{}
#Hack to get around setting $Computer to $null if scanning localhost
$RemoteComputer = $Computer
#First, check if we are scanning the local machine
#Setting the -ComputerName property of Get-CIMInstance to $null will allow you
# to scan a local machine without WinRM enabled
if ( $Computer -eq $($env:COMPUTERNAME) )
{
$RemoteComputer = $null
}
#If the user wants to use DCOM instead of WinRM, enable this
#Do not use this branch if scanning local computer because will cause errors and not needed
if ( $DCOM -and $RemoteComputer )
{
$SessionOption = New-CimSessionOption -Protocol Dcom
#Create the remote CIM session and add to CimParameters
$RemoteSession = New-CimSession -ComputerName $RemoteComputer -SessionOption $SessionOption
$CimParameters = @{CimSession = $RemoteSession}
}
else
{
$CimParameters = @{ComputerName = $RemoteComputer}
}
#Get Serial Number
$Serial = Get-CimInstance -Class Win32_BIOS @CimParameters |
Select-Object -ExpandProperty SerialNumber
#Get Current or last logged in username
$CurrentUser = Get-CimInstance -Class Win32_ComputerSystem @CimParameters -Property UserName |
Select-Object -ExpandProperty UserName
#Get list of network adapters
$IPConfigSet = Get-CimInstance -Class Win32_NetworkAdapterConfiguration @CimParameters -Filter "IPEnabled='True'"
#Get Model of the PC
$Model = Get-CimInstance -Class Win32_ComputerSystem @CimParameters -Property Model |
Select-Object -ExpandProperty Model
#Get Manufacturer of the PC
$Manufacturer = Get-CimInstance -Class Win32_ComputerSystem @CimParameters -Property Manufacturer |
Select-Object -ExpandProperty Manufacturer
#Get MAC address of the PC
#This may need to be looked at further if using additional adapters; returns all MAC addresses, even virtual, but I'm only printing the first one in the output below
#This was created and tested in an Ethernet-only environment. If you use this in an environment where you have multiple adapters you need to track you may
#need to modify the properties of the object below and change or remove the array selection
$MACAddress = $IPConfigSet.MACAddress
#Check if user specified a patch to check for
if ($ComplianceKB -ne "None Specified")
{
#Check if the specified patch has been installed
$Compliance = if (Get-HotFix -Id "$ComplianceKB" -ComputerName $Computer -ErrorAction SilentlyContinue)
{
Write-Output "Patch $ComplianceKB Compliant" | Tee-Object -Append $TXTLogFile
}
else
{
Write-Output "Patch $ComplianceKB Non-compliant" | Tee-Object -Append $TXTLogFile
}
}
else
{
$Compliance = "None Specified"
}
Write-Output "`tAdapter Information for $($Computer):" | Tee-Object -Append $TXTLogFile
Write-Output "`t------------------------------------" | Tee-Object -Append $TXTLogFile
[String[]]$IP = @()
# Iterate and get IP addresses for each network interface
$count = 0
foreach ($IPConfig in $IPConfigSet)
{
if ($IPConfig.IPAddress)
{
$AdapterName = $IPConfig.Description
foreach ($address in $IPConfig.IPAddress)
{
Write-Output "`t$AdapterName : $address" | Tee-Object -Append $TXTLogFile
$IP += $address
$count++
}
}
}
#Write how many IP addresses were found
if ($count -eq 0)
{
Write-Output "`tNo IP addresses found.`n" | Tee-Object -Append $TXTLogFile
}
else
{
Write-Output "`t$Count IP addresses found on this system.`n" | Tee-Object -Append $TXTLogFile
}
Write-Verbose "Scan of $Computer complete."
#Create a new generic object, assigning the variables from above as object Properties
#This is needed to output to CSV with headers
[PSCustomObject]@{
Computer_Name = $Computer
Serial_Number = $Serial
Current_User = $CurrentUser
Manufacturer = $Manufacturer
Model = $Model
MAC_Address = $MACAddress #Select only the first interface (Usually built-in Ethernet)
Compliance_Status = $Compliance
IP_Address = $IP[0] #Select only the first interface (Usually built-in Ethernet)
} |
#Select the properties of the (unnamed) PSCustomObject and write to the CSV file.
Select-Object Computer_Name,Serial_Number,Current_User,Manufacturer,Model,MAC_Address,Compliance_Status,IP_Address |
Export-Csv -Append $CSVLogFile -NoTypeInformation
#Write the output to the console and text log in the following format
Write-Output "[ ] ComputerName | Serial | CurrentUser | Manufacturer | Model | MACAddress | Compliance Checks | IP [ ]" | Tee-Object -Append $TXTLogFile
Write-Output "[ ] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [ ]" | Tee-Object -Append $TXTLogFile
Write-Output "[+] $Computer | $Serial | $CurrentUser | $Manufacturer | $Model | $MACAddress | $Compliance | $($IP[0])" | Tee-Object -Append $TXTLogFile
}
#If unable to ping the computer this will be written to console and text log instead
Else
{
Write-Output "[x] Failed to ping $Computer." | Tee-Object -Append $TXTLogFile
}
}
}
End
{
Write-Verbose "Scan complete."
Write-Verbose "$ComputerCount computers were scanned."
Write-Verbose "$CSVLogFile and $TXTLogFile files created."
}
}