-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGet-DefenderStatus.ps1
380 lines (308 loc) · 14.1 KB
/
Get-DefenderStatus.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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
<#
.SYNOPSIS
This script is intended to fecth information about Microsoft Defender on all computers in a domain.
.DESCRIPTION
The script must be run from a computer in a domain. The computer must have network access to all computers in the domain and the script me be run by a user with
sufficient permissions. The script can be run from a domain controller for that purpose. When running, the script will list every computers on the domain that
run uder Windows and will query Microsoft Defender status in search for threat detections, inactive Defender processes and outdated signatures. The report is
generated in HTML and can be sent by email to a specified recipient using the -mailto switch. Unreachable computers need to be investigated and could be caused
by many things. Most frequent issues are Defender not installed, windows firewalls not allowing the query and computer is not existing anymore but has not been
cleaned up from Active Directory.
.EXAMPLE
"./Get-DefenderStatus.ps1" -MailTo [email protected]
Runs the script and sends the report as email
.EXAMPLE
"./Get-DefenderStatus.ps1" -OutputFile "C:\temp\report.html"
Runs the script and save the report in c:\temp\report.html
.INPUTS
OutputFile : specifiy the location where to save the report as a .html file
MailTo : recipient's email address that will receive the report
Computer : if specified, the script will only query this computer. By default, the script queries all computers from the domain.
.NOTES
Written by : Lucas Bablon
Version : 1.0
Link : https://github.com/lbablon
#>
#required components
#requires -Module ActiveDirectory
#params
param
(
[Parameter(Mandatory=$false, HelpMessage="Recipient address for mail notification")]
[string]$mailto,
[Parameter(Mandatory=$false, HelpMessage="Export path for csv file")]
[string]$outputfile=".\MicrosoftDefender-report.html",
[Parameter(Mandatory=$false, HelpMessage="Export path for csv file")]
[string]$computer
)
##
##VARIABLES
##
$date = Get-Date -format "dd-MM-yyyy"
$fulldate = Get-Date -format "dd-MM-yyyy hh:mm"
$hostname = hostname
$domain = $env:USERDOMAIN
#mail notification configuration
$SmtpServer = "your.smtp-server.com"
$mailsubject = "Defender for $domain - Reported on: "+$date
#html and css styling
$html = "<style>"
$html = $html + "BODY{background-color:white;font-family: Arial;}"
$html = $html + "TABLE{border: 1px;border-collapse: collapse;}"
$html = $html + "TH{border: 1px solid #ddd;padding: 15px;background-color: #300e7b;font-family: Arial;color: white;text-align: left;}"
$html = $html + "TD{border: 1px solid #ddd;padding: 15px;background-color: white;font-family: Arial;}"
$html = $html + "</style>"
#counters reset
$unreachable = 0
##
##SCRIPT
##
if ($computer)
{
$computers=$computer
Write-Output "`n"
Write-Output "Fetching $computers"
}
else
{
#list every windows computer in the domain
Write-Output "`n"
Write-Output "Listing Windows computers from domain $domain..."
$computers = Get-ADComputer -filter * -properties *| ? {$_.operatingsystem -like "Windows*"} | select name
$computerscount = ($computers | measure).count
Write-Output "$computerscount computer(s) has been found.`n"
}
# for every windows compturer in the domain and final object creation
Write-Output "Fetching Microsoft Defender information for computers..."
$i=1
$report = $computers | sort ServerName | % {
#progress bar
$completed=[math]::round(($i/$computerscount)*100)
Write-Progress -Activity "Computers requested" -Status "$completed% complete" -PercentComplete $completed
Start-Sleep -Milliseconds 300
#clear values from previous run
$error.clear()
$DefenderStatus=""
$Signatures=""
$lastfullscan=""
$lastquickscan=""
$threatdetected=""
$threatname=""
$infectedfile=""
$threatstatus=""
$infected=""
$ping=""
$computer = $_
$computername = $computer.name
#test if computer is reachable on the network
$ping = Test-Connection $computername -Count 1 -ErrorAction SilentlyContinue
#if computer responds then get windows defender information
if ($ping)
{
try
{
#get id of the last threat windows defender has detected on the computer
$ThreatID = Get-MpThreatDetection -CimSession "$computername" | Sort-Object InitialDetectionTime -Descending | select -First 1 -ExpandProperty ThreatID
#if a threat has been detected what action took defender
$ThreatActionID = Get-MpThreatDetection -CimSession "$computername" | Sort-Object InitialDetectionTime -Descending | select -First 1 -ExpandProperty ThreatStatusID
switch ( $ThreatActionID )
{
0 { $Threatstatus = 'Unknown' }
1 { $Threatstatus = 'Detected' }
2 { $Threatstatus = 'Cleaned' }
3 { $Threatstatus = 'Quarantined' }
4 { $Threatstatus = 'Removed' }
5 { $Threatstatus = 'Allowed' }
6 { $Threatstatus = 'Blocked' }
102 { $Threatstatus = 'QuarantinedFailed' }
103 { $Threatstatus = 'RemoveFailed' }
104 { $Threatstatus = 'AllowFailed' }
105 { $Threatstatus = 'Abondoned' }
107 { $Threatstatus = 'BlockedFailed' }
}
#check if windows defender is enabled on the computer
$DefenderStatus = Get-MpComputerStatus -CimSession "$computername" | select -ExpandProperty AntivirusEnabled
switch ( $DefenderStatus )
{
True { $DefenderStatus = 'Active' }
False { $DefenderStatus = 'Inactive' }
}
#check if protections are up to date on the computer
$Signatures = Get-MpComputerStatus -CimSession "$computername" | select -ExpandProperty DefenderSignaturesOutOfDate
switch ( $Signatures )
{
True { $Signatures = 'Out of date' }
False { $Signatures = 'Up to date' }
}
#last time a full scan of the computer has been performed
$lastfullscan = Get-MpComputerStatus -CimSession "$computername" | select -ExpandProperty FullScanEndTime
#last time a quick scan of the computer has been performed
$lastquickscan = Get-MpComputerStatus -CimSession "$computername" | select -ExpandProperty QuickScanEndTime
#last threat defender detected on this computer
$threatdetected = Get-MpThreatDetection -CimSession "$computername" | Sort-Object InitialDetectionTime -Descending | select -First 1 -ExpandProperty InitialDetectionTime
#threat type
$threatname = Get-MpThreat -CimSession "$computername" | where {$_threadID -like "$Threatname"} | select -ExpandProperty ThreatName
#path to infected file on the computer
$infectedfile = Get-MpThreatDetection -CimSession "$computername" | Sort-Object InitialDetectionTime -Descending | select -First 1 -ExpandProperty Resources
if ($infectedfile)
{
$infected = 1
}
}
catch
{
$erreur = 1
}
#if defender does not respond on the computer then set default values in results
if ($error)
{
$DefenderStatus = "Inactive"
$Signatures = "-"
$lastfullscan = "-"
$lastquickscan = "-"
$threatdetected = "-"
$threatname = "-"
$infectedfile = "-"
$threatstatus = "-"
$infected = 0
}
}
else
{
$DefenderStatus = "Computer cannot be reached"
$Signatures = "-"
$lastfullscan = "-"
$lastquickscan = "-"
$threatdetected = "-"
$threatname = "-"
$infectedfile = "-"
$threatstatus = "-"
$infected = 0
$unreachable++
}
#results
New-Object -TypeName PSobject -Property @{
ServerName = $computer.name
ipv4Address = $ping.IPV4Address
DefenderStatus = $DefenderStatus
IsOutOfDate = $Signatures
LastFullScan = $lastfullscan
LastQuickScan = $lastquickscan
ThreatDetected = $threatdetected
InfectedFile = $infectedfile
InfectedComputer = $infected
ThreatName = $threatname
ThreatStatus = $Threatstatus
}
$i++
}
Write-Output "Done`n"
##
##REPORT CREATION
##
#html main report
$reporthtml=$report |
select @{Name="Server name";Expression={$_.ServerName}},@{Name="IPv4 Address";Expression={$_.ipv4Address}},@{Name="Protection";Expression={$_.DefenderStatus}},@{Name="Out of date";Expression={$_.IsOutofDate}},@{Name="Last full scan";Expression={$_.LastFullScan}},@{Name="Last quick scan";Expression={$_.LastQuickScan}},@{Name="Threat detected";Expression={$_.ThreatDetected}},@{Name="Threat name";Expression={$_.ThreatName}},@{Name="Infected file";Expression={$_.InfectedFile}},@{Name="Action";Expression={$_.ThreatStatus}} |
ConvertTo-Html -Head $html
#statistics
$totalcomputers = ($computers | Measure-Object).count
$unreachablecomputers = $unreachable
$inactivecomputers = ($report | ? DefenderStatus -eq "Inactive" | Measure-Object).count
$outofdatecomputers = ($report | ? IsOutofDate -e "Out of date" | Measure-Object).count
$infectedcomputers = ($report | ? InfectedComputer -eq "1" | Measure-Object).count
$reportoverview = New-Object -TypeName PSobject -Property @{
TotalComputers = $totalcomputers
UnreachableComputers = $unreachablecomputers
InactiveComputers = $inactivecomputers
OutOfdateComputers = $outofdatecomputers
InfectedComputers = $infectedcomputers
}
#report overview as html
$reportoverview = $reportoverview |
select @{Name="Total computers";Expression={$_.TotalComputers}},@{Name="Unreachable";Expression={$_.UnreachableComputers}},@{Name="Unprotected";Expression={$_.InactiveComputers}},@{Name="Out of date";Expression={$_.OutOfDateComputers}},@{Name="Infected";Expression={$_.InfectedComputers}} |
ConvertTo-Html -head $html
#html introduction message for outputfile
$htmlintro = @"
This email has been generated on $FullDate by script 'Get-DefenderStatus.ps1' on server $hostname<br>
<br>
"@
#html overview statistics text
$htmloverview = @"
<br>
<b>Report overview explanation :</b>
<ul>
<li>Total computers : number of computer in the domain $domain that run on Windows</li>
<li>Unreachable : at the time the script runned, number of computers that could not have been reached on the network</li>
<li>Unprotected : number of computers that are reachable on the network but not protected by Windows Defender</li>
<li>Out of Date : number of computers with active protection but out of date signatures</li>
<li>Infected : number of computers where Windows Defender has detected a malicious object</li>
</ul>
"@
#instructions text
$htmlinstructions = @"
<br>
<b>The following scenarios will require further investigation on the computer :</b>
<ul>
<li>The computer cannot be reached</li>
<li>The protection is not active on the computer</li>
<li>Signatures are not up to date</li>
<li>No quick scan performed since a week ago</li>
<li>A threat has been detected on the computer</li>
</ul>
"@
#full report as html file
$htmlintro+"<br>"+$reportoverview+$htmloverview+$reporthtml+$htmlinstructions | Out-File $outputfile
Write-Output "Full report has been saved in "(Get-ChildItem $outputfile).versioninfo.filename"`n"
##
##MAIL
##
if ($mailto)
{
#display only computers with no active protection or where threats have been detected in mail body
$report = $report |
sort ServerName |
? { ($_.ThreatDetected -ne $null -and $_.ThreatDetected -notlike "-") -or $_.DefenderStatus -like "Inactive" } |
select @{Name="Server name";Expression={$_.ServerName}},@{Name="IPv4 Address";Expression={$_.ipv4Address}},@{Name="Protection";Expression={$_.DefenderStatus}},@{Name="Signatures";Expression={$_.IsOutofDate}},@{Name="Last full scan";Expression={$_.LastFullScan}},@{Name="Last quick scan";Expression={$_.LastQuickScan}},@{Name="Threat detected";Expression={$_.ThreatDetected}},@{Name="Threat name";Expression={$_.ThreatName}},@{Name="Infected file";Expression={$_.InfectedFile}},@{Name="Action";Expression={$_.ThreatStatus}} |
ConvertTo-Html -Head $html
#insert introduction into the top part of the email message
$mailtop = @"
This email has been generated on $FullDate by script 'Get-DefenderStatus.ps1' on server $hostname<br>
<br>
The Full report can be found attached to this message.
<br>
"@
#insert information into bottom part of the email messae
$mailbot = @"
<br>
<b>The following scenarios will require further investigation on the computer :</b>
<ul>
<li>The computer cannot be reached</li>
<li>The protection is not active on the computer</li>
<li>Signatures are not up to date</li>
<li>No quick scan performed since a week ago</li>
<li>A threat has been detected on the computer</li>
</ul>
<br>
<b>Report overview explanation :</b>
<ul>
<li>Total computers : number of computer in the domain $domain that run on Windows</li>
<li>Unreachable : at the time the script runned, number of computers that could not have been reached on the network</li>
<li>Unprotected : number of computers that are reachable on the network but not protected by Windows Defender</li>
<li>Out of Date : number of computers with active protection but out of date signatures</li>
<li>Infected : number of computers where Windows Defender has detected a malicious object</li>
</ul>
"@
#mail params
$MailParam = @{
Subject = $mailsubject
Body = $reportoverview+$report+$mailbot+$mailtop | Out-String
From = $mailfrom
To = $mailto
SmtpServer = $smtpserver
}
#send recap mail with full report as attachment
Send-MailMessage @MailParam -BodyAsHtml -Attachments $outputfile
Write-Output "Report has been sent by email to $mailto.`n"
}
#$top+$reportoverview+$reporthtml+$bot | Out-File $outputfile