Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Checks a workstation regarding basic PowerShell hardening, Applocker and System
function Test-RegistryValue {
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]$Path,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]$Value
)
try {
Get-ItemProperty -Path $Path | Select-Object -ExpandProperty $Value -ErrorAction Stop | Out-Null
return $true
}
catch {
return $false
}
}
function Get-ProcessInfo() {
<#
.SYNOPSIS
Gets detailed process information via WMI
#>
# Extra work here to include process owner and commandline using WMI
Write-Verbose "Enumerating running processes..."
$owners = @{}
$commandline = @{}
gwmi win32_process |% {$owners[$_.handle] = $_.getowner().user}
gwmi win32_process |% {$commandline[$_.handle] = $_.commandline}
$procs = Get-Process | Sort-Object -property ID
$procs | ForEach-Object {$_|Add-Member -MemberType NoteProperty -Name "Owner" -Value $owners[$_.id.tostring()] -force}
$procs | ForEach-Object {$_|Add-Member -MemberType NoteProperty -Name "CommandLine" -Value $commandline[$_.id.tostring()] -force}
Return $procs
}
function Get-UserRightsAssignment{
# Fail script if we can't find SecEdit.exe
$SecEdit = Join-Path ([Environment]::GetFolderPath([Environment+SpecialFolder]::System)) "SecEdit.exe"
if ( -not (Test-Path $SecEdit) ) {
Write-Error "File not found - '$SecEdit'" -Category ObjectNotFound
exit
}
# LookupPrivilegeDisplayName Win32 API doesn't resolve logon right display
# names, so use this hashtable
$UserLogonRights = @{
"SeBatchLogonRight" = "Log on as a batch job"
"SeDenyBatchLogonRight" = "Deny log on as a batch job"
"SeDenyInteractiveLogonRight" = "Deny log on locally"
"SeDenyNetworkLogonRight" = "Deny access to this computer from the network"
"SeDenyRemoteInteractiveLogonRight" = "Deny log on through Remote Desktop Services"
"SeDenyServiceLogonRight" = "Deny log on as a service"
"SeInteractiveLogonRight" = "Allow log on locally"
"SeNetworkLogonRight" = "Access this computer from the network"
"SeRemoteInteractiveLogonRight" = "Allow log on through Remote Desktop Services"
"SeServiceLogonRight" = "Log on as a service"
}
# Create type to invoke LookupPrivilegeDisplayName Win32 API
$Win32APISignature = @'
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool LookupPrivilegeDisplayName(
string systemName,
string privilegeName,
System.Text.StringBuilder displayName,
ref uint cbDisplayName,
out uint languageId
);
'@
$AdvApi32 = Add-Type advapi32 $Win32APISignature -Namespace LookupPrivilegeDisplayName -PassThru
# Use LookupPrivilegeDisplayName Win32 API to get display name of privilege
# (except for user logon rights)
function Get-PrivilegeDisplayName {
param(
[String] $name
)
$displayNameSB = New-Object System.Text.StringBuilder 1024
$languageId = 0
$ok = $AdvApi32::LookupPrivilegeDisplayName($null, $name, $displayNameSB, [Ref] $displayNameSB.Capacity, [Ref] $languageId)
if ( $ok ) {
$displayNameSB.ToString()
}
else {
# Doesn't lookup logon rights, so use hashtable for that
if ( $UserLogonRights[$name] ) {
$UserLogonRights[$name]
}
else {
$name
}
}
}
# Outputs list of hashtables as a PSObject
function Out-Object {
param(
[System.Collections.Hashtable[]] $hashData
)
$order = @()
$result = @{}
$hashData | ForEach-Object {
$order += ($_.Keys -as [Array])[0]
$result += $_
}
New-Object PSObject -Property $result | Select-Object $order
}
# Translates a SID in the form *S-1-5-... to its account name;
function Get-AccountName {
param(
[String] $principal
)
if ( $principal[0] -eq "*" ) {
$sid = New-Object System.Security.Principal.SecurityIdentifier($principal.Substring(1))
$sid.Translate([Security.Principal.NTAccount])
}
else {
$principal
}
}
$TemplateFilename = Join-Path ([IO.Path]::GetTempPath()) ([IO.Path]::GetRandomFileName())
$LogFilename = Join-Path ([IO.Path]::GetTempPath()) ([IO.Path]::GetRandomFileName())
$StdOut = & $SecEdit /export /cfg $TemplateFilename /areas USER_RIGHTS /log $LogFilename
if ( $LASTEXITCODE -eq 0 ) {
Select-String '^(Se\S+) = (\S+)' $TemplateFilename | Foreach-Object {
$Privilege = $_.Matches[0].Groups[1].Value
$Principals = $_.Matches[0].Groups[2].Value -split ','
foreach ( $Principal in $Principals ) {
Out-Object `
@{"Privilege" = $Privilege},
@{"PrivilegeName" = Get-PrivilegeDisplayName $Privilege},
@{"Principal" = Get-AccountName $Principal}
}
}
}
else {
$OFS = ""
Write-Error "$StdOut"
}
Remove-Item $TemplateFilename,$LogFilename -ErrorAction SilentlyContinue
}
function Get-ExplicitLogonEvents {
<#
.SYNOPSIS
Gets 4648 Explicit Logon Events from Windows Event Log
Author: Lee Christensen (@tifkin_)
#>
[CmdletBinding()]
Param(
[int]
$Days = 10
)
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4648; StartTime=(Get-Date).AddDays(-$Days)} | ?{!$_.Properties[5].Value.EndsWith('$')} | %{
$Properties = $_.Properties
New-Object PSObject -Property @{
TimeCreated = $_.TimeCreated
#SubjectUserSid = $Properties[0].Value.ToString()
SubjectUserName = $Properties[1].Value
SubjectDomainName = $Properties[2].Value
#SubjectLogonId = $Properties[3].Value
#LogonGuid = $Properties[4].Value.ToString()
TargetUserName = $Properties[5].Value
TargetDomainName = $Properties[6].Value
#TargetLogonGuid = $Properties[7].Value
#TargetServerName = $Properties[8].Value
#TargetInfo = $Properties[9].Value
#ProcessId = $Properties[10].Value
ProcessName = $Properties[11].Value
IpAddress = $Properties[12].Value
#IpPort = $Properties[13].Value
}
}
}
function Get-CSDeviceGuardStatus {
<#
.SYNOPSIS
Obtains Device Guard configuration status information
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
.DESCRIPTION
Get-CSDeviceGuardStatus obtains information about available and configured Device Guard settings. This function will only work on systems where Device Guard is available - starting with Windows 10 Enterprise and Server 2016. It relies upon the ROOT\Microsoft\Windows\DeviceGuard:Win32_DeviceGuard WMI class. While returning an instance of a Win32_DeviceGuard class would suffice, it returns numeric values for settings that are not human-readable.
.PARAMETER CimSession
Specifies the CIM session to use for this cmdlet. Enter a variable that contains the CIM session or a command that creates or gets the CIM session, such as the New-CimSession or Get-CimSession cmdlets. For more information, see about_CimSessions.
.EXAMPLE
Get-CSDeviceGuardStatus
Lists the available and configured Device Guard settings.
.OUTPUTS
CimSweep.DeviceGuardStatus
Outputs objects representing available and configured Device Guard settings.
#>
[CmdletBinding()]
[OutputType('CimSweep.DeviceGuardStatus')]
param(
[Alias('Session')]
[ValidateNotNullOrEmpty()]
[Microsoft.Management.Infrastructure.CimSession[]]
$CimSession
)
BEGIN {
# If a CIM session is not provided, trick the function into thinking there is one.
if (-not $PSBoundParameters['CimSession']) {
$CimSession = ''
$CIMSessionCount = 1
} else {
$CIMSessionCount = $CimSession.Count
}
$CurrentCIMSession = 0
# Also applies to RequiredSecurityProperties
$AvailableSecurityPropertiesTable = @{
1 = 'BaseVirtualizationSupport'
2 = 'SecureBoot'
3 = 'DMAProtection'
4 = 'SecureMemoryOverwrite'
5 = 'UEFICodeReadOnly'
6 = 'SMMSecurityMitigations1.0'
}
# Also applies to UsermodeCodeIntegrityPolicyEnforcementStatus
$CodeIntegrityPolicyEnforcementStatusTable = @{
0 = 'Off'
1 = 'AuditMode'
2 = 'EnforcementMode'
}
# Also applies to SecurityServicesRunning
$SecurityServicesConfiguredTable = @{
1 = 'CredentialGuard'
2 = 'HypervisorEnforcedCodeIntegrity'
}
$VirtualizationBasedSecurityStatusTable = @{
0 = 'Off'
1 = 'Configured'
2 = 'Running'
}
}
PROCESS {
foreach ($Session in $CimSession) {
$ComputerName = $Session.ComputerName
if (-not $Session.ComputerName) { $ComputerName = 'localhost' }
# Display a progress activity for each CIM session
Write-Progress -Id 1 -Activity 'CimSweep - Device Guard configuration sweep' -Status "($($CurrentCIMSession+1)/$($CIMSessionCount)) Current computer: $ComputerName" -PercentComplete (($CurrentCIMSession / $CIMSessionCount) * 100)
$CurrentCIMSession++
$CommonArgs = @{}
if ($Session.Id) { $CommonArgs['CimSession'] = $Session }
$DeviceGuardStatus = Get-CimInstance -Namespace ROOT\Microsoft\Windows\DeviceGuard -ClassName Win32_DeviceGuard @CommonArgs
# An object will not be returned if the namespace/class do not exist
# e.g. <= Win8 and Server 2012
if ($DeviceGuardStatus) {
# Map numeric settings values to human readable strings.
# All of these properties are UInt32 values.
# The currently defined values are safe to cast to Int32
$AvailableSecurityProperties = $DeviceGuardStatus.AvailableSecurityProperties |
ForEach-Object { $AvailableSecurityPropertiesTable[[Int32] $_] }
$CodeIntegrityPolicyEnforcementStatus = $CodeIntegrityPolicyEnforcementStatusTable[[Int32] $DeviceGuardStatus.CodeIntegrityPolicyEnforcementStatus]
$RequiredSecurityProperties = $DeviceGuardStatus.RequiredSecurityProperties |
ForEach-Object { $AvailableSecurityPropertiesTable[[Int32] $_] }
$SecurityServicesConfigured = $DeviceGuardStatus.SecurityServicesConfigured |
ForEach-Object { $SecurityServicesConfiguredTable[[Int32] $_] }
$SecurityServicesRunning = $DeviceGuardStatus.SecurityServicesRunning |
ForEach-Object { $SecurityServicesConfiguredTable[[Int32] $_] }
$UsermodeCodeIntegrityPolicyEnforcementStatus = $CodeIntegrityPolicyEnforcementStatusTable[[Int32] $DeviceGuardStatus.UsermodeCodeIntegrityPolicyEnforcementStatus]
$VirtualizationBasedSecurityStatus = $VirtualizationBasedSecurityStatusTable[[Int32] $DeviceGuardStatus.VirtualizationBasedSecurityStatus]
$ObjectProperties = [Ordered] @{
PSTypeName = 'CimSweep.DeviceGuardStatus'
AvailableSecurityProperties = $AvailableSecurityProperties
CodeIntegrityPolicyEnforcementStatus = $CodeIntegrityPolicyEnforcementStatus
InstanceIdentifier = $DeviceGuardStatus.InstanceIdentifier
RequiredSecurityProperties = $RequiredSecurityProperties
SecurityServicesConfigured = $SecurityServicesConfigured
SecurityServicesRunning = $SecurityServicesRunning
UsermodeCodeIntegrityPolicyEnforcementStatus = $UsermodeCodeIntegrityPolicyEnforcementStatus
Version = $DeviceGuardStatus.Version
VirtualizationBasedSecurityStatus = $VirtualizationBasedSecurityStatus
}
if ($DeviceGuardStatus.PSComputerName) {
$ObjectProperties['PSComputerName'] = $DeviceGuardStatus.PSComputerName
}
[PSCustomObject] $ObjectProperties
}
}
}
}
function Test-SysmonInstalled {
# Find the Sysmon driver based solely off the presence of the "Rules" value.
# This is being done because the user can optionally specify a driver name other than the default: SysmonDrv
$ServiceParameters = Get-ChildItem -Path HKLM:\SYSTEM\CurrentControlSet\Services -Recurse -Include 'Parameters' -ErrorAction SilentlyContinue
$DriverParameters = $ServiceParameters | Where-Object { $_.Property -contains 'Rules' }
if (-not $DriverParameters) {
Write-Host 'Unable to locate a Sysmon driver. Either it is not installed or you do not have permissions to read the driver configuration in the registry.' -ForegroundColor Red
return
}
$FoundSysmonMatch = $False
$SysmonDriverName = $null
$SysmonServiceName = $null
$SysmonDriverParams = $null
# Just in case there is more than one instance where there is a "Rules" value, correlate it with the user-mode service to confirm.
$DriverParameters | ForEach-Object {
$CandidateDriverName = $_.PSParentPath.Split('\')[-1]
$CandidateDriverParams = $_
$CandidateUserModeServices = $ServiceParameters | Where-Object { $_.Property -contains 'DriverName' }
$CandidateUserModeServices | ForEach-Object {
$CandidateServiceName = $_.PSParentPath.Split('\')[-1]
$DriverName = ($_ | Get-ItemProperty).DriverName
# We have a matching user-mode Sysmon service and Sysmon driver.
if ($DriverName -eq $CandidateDriverName) {
$FoundSysmonMatch = $True
$SysmonDriverName = $CandidateDriverName
$SysmonServiceName = $CandidateServiceName
$SysmonDriverParams = $CandidateDriverParams | Get-ItemProperty
}
}
}
[PSCustomObject] @{
SysmonInstalled = $FoundSysmonMatch
ServiceName = $SysmonServiceName
DriverName = $SysmonDriverName
}
}
Write-Host '#########################' -BackgroundColor Black
Write-Host '## PowerShell Version ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
Write-Host 'Checking the version used by default' -ForegroundColor Black -BackgroundColor White
Write-Host ' '
$PSVersionTable.PSVersion
Write-Host ' '
Write-Host ' '
Write-Host 'Checking if PowerShellv2 is installed' -ForegroundColor Black -BackgroundColor White
Get-WindowsOptionalFeature -Online | Where-Object {$_.FeatureName -match "PowerShellv2"}
Write-Host ' '
Write-Host ' '
Write-Host '####################' -BackgroundColor Black
Write-Host '## Module Logging ##' -BackgroundColor Black
Write-Host '####################' -BackgroundColor Black
Write-Host 'Checking if PowerShell Module Logging is enabled' -ForegroundColor Black -BackgroundColor White
$regPath = "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging"
$regPathProperty = "EnableModuleLogging"
if(Test-Path -Path $regPath)
{
$check = Get-ItemProperty -Path $regPath | Select-Object -ExpandProperty $regPathProperty -ErrorAction silentlycontinue
Switch($check)
{
'1'
{
Write-Host 'Module Logging is enabled' -ForegroundColor Green
Write-Host ' '
Write-Host 'The following module names will be logged' -ForegroundColor Black -BackgroundColor White
Write-Host ' '
Get-ChildItem -Path "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ModuleLogging\" | Format-Table Property
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
'0'
{
Write-Host 'Module Logging is disabled - Explicitly deactivated' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
}
}
else{
Write-Host 'Module Logging is disabled - Not configured (Default)' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
Write-Host '##########################' -BackgroundColor Black
Write-Host '## Script Block Logging ##' -BackgroundColor Black
Write-Host '##########################' -BackgroundColor Black
Write-Host 'Checking if PowerShell Script Block Logging is enabled' -ForegroundColor Black -BackgroundColor White
$regPath = "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"
$regPathProperty = "EnableScriptBlockLogging"
if(Test-Path -Path $regPath)
{
$check = Get-ItemProperty -Path $regPath | Select-Object -ExpandProperty $regPathProperty -ErrorAction silentlycontinue
Switch($check)
{
'1'
{
Write-Host 'Script Block Logging is enabled' -ForegroundColor Green
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
'0'
{
Write-Host 'Script Block Logging is disabled - Explicitly deactivated' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
}
}
else{
Write-Host 'Script Block Logging is disabled - Not configured (Default)' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
Write-Host '#########################' -BackgroundColor Black
Write-Host '## Transcript Logging ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
Write-Host 'Checking if PowerShell Transcript Logging is enabled' -ForegroundColor Black -BackgroundColor White
$regPath = "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\Transcription"
$regPathProperty = "EnableTranscripting"
if(Test-Path -Path $regPath)
{
$check = Get-ItemProperty -Path $regPath | Select-Object -ExpandProperty $regPathProperty -ErrorAction silentlycontinue
Switch($check)
{
'1'
{
## Enabled
Write-Host 'Transcript Logging is enabled' -ForegroundColor Green
Write-Host ' '
Write-Host ' '
## Check Invocation Header
if((Test-RegistryValue -Path $regPath -Value EnableInvocationHeader)){
Write-Host 'Invocation Header is set' -ForegroundColor Green
' '
} else {
Write-Host 'Invocation Header is not set' -ForegroundColor Red
' '
}
## Output Directory
if((Test-RegistryValue -Path $regPath -Value OutputDirectory)) {
' '
'Output Directory is set to:'
$outputDirectory=(Get-ItemProperty -Path "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\Transcription\" -Name "OutputDirectory").OutputDirectory
if(([string]::IsNullOrEmpty($outputDirectory))){
Write-Host '(Default) Windows PowerShell will record transcript output to each users My Documents directory' -ForegroundColor Yellow
Write-Host ' '
} else {
Write-Host $outputDirectory
Write-Host ' '
}
} else {
Write-Host 'Output Directory is not set' -ForegroundColor Red
}
}
'0'
{
Write-Host 'Transcript Logging is disabled - Explicitly deactivated' -fore
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
}
}
else
{
Write-Host 'Transcript Logging is disabled - Not configured (Default)' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
Write-Host '#########################' -BackgroundColor Black
Write-Host '## Language Mode ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
Write-Host 'Checking if ConstrainedLanguage Mode is active' -ForegroundColor Black -BackgroundColor White
Switch($ExecutionContext.SessionState.LanguageMode)
{
'FullLanguage'
{
Write-Host 'Constrained Language Mode is not active' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
'ConstrainedLanguage'
{
Write-Host 'Constrained Language Mode is active' -ForegroundColor Green
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
}
Write-Host '#########################' -BackgroundColor Black
Write-Host '## Sysmon ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
Write-Host 'Checking if Sysmon is installed' -ForegroundColor Black -BackgroundColor White
Test-SysmonInstalled
Write-Host ' '
Write-Host ' '
Write-Host ' '
Write-Host '#########################' -BackgroundColor Black
Write-Host '## LSA Protection ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
Write-Host 'Checking if LSA Protection is enabled' -ForegroundColor Black -BackgroundColor White
## LSA Protection
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"
$regPathProperty = "RunAsPPL"
if((Test-RegistryValue -Path $regPath -Value $regPathProperty)){
$check = Get-ItemProperty -Path $regPath | Select-Object -ExpandProperty $regPathProperty -ErrorAction silentlycontinue
Switch($check)
{
'1'
{
Write-Host 'LSA Protection is enabled' -ForegroundColor Green
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
'0'
{
Write-Host 'LSA Protection is explicitly disabled' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
}
} else {
Write-Host 'LSA Protection is not enabled' -ForegroundColor Red
' '
}
## WDIGEST
# https://www.praetorian.com/blog/mitigating-mimikatz-wdigest-cleartext-credential-theft/
Write-Host '#########################' -BackgroundColor Black
Write-Host '## WDigest ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
Write-Host 'Checking if WDigest is enabled' -ForegroundColor Black -BackgroundColor White
$regPath = "HKLM:\\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest"
$regPathProperty = "UseLogonCredential"
if((Test-RegistryValue -Path $regPath -Value $regPathProperty)){
$check = Get-ItemProperty -Path $regPath | Select-Object -ExpandProperty $regPathProperty -ErrorAction silentlycontinue
Switch($check)
{
'1'
{
Write-Host 'WDigest is enabled' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
'0'
{
Write-Host 'WDigest is not enabled' -ForegroundColor Green
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
}
} else {
Write-Host 'WDigest is not enabled' -ForegroundColor Green
' '
}
Write-Host '#########################' -BackgroundColor Black
Write-Host '## AppLocker ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
Write-Host 'Checking if Applocker Policy' -ForegroundColor Black -BackgroundColor White
Get-AppLockerPolicy -Effective | Format-List
Write-Host 'Exporting AppLocker Policy to CSV' -ForegroundColor Black -BackgroundColor White
Get-AppLockerPolicy -Effective -Xml | Set-Content ('.\applocker.xml')
#PS C:\> (Get-AppLockerPolicy -Local).RuleCollections
#PS C:\> Get-AppLockerPolicy -Effective -Xml
#PS C:\> Get-ChildItem -Path HKLM:Software\Policies\Microsoft\Windows\SrpV2 -Recurse
#PS C:\> Get-AppLockerPolicy -Domain -LDAP "LDAP:// DC13.Contoso.com/CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=Policies,CN=System,DC=Contoso,DC=com
Write-Host '#########################' -BackgroundColor Black
Write-Host '## Device Guard ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
Write-Host 'Checking if Device Guard is in use' -ForegroundColor Black -BackgroundColor White
Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard | Format-List
$SecurityProps = Get-CSDeviceGuardStatus
$SecurityProps.AvailableSecurityProperties
Write-Host '###########################' -BackgroundColor Black
Write-Host '## Credential Guard ##' -BackgroundColor Black
Write-Host '###########################' -BackgroundColor Black
Write-Host 'Checking if Credential Guard is in use' -ForegroundColor Black -BackgroundColor White
# https://github.com/MicrosoftDocs/windows-itpro-docs/blob/public/windows/security/identity-protection/credential-guard/credential-guard-manage.md
$DevGuard = Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard
$check = $DevGuard.SecurityServicesConfigured -contains 1 -and $DevGuard.SecurityServicesRunning -contains 1
Switch($check)
{
$true
{
Write-Host 'Credential Guard is running' -ForegroundColor Green
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
$false
{
Write-Host 'Credential Guard is not running' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
}
Write-Host '#########################' -BackgroundColor Black
Write-Host '## Windows Firewall ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
Write-Host 'Checking Firewall State' -ForegroundColor Black -BackgroundColor White
netsh advfirewall show all state
Write-Host 'Exporting Windows Firewall Rules to CSV-file'
#Get-NetFirewallRule | Select-Object -Property Name, DisplayName, DisplayGroup,
#@{Name='Protocol';Expression={($PSItem | Get-NetFirewallPortFilter).Protocol}},
#@{Name='LocalPort';Expression={($PSItem | Get-NetFirewallPortFilter).LocalPort}},
#@{Name='RemotePort';Expression={($PSItem | Get-NetFirewallPortFilter).RemotePort}},
#@{Name='RemoteAddress';Expression={($PSItem | Get-NetFirewallAddressFilter).RemoteAddress}}, Enabled, Profile, Direction, Action |
#Export-Csv -NoTypeInformation -Path .\windows-firewall-rules.csv
Write-Host '#########################' -BackgroundColor Black
Write-Host '## LLMNR ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
Write-Host 'Check if LLMNR is enabled' -ForegroundColor Black -BackgroundColor White
$regPath = "HKLM:\\Software\Policies\Microsoft\Windows NT\DNSClient"
$regPathProperty = "EnableMulticast"
if((Test-RegistryValue -Path $regPath -Value $regPathProperty)){
$check = Get-ItemProperty -Path $regPath | Select-Object -ExpandProperty $regPathProperty -ErrorAction silentlycontinue
Switch($check)
{
'1'
{
Write-Host 'LLMNR is enabled' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
'0'
{
Write-Host 'LLMNR is disabled' -ForegroundColor Green
Write-Host ' '
Write-Host ' '
Write-Host ' '
}
}
} else {
Write-Host 'LLMNR is disabled' -ForegroundColor Green
' '
}
Write-Host '#########################' -BackgroundColor Black
Write-Host '## NBNS ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
Write-Host 'Check if NBNS is enabled' -ForegroundColor Black -BackgroundColor White
$regPath="HKLM:SYSTEM\CurrentControlSet\services\NetBT\Parameters\Interfaces"
Get-ChildItem $regPath | foreach { get-ItemProperty -Path "$regPath\$($_.pschildname)" -Name NetbiosOptions} | Format-Table NetBiosOptions,@{Name='Interf
ace';Expression={$_.PSChildname}}
Write-Host '0 - Configuration via DHCP' -ForegroundColor Red
Write-Host '1 - Specifies that NetBIOS is enabled.' -ForegroundColor Red
Write-Host '2 - NetBIOS is disabled' -ForegroundColor Green
Write-Host ' '
Write-Host ' '
Write-Host ' '
# Mitigation:
# $regkey = "HKLM:SYSTEM\CurrentControlSet\services\NetBT\Parameters\Interfaces"
# Get-ChildItem $regkey |foreach { Set-ItemProperty -Path "$regkey\$($_.pschildname)" -Name NetbiosOptions -Value 2 -Verbose}
# http://woshub.com/how-to-disable-netbios-over-tcpip-and-llmnr-using-gpo/#h2_4
# Windows Defender
# https://www.windowscentral.com/how-manage-microsoft-defender-antivirus-powershell-windows-10
Write-Host '#########################' -BackgroundColor Black
Write-Host '# Windows Defender ##' -BackgroundColor Black
Write-Host '#########################' -BackgroundColor Black
$defenderPreferences = Get-MpPreference
if(($defenderDetails.RealTimeProtectionEnabled)){
Write-Host 'Defender is active' -ForegroundColor Green
' '
' '
} else {
Write-Host 'Defender is not active' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
}
Write-Host '##########################' -BackgroundColor Black
Write-Host '## Installed Software ##' -BackgroundColor Black
Write-Host '##########################' -BackgroundColor Black
Write-Host 'Getting a list of installed Software:' -ForegroundColor Black -BackgroundColor White
Get-WMIObject -Query "SELECT * FROM Win32_Product" | Select-Object Name,Version,Vendor,InstallLocation,InstallDate | format-table
Write-Host ' '
Write-Host ' '
Write-Host 'Exporting installed software to CSV-File'
Get-WMIObject -Query "SELECT * FROM Win32_Product" | Select-Object Name,Version,Vendor,InstallLocation,InstallDate | Export-Csv -NoTypeInformation ".\installed-software.csv"
Write-Host '##################################' -BackgroundColor Black
Write-Host '## Listening network services ##' -BackgroundColor Black
Write-Host '##################################' -BackgroundColor Black
# Make a lookup table by process ID
$Processes = @{}
Get-Process -IncludeUserName | ForEach-Object {
$Processes[$_.Id] = $_
}
# Query Listening TCP Daemons
Write-Host "TCP Listening Services" -ForegroundColor Black -BackgroundColor White
Get-NetTCPConnection |
Where-Object { $_.LocalAddress -eq "0.0.0.0" -and $_.State -eq "Listen" } |
Select-Object LocalAddress,
LocalPort,
@{Name="PID"; Expression={ $_.OwningProcess }},
@{Name="UserName"; Expression={ $Processes[[int]$_.OwningProcess].UserName }},
@{Name="ProcessName"; Expression={ $Processes[[int]$_.OwningProcess].ProcessName }},
@{Name="Path"; Expression={ $Processes[[int]$_.OwningProcess].Path }} |
Sort-Object -Property LocalPort, UserName |
Format-Table -AutoSize
Get-NetTCPConnection |
Where-Object { $_.LocalAddress -eq "0.0.0.0" -and $_.State -eq "Listen" } |
Select-Object LocalAddress,
LocalPort,
@{Name="PID"; Expression={ $_.OwningProcess }},
@{Name="UserName"; Expression={ $Processes[[int]$_.OwningProcess].UserName }},
@{Name="ProcessName"; Expression={ $Processes[[int]$_.OwningProcess].ProcessName }},
@{Name="Path"; Expression={ $Processes[[int]$_.OwningProcess].Path }} |
Sort-Object -Property LocalPort, UserName | Export-Csv -NoTypeInformation ".\network-services-tcp.csv"
# Query Listening UDP Daemons
Write-Host "UDP Listening Services" -ForegroundColor Black -BackgroundColor White
Get-NetUDPEndpoint |
Where-Object { $_.LocalAddress -eq "0.0.0.0" } |
Select-Object LocalAddress,
LocalPort,
@{Name="PID"; Expression={ $_.OwningProcess }},
@{Name="UserName"; Expression={ $Processes[[int]$_.OwningProcess].UserName }},
@{Name="ProcessName"; Expression={ $Processes[[int]$_.OwningProcess].ProcessName }},
@{Name="Path"; Expression={ $Processes[[int]$_.OwningProcess].Path }} |
Sort-Object -Property LocalPort, UserName |
Format-Table -AutoSize
Write-Host "UDP Listening Services" -ForegroundColor Black -BackgroundColor White
Get-NetUDPEndpoint |
Where-Object { $_.LocalAddress -eq "0.0.0.0" } |
Select-Object LocalAddress,
LocalPort,
@{Name="PID"; Expression={ $_.OwningProcess }},
@{Name="UserName"; Expression={ $Processes[[int]$_.OwningProcess].UserName }},
@{Name="ProcessName"; Expression={ $Processes[[int]$_.OwningProcess].ProcessName }},
@{Name="Path"; Expression={ $Processes[[int]$_.OwningProcess].Path }} |
Sort-Object -Property LocalPort, UserName | Export-Csv -NoTypeInformation ".\network-services-udp.csv"
Write-Host '###################' -BackgroundColor Black
Write-Host '## Local Users ##' -BackgroundColor Black
Write-Host '###################' -BackgroundColor Black
Write-Host "Local Users and their group memberships" -ForegroundColor Black -BackgroundColor White
Get-LocalUser |
ForEach-Object {
$user = $_
return [PSCustomObject]@{
"User" = $user.Name
"Enabled" = $user.Enabled
"LastLogon" = $user.LastLogon
"Description" = $user.Description
"SID" = $user.SID
"PasswordLastSet" = $user.PasswordLastSet
"Groups" = Get-LocalGroup | Where-Object { $user.SID -in ($_ | Get-LocalGroupMember | Select-Object -ExpandProperty "SID") } | Select-Object -ExpandProperty "Name"
"FullName" = $user.FullName
}
} | Format-Table -Wrap -AutoSize
Get-LocalUser |
ForEach-Object {
$user = $_
return [PSCustomObject]@{
"User" = $user.Name
"Enabled" = $user.Enabled
"LastLogon" = $user.LastLogon
"Description" = $user.Description
"SID" = $user.SID
"PasswordLastSet" = $user.PasswordLastSet
"Groups" = (Get-LocalGroup | Where-Object { $user.SID -in ($_ | Get-LocalGroupMember | Select-Object -ExpandProperty "SID") } | Select-Object -ExpandProperty "Name" | Out-String).Trim()
"FullName" = $user.FullName
}
} | Export-Csv -NoTypeInformation -Path .\users.csv
Write-Host '###################' -BackgroundColor Black
Write-Host '## Processes ##' -BackgroundColor Black
Write-Host '###################' -BackgroundColor Black
Write-Host "Running processes" -ForegroundColor Black -BackgroundColor White
$Results = Get-ProcessInfo
$Results | Format-Table ID, Name, Owner, Path, CommandLine -auto
Get-ProcessInfo | Select-Object ID, Name, Owner, Path, CommandLine -auto | Export-Csv -NoTypeInformation -Path .\processes.csv
Write-Host '###############################' -BackgroundColor Black
Write-Host '## BIOS Information ##' -BackgroundColor Black
Write-Host '###############################' -BackgroundColor Black
Write-Host "BIOS Information" -ForegroundColor Black -BackgroundColor White
Get-WmiObject -Class win32_bios |Select-Object SMBIOSBIOSVersion, Manufacturer, Name, SerialNumber, Version | Format-List
Write-Host "Checking if Secure Boot is enabled" -ForegroundColor Black -BackgroundColor White
$securebootUEFI=$false
$secBootError=$false
Try
{
$securebootUEFI = Confirm-SecureBootUEFI
}
Catch {
Write-Host 'Secure Boot is disabled' -ForegroundColor Red
$secBootError=$true
}
if ($securebootUEFI)
{
Write-Host 'Secure Boot is enabled' -ForegroundColor Green
Get-SecureBootPolicy
}
else
{
if($secBootError -eq $false){
Write-Host 'Secure Boot is disabled' -ForegroundColor Red
}
}
Write-Host '#################################' -BackgroundColor Black
Write-Host '## Explicit Logon Events ##' -BackgroundColor Black
Write-Host '#################################' -BackgroundColor Black
#Get-ExplicitLogonEvents | Format-Table
Write-Host '#################################' -BackgroundColor Black
Write-Host '## SMB v1 ##' -BackgroundColor Black
Write-Host '#################################' -BackgroundColor Black
Try
{
$smbV1State = (Get-WindowsOptionalFeature -Online -FeatureName smb1protocol).State
}
Catch {
Write-Host 'Error getting SMB v1 state' -ForegroundColor Red
}
if ($smbV1State)
{
Write-Host 'SMBv1 is enabled' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
Get-WindowsOptionalFeature -Online -FeatureName smb1protocol
}
else
{
Write-Host 'SMBv1 is disabled' -ForegroundColor Green
Write-Host ' '
Write-Host ' '
}
Write-Host '#################################' -BackgroundColor Black
Write-Host '## SMB-Signing ##' -BackgroundColor Black
Write-Host '#################################' -BackgroundColor Black
Write-Host 'Check if SMB-Signing is enabled (Client)' -ForegroundColor Black -BackgroundColor White
$regPath = "HKLM:\System\CurrentControlSet\Services\LanmanWorkstation\Parameters"
$regPathProperty = "EnableSecuritySignature"
if((Test-RegistryValue -Path $regPath -Value $regPathProperty)){
$check = Get-ItemProperty -Path $regPath | Select-Object -ExpandProperty $regPathProperty -ErrorAction silentlycontinue
Switch($check)
{
'1'
{
Write-Host 'SMB-Signing (Client) is enabled' -ForegroundColor Green
}
'0'
{
Write-Host 'SMB-Signing (Client) is disabled' -ForegroundColor Red
}
}
} else {
Write-Host 'SMB-Signing (Client) is disabled' -ForegroundColor Red
}
Write-Host 'Check if SMB-Signing is enforced (Client)' -ForegroundColor Black -BackgroundColor White
$regPath = "HKLM:\System\CurrentControlSet\Services\LanmanWorkstation\Parameters"
$regPathProperty = "RequireSecuritySignature"
if((Test-RegistryValue -Path $regPath -Value $regPathProperty)){
$check = Get-ItemProperty -Path $regPath | Select-Object -ExpandProperty $regPathProperty -ErrorAction silentlycontinue
Switch($check)
{
'1'
{
Write-Host 'SMB-Signing (Client) is enforced' -ForegroundColor Green
Write-Host ' '
Write-Host ' '
}
'0'
{
Write-Host 'SMB-Signing (Client) is not enforced and can be downgraded' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
}
}
} else {
Write-Host 'SMB-Signing (Client) is not enforced and can be downgraded' -ForegroundColor Red
' '
}
Write-Host 'Check if SMB-Signing is enabled (server)' -ForegroundColor Black -BackgroundColor White
$regPath = "HKLM:\System\CurrentControlSet\Services\LanManServer\Parameters"
$regPathProperty = "EnableSecuritySignature"
if((Test-RegistryValue -Path $regPath -Value $regPathProperty)){
$check = Get-ItemProperty -Path $regPath | Select-Object -ExpandProperty $regPathProperty -ErrorAction silentlycontinue
Switch($check)
{
'1'
{
Write-Host 'SMB-Signing (server) is enabled' -ForegroundColor Green
}
'0'
{
Write-Host 'SMB-Signing (server) is disabled' -ForegroundColor Red
}
}
} else {
Write-Host 'SMB-Signing (server) is disabled' -ForegroundColor Red
' '
}
Write-Host 'Check if SMB-Signing is enforced (server)' -ForegroundColor Black -BackgroundColor White
$regPath = "HKLM:\System\CurrentControlSet\Services\LanManServer\Parameters"
$regPathProperty = "RequireSecuritySignature"
if((Test-RegistryValue -Path $regPath -Value $regPathProperty)){
$check = Get-ItemProperty -Path $regPath | Select-Object -ExpandProperty $regPathProperty -ErrorAction silentlycontinue
Switch($check)
{
'1'
{
Write-Host 'SMB-Signing (server) is enforced' -ForegroundColor Green
Write-Host ' '
Write-Host ' '
}
'0'
{
Write-Host 'SMB-Signing (server) is not enforced and can be downgraded' -ForegroundColor Red
Write-Host ' '
Write-Host ' '
}
}
} else {
Write-Host 'SMB-Signing (server) is not enforced and can be downgraded' -ForegroundColor Red
' '
}
Write-Host '#################################' -BackgroundColor Black
Write-Host '## User Rights Assignment ##' -BackgroundColor Black
Write-Host '#################################' -BackgroundColor Black
Get-UserRightsAssignment | Sort-Object -Property PrivilegeName | Format-Table
Get-UserRightsAssignment | Sort-Object -Property PrivilegeName | Export-Csv -Path ".\windows_user_rights-assignment.csv" -NoTypeInformation
Write-Host '#################################' -BackgroundColor Black
Write-Host '## Bitlocker ##' -BackgroundColor Black
Write-Host '#################################' -BackgroundColor Black
Try
{
Get-BitLockerVolume | Format-Table -AutoSize -Wrap
}
Catch {
Write-Host 'Error getting Bitlocker volumes - Bitlocker may not be available' -ForegroundColor Red
}
# TODO
# Registry Auditing for Credential Theft - https://medium.com/threatpunter/detecting-attempts-to-steal-passwords-from-the-registry-7512674487f8
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment