Skip to content

Commit 76a749a

Browse files
authored
Merge pull request #1 from microsoft/master
Overhaul of reporting and event workbook (#15)
2 parents 3ac18de + 64e55bf commit 76a749a

8 files changed

Lines changed: 321 additions & 113 deletions

File tree

AaronLocker/CustomizationInputs/TrustedSigners-MsvcMfc.ps1

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,14 @@ ProductName = "MICROSOFT® VISUAL STUDIO® 2017";
194194
BinaryName = "VCRUNTIME140.DLL";
195195
}
196196

197+
@{
198+
label = "MFC runtime DLL";
199+
RuleCollection = "Dll";
200+
PublisherName = "O=MICROSOFT CORPORATION, L=REDMOND, S=WASHINGTON, C=US";
201+
ProductName = "MICROSOFT® VISUAL STUDIO® 2017";
202+
BinaryName = "MFC140.DLL";
203+
}
204+
197205
###########################################################################
198206
# Visual Studio 10
199207
###########################################################################

AaronLocker/CustomizationInputs/TrustedSigners.ps1

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ RuleCollection = "Script";
8484
PublisherName = "O=MICROSOFT CORPORATION, L=REDMOND, S=WASHINGTON, C=US";
8585
}
8686

87+
@{
88+
# During Windows upgrade, setup loads %OSDRIVE%\$WINDOWS.~BT\SOURCES\GENERALTEL.DLL
89+
label = "Allow execution of %OSDRIVE%\$WINDOWS.~BT\SOURCES\GENERALTEL.DLL during Windows upgrade";
90+
RuleCollection = "Dll";
91+
PublisherName = "O=MICROSOFT CORPORATION, L=REDMOND, S=WASHINGTON, C=US";
92+
ProductName = "MICROSOFT® WINDOWS® OPERATING SYSTEM";
93+
BinaryName = "GENERALTEL.DLL";
94+
}
95+
8796
# Uncomment this block if Google Chrome is installed to ProgramFiles.
8897
# Google Chrome runs some code in the user profile even when Chrome is installed to Program Files.
8998
# This creates publisher rules that allow those components to run.

AaronLocker/Generate-EventWorkbook.ps1

Lines changed: 154 additions & 77 deletions
Large diffs are not rendered by default.

AaronLocker/Get-AppLockerEvents.ps1

Lines changed: 68 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ See the detailed parameter descriptions for more information.
3333
3434
Output fields:
3535
36+
* Location high-level indicator of file location, such as "User profile," "Hot/removable," "ProgramData," etc.
3637
* GenericPath is the original file path with "%LOCALAPPDATA%" replacing the beginning of the path name
3738
if it matches the typical pattern "C:\Users\[username]\AppData\Local".
3839
Makes similar replacements for "%APPDATA%" or "%USERPROFILE%" if LOCALAPPDATA isn't applicable.
@@ -133,9 +134,9 @@ Get warning and error events from events exported into ForwardedEvents1.evtx and
133134
134135
.EXAMPLE
135136
136-
.\Get-AppLockerEvents.ps1 -Objects | Where-Object { $_.PublisherName -eq "-" }
137+
.\Get-AppLockerEvents.ps1 -Objects | Where-Object { $_.PublisherName -eq "[not signed]" }
137138
138-
Get warning and error events from the default AppLocker logs where target file is unsigned (publisher name is "-"). Results are output to the PowerShell pipeline as PSCustomObjects.
139+
Get warning and error events from the default AppLocker logs where target file is unsigned. Results are output to the PowerShell pipeline as PSCustomObjects.
139140
140141
.EXAMPLE
141142
@@ -359,9 +360,9 @@ if ($AllEvents)
359360
{
360361
$eventIdFilter = "$ExeDllAllowed or $MsiScriptAllowed or $PkgdAppAllowed or $ExeDllWarning or $MsiScriptWarning or $PkgdAppWarning or $ExeDllError or $MsiScriptError or $PkgdAppError"
361362
}
362-
if (($ForwardedEvents -or $EventLogNames) -and !$NoFilteredMachines)
363+
if (($ForwardedEvents -or $EventLogNames -or $EvtxLogFilePaths) -and !$NoFilteredMachines)
363364
{
364-
# If forwarded events, also pick up subscription bookmark events. (Assume that $EventLogNames implies event collector.)
365+
# If forwarded events, also pick up subscription bookmark events. (Assume that $EventLogNames implies event collector, and that $EvtxLogFilePaths might.)
365366
$eventIdFilter += " or $SubscriptionBkmrk"
366367
}
367368
$eventIdFilter = "($eventIdFilter)"
@@ -395,15 +396,20 @@ $PsPolicyTestFileHash2 = "0x96AD1146EB96877EAB5942AE0736B82D8B5E2039A80D3D693266
395396
Note: as of 17 June 2019, still seeing both hashes in different environments.
396397
#>
397398

399+
# Filepath pattern that can be replaced by %PUBLIC%
400+
$PublicPattern = "^(%OSDRIVE%|C:)\\Users\\Public\\"
398401
# Filepath pattern that can be replaced by %LOCALAPPDATA%
399402
$LocalAppDataPattern = "^(%OSDRIVE%|C:)\\Users\\[^\\]*\\AppData\\Local\\"
400403
# Filepath pattern that can be replaced by %APPDATA%
401404
$RoamingAppDataPattern = "^(%OSDRIVE%|C:)\\Users\\[^\\]*\\AppData\\Roaming\\"
402405
# Filepath pattern that can be replaced by %USERPROFILE% (after the above already done)
403406
$UserProfilePattern = "^(%OSDRIVE%|C:)\\Users\\[^\\]*\\"
407+
# FIlepath pattern that can be replaced by %PROGRAMDATA%
408+
$ProgramDataPattern = "^(%OSDRIVE%|C:)\\ProgramData\\"
404409

405410
# Tab-delimited CSV headers
406411
$headers =
412+
"Location" + "`t" +
407413
"GenericPath" + "`t" +
408414
"GenericDir" + "`t" +
409415
"OriginalPath" + "`t" +
@@ -657,38 +663,80 @@ $oLines = @(
657663
$userSid = $Properties[1].ToString()
658664
$username = SidToNameLookup -sid $userSid
659665
$sPID = $Properties[2].ToString()
660-
$pubInfo = $Properties[3].Split("\") # Publisher info, separated with backslashes
666+
if ($Properties[3] -eq "-")
667+
{
668+
$pubName = $sUnsigned
669+
$prodName = $binaryName = $filever = [string]::Empty
670+
}
671+
else
672+
{
673+
# Break up Fqdn publisher info
674+
$pubInfo = $Properties[3].Split("\") # Publisher info, separated with backslashes
675+
$pubName = $pubInfo[0] # Publisher name
676+
$prodName = $pubInfo[1] # Product name (syntax works even if array not this long)
677+
$binaryName = $pubInfo[2] # Original "binary" name (syntax works even if array not this long)
678+
$filever = $pubInfo[3] # File version (syntax works even if array not this long)
679+
}
661680

662681
if ($isAppxEvent)
663682
{
664683
$origPath = $Properties[4]
665684
$filename = $genpath = $gendir = $origPath
666685
$fileext = [string]::Empty
667686
$hash = "N/A"
687+
$location = "Packaged app"
668688
}
669689
else
670690
{
671691
# Already got $origPath earlier
672692
$filename = [System.IO.Path]::GetFileName($origPath)
673693
$fileext = [System.IO.Path]::GetExtension($origPath)
674694
# Generic path replaces user-specific paths with more generic variable syntax.
675-
# Userprofile has to be performed after more specific appdata replacements.
676-
$genpath = (($origPath -replace $LocalAppDataPattern, "%LOCALAPPDATA%\") -replace $RoamingAppDataPattern, "%APPDATA%\") -replace $UserProfilePattern, "%USERPROFILE%\"
677-
$gendir = $null
695+
# Userprofile has to be performed after more specific appdata replacements, and Public before then.
696+
$genpath = ((((( $origPath `
697+
-replace $ProgramDataPattern, "%PROGRAMDATA%\") `
698+
-replace $PublicPattern, "%PUBLIC%\") `
699+
-replace $LocalAppDataPattern, "%LOCALAPPDATA%\") `
700+
-replace $RoamingAppDataPattern, "%APPDATA%\") `
701+
-replace $UserProfilePattern, "%USERPROFILE%\")
678702
$gendir = [System.IO.Path]::GetDirectoryName($genpath)
679-
if ($null -eq $gendir)
680-
{
681-
Write-Host ($_ | fl *) -ForegroundColor Magenta
682-
}
703+
if ($gendir.StartsWith("%PUBLIC%"))
704+
{
705+
$location = "Public profile"
706+
}
707+
elseif ($gendir.StartsWith("%APPDATA%") -or $gendir.StartsWith("%LOCALAPPDATA%") -or $gendir.StartsWith("%USERPROFILE%"))
708+
{
709+
$location = "User profile"
710+
}
711+
elseif ($gendir.StartsWith("%PROGRAMDATA%"))
712+
{
713+
$location = "ProgramData"
714+
}
715+
elseif ($gendir.StartsWith("%HOT%") -or $gendir.StartsWith("%REMOVABLE%"))
716+
{
717+
$location = "Hot/Removable"
718+
}
719+
elseif ($gendir.StartsWith("\\") -or ($genPath.Substring(1, 2) -eq ":\"))
720+
{
721+
$location = "Drive/UNC"
722+
}
723+
elseif ($gendir.StartsWith("%WINDIR%") -or $gendir.StartsWith("%SYSTEM32%") -or $gendir.StartsWith("%PROGRAMFILES%"))
724+
{
725+
$location = "Windir/ProgramFiles"
726+
}
727+
elseif ($gendir.StartsWith("%OSDRIVE%"))
728+
{
729+
$location = "Non-default root"
730+
}
731+
else
732+
{
733+
$location = "Other"
734+
}
683735
}
684736

685-
# Break up Fqdn publisher info
686-
$pubName = $pubInfo[0] # Publisher name
687-
$prodName = $pubInfo[1] # Product name (syntax works even if array not this long)
688-
$binaryName = $pubInfo[2] # Original "binary" name (syntax works even if array not this long)
689-
$filever = $pubInfo[3] # File version (syntax works even if array not this long)
690-
691737
# Output tab-delimited CSV (faster to do this and then convert to objects later than to create objects to begin with)
738+
# Also, this avoids having dquotes around everything.
739+
$location + "`t" +
692740
$genpath + "`t" +
693741
$gendir + "`t" +
694742
$origPath + "`t" +
@@ -731,6 +779,7 @@ if (!$NoFilteredMachines)
731779
if (!$ReportedMachines.ContainsKey($machineName))
732780
{
733781
# Output the data as CSV
782+
<# Location #> "" + "`t" +
734783
<# GenericPath #> "" + "`t" +
735784
<# GenericDir #> "" + "`t" +
736785
<# OriginalPath #> "" + "`t" +
@@ -748,7 +797,7 @@ if (!$NoFilteredMachines)
748797
<# EventTime #> "" + "`t" +
749798
<# EventTimeXL #> "" + "`t" +
750799
<# PID #> "" + "`t" +
751-
<# EventType #> "FILTERED"
800+
<# EventType #> $sFiltered
752801
}
753802
}
754803
)

AaronLocker/Support/DownloadAccesschk.ps1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
.SYNOPSIS
33
Download Sysinternals accesschk.exe into the parent directory above this script's directory.
44
5+
TODO: Maybe add an optional target directory.
56
TODO: Maybe add a required -AcceptEula switch
67
#>
78

@@ -12,4 +13,4 @@ $targetDir = [System.IO.Directory]::GetParent($thisDir).FullName
1213
Invoke-WebRequest -Uri https://live.sysinternals.com/accesschk.exe -OutFile (Join-Path $targetDir "accesschk.exe")
1314
#TODO: Verify that Invoke-Request succeeded.
1415

15-
#TODO: Set the LastWriteTime to match
16+
#TODO: Set the LastWriteTime to match (might need to copy from UNC path instead of https to get that)

AaronLocker/Support/SupportFunctions.ps1

Lines changed: 80 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Functions to create Excel spreadsheets/workbooks:
1616
SaveWorkbook([string]$filename)
1717
AddNewWorksheet([string]$tabname)
1818
AddWorksheetFromText([string[]]$text, [string]$tabname)
19-
AddWorksheetFromCsvFile([string]$filename, [string]$tabname, [string]$CrLfEncoded)
20-
AddWorksheetFromCsvData([string[]]$csv, [string]$tabname, [string]$CrLfEncoded)
19+
AddWorksheetFromCsvFile([string]$filename, [string]$tabname, [string]$CrLfEncoded, [switch]$AddChart)
20+
AddWorksheetFromCsvData([string[]]$csv, [string]$tabname, [string]$CrLfEncoded, [switch]$AddChart)
2121
CreateExcelFromCsvFile([string]$filename, [string]$tabname, [string]$CrLfEncoded, [string]$saveAsName)
2222
2323
Function to determine whether a file is a Win32 EXE, a Win32 DLL, or neither
@@ -167,7 +167,7 @@ function AddWorksheetFromText([string[]]$text, [string]$tabname)
167167
}
168168

169169
# Add a new named worksheet from CSV data in the specified file, optionally replacing encoded CrLf with CrLf.
170-
function AddWorksheetFromCsvFile([string]$filename, [string]$tabname, [string]$CrLfEncoded)
170+
function AddWorksheetFromCsvFile([string]$filename, [string]$tabname, [string]$CrLfEncoded, [switch]$AddChart)
171171
{
172172
Write-Host "Populating tab `"$tabname`"..." -ForegroundColor Cyan
173173

@@ -199,25 +199,29 @@ function AddWorksheetFromCsvFile([string]$filename, [string]$tabname, [string]$C
199199
$global:ExcelAppInstance.ActiveWindow.SplitColumn = 0
200200
$global:ExcelAppInstance.ActiveWindow.SplitRow = 1
201201
$global:ExcelAppInstance.ActiveWindow.FreezePanes = $true
202-
$global:ExcelAppInstance.ActiveWindow.Zoom = 80
202+
#$global:ExcelAppInstance.ActiveWindow.Zoom = 80
203203

204204
$dummy = $worksheet.Range("A2").Select()
205205

206206
# Formatting: autosize column widths, then set maximum width (except on last column)
207-
$maxWidth = 40
207+
$maxWidth = 50
208208
$maxHeight = 120
209209

210210
$dummy = $worksheet.Cells.EntireColumn.AutoFit()
211-
$ix = 1
212-
# Do this until the next to last column; don't set max width on the last column
213-
while ( $worksheet.Cells(1, $ix + 1).Text.Length -gt 0)
211+
# Don't set max width if 3 columns or fewer
212+
if ($worksheet.UsedRange.Columns.Count -gt 3)
214213
{
215-
$cells = $worksheet.Cells(1, $ix)
216-
#Write-Host ($cells.Text + "; " + $cells.ColumnWidth)
217-
if ($cells.ColumnWidth -gt $maxWidth) { $cells.ColumnWidth = $maxWidth }
218-
$ix++
214+
$ix = 1
215+
# Do this until the next to last column; don't set max width on the last column
216+
while ( $worksheet.Cells(1, $ix + 1).Text.Length -gt 0)
217+
{
218+
$cells = $worksheet.Cells(1, $ix)
219+
#Write-Host ($cells.Text + "; " + $cells.ColumnWidth)
220+
if ($cells.ColumnWidth -gt $maxWidth) { $cells.ColumnWidth = $maxWidth }
221+
$ix++
222+
}
219223
}
220-
224+
221225
# Formatting: autosize row heights, then set maximum height (if CrLf replacement on)
222226
$dummy = $worksheet.Cells.EntireRow.AutoFit()
223227
# If line breaks added, limit autofit row height to
@@ -233,20 +237,77 @@ function AddWorksheetFromCsvFile([string]$filename, [string]$tabname, [string]$C
233237
}
234238
}
235239

240+
if ($AddChart)
241+
{
242+
# If lots of input data, limit number of entries in chart
243+
$chartLimit = 20
244+
245+
$oShape = $worksheet.Shapes.AddChart2(216, 57)
246+
# Have to cast from double to single to avoid runtime errors
247+
$oShape.Left = [System.Single]($worksheet.Range("D2").Left)
248+
$oShape.Top = [System.Single]($worksheet.Range("D2").Top)
249+
$oShape.Visible = $true
250+
251+
$oChartObject = $worksheet.ChartObjects(1)
252+
$oChart = $oChartObject.Chart
253+
$rowCount = $worksheet.UsedRange.Rows.Count
254+
$oChart.ChartTitle.Text = $tabname
255+
if ($rowCount -le $chartLimit)
256+
{
257+
# Use whatever data is there
258+
$oChart.SetSourceData($worksheet.UsedRange, 2) # 2 = xlColumns
259+
}
260+
else
261+
{
262+
# Build chart from top $chartLimit entries, then sum the rest into "Others"
263+
$sSeries1 = [System.Text.StringBuilder]::new()
264+
$sSeries2 = [System.Text.StringBuilder]::new()
265+
2 .. ($chartLimit+1) | ForEach-Object {
266+
if ($_ -gt 2) {
267+
[void]$sSeries1.Append(",")
268+
[void]$sSeries2.Append(",")
269+
}
270+
[void]$sSeries1.Append("`"" + $worksheet.Range('$A' + $_).Text + "`"")
271+
[void]$sSeries2.Append($worksheet.Range('$B' + $_).Text)
272+
}
273+
[void]$sSeries1.Append(",`"Others`"")
274+
[void]$sSeries2.Append("," + $global:ExcelAppInstance.WorksheetFunction.Sum($worksheet.Range('$B' + ($chartLimit+2) + ":B" + $rowCount)))
275+
$sSeries =
276+
"=SERIES(`"" + $worksheet.Range('$B1').Text + "`"," +
277+
"{" + $sSeries1.ToString() + "},{" + $sSeries2.ToString() + "},1)"
278+
#Write-Host $sSeries -ForegroundColor Green
279+
$oChart.SeriesCollection(1).Formula = $sSeries
280+
#$oChart.SetSourceData($worksheet.Range('$A$1:$B$' + ($chartLimit + 1).ToString()), 2) # 2 = xlColumns
281+
# $oChart.ChartTitle.Text = "Top " + $chartLimit.ToString() + " " + $tabname
282+
$oShape.Height = $oShape.Height * 2
283+
}
284+
285+
$oAxes = $oChart.Axes(1)
286+
$oAxes.ReversePlotOrder = $true
287+
$oAxes.TickLabelSpacing = 1
288+
289+
$dummy = $worksheet.Range("A2").Select()
290+
291+
# Release COM interface references
292+
$dummy = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($oAxes)
293+
$dummy = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($oChartObject)
294+
$dummy = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($oShape)
295+
}
296+
236297
# Release COM interface references
237298
$dummy = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($query)
238299
$dummy = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Connector)
239300
$dummy = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($worksheet)
240301
}
241302

242303
# Add a new named worksheet from in-memory CSV data (string array), optionally replacing encoded CrLf with CrLf.
243-
function AddWorksheetFromCsvData([string[]]$csv, [string]$tabname, [string]$CrLfEncoded)
304+
function AddWorksheetFromCsvData([string[]]$csv, [string]$tabname, [string]$CrLfEncoded, [switch]$AddChart)
244305
{
245306
Write-Host "Preparing data for tab `"$tabname`"..." -ForegroundColor Cyan
246307

247308
if ($null -eq $global:ExcelAppInstance) { return $null }
248309

249-
if ($null -ne $csv)
310+
if ($null -ne $csv -and $csv.Length -gt 0)
250311
{
251312
$OutputEncodingPrevious = $OutputEncoding
252313
$OutputEncoding = [System.Text.ASCIIEncoding]::Unicode
@@ -255,7 +316,7 @@ function AddWorksheetFromCsvData([string[]]$csv, [string]$tabname, [string]$CrLf
255316

256317
$csv | Out-File $tempfile -Encoding unicode
257318

258-
AddWorksheetFromCsvFile -filename $tempfile -tabname $tabname -CrLfEncoded $CrLfEncoded
319+
AddWorksheetFromCsvFile -filename $tempfile -tabname $tabname -CrLfEncoded $CrLfEncoded -AddChart:$AddChart
259320

260321
Remove-Item $tempfile
261322

@@ -428,3 +489,6 @@ Set-Variable -Name NeverExecutableExts -Option Constant -Value `
428489
".zip", ".7z", ".tar",
429490
".wav", ".wmv", ".mp3", ".mp4", ".mpg", ".mpeg", ".avi", ".mov"
430491

492+
Set-Variable -Name sNoPublisher -Option Constant -Value "-"
493+
Set-Variable -Name sUnsigned -Option Constant -Value "[not signed]"
494+
Set-Variable -Name sFiltered -Option Constant -Value "FILTERED"

Documentation/AaronLocker.docx

17 KB
Binary file not shown.

Documentation/Known Issues.docx

1.64 KB
Binary file not shown.

0 commit comments

Comments
 (0)