Windows 10 nach Inplace-Upgrade absichern: BSI-Hardening, Firewall & Killer-WLAN mit PowerShell automatisieren

Ein Windows 10 Inplace-Upgrade ist oft das beste Werkzeug, um ein beschädigtes Betriebssystem ohne Datenverlust zu reparieren. Was viele Anwender – insbesondere im privaten Umfeld – jedoch nicht bedenken: Eine Inplace-Reparatur setzt nahezu alle Sicherheitseinstellungen, Dienste und Firewall-Profilregeln auf den Microsoft-Standardzustand zurück.
Plötzlich funken Telemetriedienste wieder nach Hause, unnötige Remote-Schnittstellen werden geöffnet und ungeliebte Softwarepakete wie das Killer Network Center auf MSI-Notebooks (z. B. MSI GT80) übernehmen wieder die Regie über den Netzwerk-Stack.
In den meisten Haushalten läuft ein PC nach dem Motto: „Hauptsache, das Internet geht.“ Aber Sicherheit im Netz gilt für jeden. Das Bundesamt für Sicherheit in der Informationstechnik (BSI) hat umfangreiche Sicherheitsempfehlungen herausgegeben, um Windows 10 zu härten. Leider stellt das BSI kein fertiges PowerShell-Skript zur Verfügung, um diese Empfehlungen rasch umzusetzen.
In diesem Beitrag zeige ich Schritt für Schritt, wie ich mein System nach dem Inplace-Upgrade nach BSI-Vorgaben gehärtet habe – inklusive aller von mir entwickelten Skripte zur Diagnose, Automatisierung und Deaktivierung störender Dienste.
Das Problem: Nach der Reparatur steht das Scheunentor wieder offen
Nach dem Inplace-Upgrade auf meinem MSI GT80 fielen mir direkt mehrere Schwachstellen und Performance-Killer auf:
Killer WLAN Bloatware: Das mit installierte Software-Paket von Killer Networking (Analytics, Dynamic Bandwidth Management etc.) führt auf MSI-Geräten häufiger zu Paketverlusten und Systembremsen, als dass es hilft. Der reine Treiber reicht völlig aus!
Telemetrie & Datenerfassung: Microsoft-Dienste wie
DiagTrackoder derWindows-Insider-Dienstwurden wieder auf automatischen Start gesetzt.Remote-Schnittstellen: Dienste wie Remote Desktop (RDP), WinRM und Remote Registry liefen im Hintergrund oder waren erreichbar.
Veraltete / Unsichere Netzwerkprotokolle: LLMNR (Link-Local Multicast Name Resolution) und NetBIOS over TCP/IP waren wieder aktiv – im lokalen Netz ein bekanntes Risiko für LLMNR-Poisoning-Angriffe.
Da ich diese Konfiguration nicht jedes Mal manuell über Dutzende Menüs durchklicken wollte, habe ich mir eine Skript-Sammlung aufgebaut.
Schritt 1: Das Starter-Skript (FirewallSecurity.bat) zur Rechteausweitung
Um PowerShell-Skripte sicher und ohne administrative Komplikationen auszuführen, nutze ich eine Batch-Datei als Starter. Sie prüft automatisch, ob administrative Rechte vorliegen, fordert diese bei Bedarf an und startet das eigentliche PowerShell-Hardening-Skript mit angepasster Execution-Policy.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
REM ============================================================
REM WINDOWS FIREWALL SECURITY CENTER
REM BAT STARTER
REM Windows 10 Home / Pro
REM ============================================================
title Windows Firewall Security Center
REM Eigenen Ordner absolut bestimmen
set "SCRIPT_DIR=%~dp0"
set "PS1_FILE=%SCRIPT_DIR%FirewallSecurity.ps1"
echo.
echo ============================================================
echo WINDOWS FIREWALL SECURITY CENTER
echo ============================================================
echo.
echo Sichere Windows-Firewall-Konfiguration
echo Windows 10 Home / Pro
echo.
echo ============================================================
echo.
REM ------------------------------------------------------------
REM Pruefen, ob die PowerShell-Datei vorhanden ist
REM ------------------------------------------------------------
if not exist "%PS1_FILE%" (
echo.
echo FEHLER:
echo.
echo Die PowerShell-Datei wurde nicht gefunden:
echo.
echo "%PS1_FILE%"
echo.
echo Bitte pruefen, ob FirewallSecurity.ps1 im selben
echo Ordner wie diese BAT-Datei liegt.
echo.
pause
exit /b 10
)
REM ------------------------------------------------------------
REM Administratorrechte pruefen
REM ------------------------------------------------------------
net session >nul 2>&1
if %ERRORLEVEL% NEQ 0 (
echo [INFO] Administratorrechte werden angefordert...
echo.
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass ^
-Command "Start-Process -FilePath '%~f0' -Verb RunAs"
exit /b
)
REM ------------------------------------------------------------
REM PowerShell-Skript starten
REM ------------------------------------------------------------
echo [INFO] PowerShell-Sicherheitskonfiguration wird gestartet...
echo.
echo Skript:
echo "%PS1_FILE%"
echo.
powershell.exe ^
-NoLogo ^
-NoProfile ^
-ExecutionPolicy Bypass ^
-File "%PS1_FILE%"
set "EXITCODE=%ERRORLEVEL%"
echo.
echo ============================================================
echo.
if "%EXITCODE%"=="0" (
echo Sicherheitskonfiguration erfolgreich beendet.
) else (
echo ACHTUNG!
echo Die Konfiguration wurde mit Fehlercode %EXITCODE% beendet.
echo.
echo Bitte die angezeigte Fehlermeldung bzw. das Log pruefen.
)
echo.
pause
exit /b %EXITCODE%
Schritt 2: Das BSI-Hardening- & Firewall-Skript (FirewallSecurity.ps1)
Das Hauptskript führt die eigentliche Aushärtung des Systems durch. Es setzt die Windows-Firewall auf ein sicheres Default-Verhalten (Block Inbound, Allow Outbound), deaktiviert Telemetriedienste sowie die stöhrenden Killer-WLAN-Hintergrunddienste, schaltet unsichere Protokolle (LLMNR, NetBIOS, SMB1) ab und kapselt RDP- sowie WinRM-Zugriffe über explizite Blockregeln.
Alle Aktionen werden übersichtlich in einer Logdatei unter C:\ProgramData\FirewallSecurity\Logs\ protokolliert.
#requires -version 5.1
<#
============================================================
WINDOWS FIREWALL SECURITY CENTER & BSI HARDENING
Version 6.1
Zielsystem:
Windows 10 / 11 Home / Pro
Sicherheitskonzept:
- Windows Firewall AKTIV
- Eingehend standardmäßig BLOCK
- Ausgehend standardmäßig ALLOW
- SMB bleibt unangetastet (SMB2/3 aktiv)
- SMB1 wird deaktiviert / geprüft
- RDP wird deaktiviert und explizit blockiert
- WinRM wird deaktiviert und explizit blockiert
- Remote Registry wird deaktiviert
- LLMNR wird deaktiviert (BSI IT-Grundschutz)
- NetBIOS over TCP/IP wird deaktiviert (BSI IT-Grundschutz)
- Telemetrie-, iSCSI-, VR- & Killer-Dienste werden deaktiviert
============================================================
#>
$ErrorActionPreference = "Stop"
$ScriptVersion = "6.1"
$Failures = 0
$RestartNeeded = $false
$SecurityGroup = "SECURITY - Managed Firewall Rules"
# ============================================================
# LOGGING SYSTEM
# ============================================================
$LogDirectory = Join-Path $env:ProgramData "FirewallSecurity\Logs"
New-Item -Path $LogDirectory -ItemType Directory -Force | Out-Null
$TimeStamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$LogFile = Join-Path $LogDirectory "FirewallSecurity_$TimeStamp.log"
function Write-Log {
param(
[string]$Message,
[ValidateSet("INFO", "OK", "WARN", "ERROR")]
[string]$Level = "INFO"
)
$Now = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$Line = "[$Now] [$Level] $Message"
Add-Content -Path $LogFile -Value $Line -Encoding UTF8
switch ($Level) {
"INFO" { Write-Host "[INFO] $Message" -ForegroundColor Cyan }
"OK" { Write-Host "[ OK ] $Message" -ForegroundColor Green }
"WARN" { Write-Host "[WARN] $Message" -ForegroundColor Yellow }
"ERROR" { Write-Host "[ERR ] $Message" -ForegroundColor Red }
}
}
# ============================================================
# HILFSFUNKTION FÜR DIENST-DEAKTIVIERUNG
# ============================================================
function Disable-SecurityService {
param(
[string]$ServiceName,
[string]$DisplayNamePattern
)
try {
$Service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if (-not $Service -and $DisplayNamePattern) {
$Service = Get-Service -DisplayName $DisplayNamePattern -ErrorAction SilentlyContinue
}
if ($Service) {
if ($Service.Status -eq "Running") {
Stop-Service -Name $Service.Name -Force -ErrorAction SilentlyContinue
}
Set-Service -Name $Service.Name -StartupType Disabled -ErrorAction Stop
Write-Log "Dienst '$($Service.DisplayName)' ($($Service.Name)) = Deaktiviert." "OK"
} else {
Write-Log "Dienst '$DisplayNamePattern' ($ServiceName) nicht vorhanden (übersprungen)." "INFO"
}
}
catch {
Write-Log "Dienst '$DisplayNamePattern' ($ServiceName) konnte nicht deaktiviert werden: $($_.Exception.Message)" "WARN"
}
}
# ============================================================
# ADMINISTRATORPRÜFUNG
# ============================================================
$Identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$Principal = New-Object Security.Principal.WindowsPrincipal($Identity)
$IsAdmin = $Principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $IsAdmin) {
Write-Host ""
Write-Host "FEHLER: Dieses Skript muss als Administrator ausgeführt werden." -ForegroundColor Red
Write-Host ""
exit 10
}
# ============================================================
# HEADER
# ============================================================
Clear-Host
Write-Host "============================================================" -ForegroundColor DarkCyan
Write-Host " WINDOWS FIREWALL & SECURITY CENTER" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor DarkCyan
Write-Host ""
Write-Host "Version: $ScriptVersion"
Write-Host "Computer: $env:COMPUTERNAME"
Write-Host "Benutzer: $env:USERNAME"
Write-Host "PowerShell: $($PSVersionTable.PSVersion)"
Write-Host ""
Write-Log "Security Center gestartet."
Write-Log "Version $ScriptVersion"
# ============================================================
# WINDOWS VERSION
# ============================================================
try {
$OS = Get-CimInstance Win32_OperatingSystem
Write-Host "Betriebssystem: $($OS.Caption)"
Write-Host "Build: $($OS.BuildNumber)"
Write-Host ""
Write-Log "Betriebssystem: $($OS.Caption)"
Write-Log "Build: $($OS.BuildNumber)"
}
catch {
Write-Log "Windows-Version konnte nicht ermittelt werden." "WARN"
}
# ============================================================
# FIREWALL DIENST
# ============================================================
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " FIREWALL-DIENST" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
Write-Host ""
try {
$FirewallService = Get-Service -Name MpsSvc -ErrorAction Stop
if ($FirewallService.Status -ne "Running") {
Write-Log "Windows-Firewall-Dienst ist nicht aktiv." "WARN"
try {
Start-Service -Name MpsSvc -ErrorAction Stop
Write-Log "Windows-Firewall-Dienst wurde gestartet." "OK"
}
catch {
Write-Log "Windows-Firewall-Dienst konnte nicht gestartet werden." "ERROR"
$Failures++
}
}
else {
Write-Log "Windows-Firewall-Dienst ist aktiv." "OK"
}
}
catch {
Write-Log "Windows-Firewall-Dienst konnte nicht geprüft werden." "ERROR"
$Failures++
}
# ============================================================
# ALTE SECURITY-REGELN BEREINIGEN
# ============================================================
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " EIGENE SECURITY-REGELN BEREINIGEN" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
Write-Host ""
try {
$OldRules = Get-NetFirewallRule -Group $SecurityGroup -ErrorAction SilentlyContinue
if ($OldRules) {
$Count = @($OldRules).Count
Remove-NetFirewallRule -Group $SecurityGroup -ErrorAction Stop
Write-Log "$Count alte SECURITY-Regel(n) entfernt." "OK"
}
else {
Write-Log "Keine alten SECURITY-Regeln vorhanden." "OK"
}
}
catch {
Write-Log "Eigene SECURITY-Regeln konnten nicht bereinigt werden." "ERROR"
$Failures++
}
# ============================================================
# FIREWALL PROFILE
# ============================================================
Write-Host ""
Write-Host "============================================================" -ForegroundColor DarkCyan
Write-Host " FIREWALL-BASISKONFIGURATION" -ForegroundColor Cyan
Write-Host "============================================================"
Write-Host ""
try {
Set-NetFirewallProfile `
-Profile Domain,Private,Public `
-Enabled True `
-DefaultInboundAction Block `
-DefaultOutboundAction Allow `
-NotifyOnListen False `
-AllowUnicastResponseToMulticast True `
-LogBlocked True `
-LogAllowed False `
-LogMaxSizeKilobytes 32767 `
-ErrorAction Stop
Write-Log "Alle Firewallprofile aktiviert." "OK"
Write-Log "Default Inbound = BLOCK." "OK"
Write-Log "Default Outbound = ALLOW." "OK"
Write-Log "Benutzerbenachrichtigungen bei Listen = AUS." "OK"
Write-Log "Blockierte Verbindungen werden protokolliert." "OK"
}
catch {
Write-Log "Firewall-Basiskonfiguration fehlgeschlagen: $($_.Exception.Message)" "ERROR"
$Failures++
}
# ============================================================
# REMOTE DESKTOP (RDP)
# ============================================================
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " REMOTE DESKTOP / RDP" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
Write-Host ""
try {
New-NetFirewallRule `
-DisplayName "SECURITY - BLOCK Remote Desktop TCP 3389" `
-Description "Blockiert eingehende Microsoft Remote Desktop Verbindungen." `
-Group $SecurityGroup `
-Direction Inbound `
-Action Block `
-Protocol TCP `
-LocalPort 3389 `
-Profile Any `
-Enabled True `
-EdgeTraversalPolicy Block `
-ErrorAction Stop | Out-Null
Write-Log "Explizite RDP-Blockregel erstellt." "OK"
}
catch {
Write-Log "RDP-Blockregel konnte nicht erstellt werden." "ERROR"
$Failures++
}
try {
$RdpRegistryPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server"
Set-ItemProperty -Path $RdpRegistryPath -Name fDenyTSConnections -Type DWord -Value 1 -Force -ErrorAction Stop
Write-Log "RDP Registry-Konfiguration = deaktiviert." "OK"
}
catch {
Write-Log "RDP Registry-Konfiguration konnte nicht gesetzt werden." "ERROR"
$Failures++
}
Disable-SecurityService -ServiceName "TermService" -DisplayNamePattern "Remotedesktoppostdienste"
# ============================================================
# WINRM & REMOTE REGISTRY
# ============================================================
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " WINRM & REMOTE REGISTRY" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
Write-Host ""
try {
New-NetFirewallRule `
-DisplayName "SECURITY - BLOCK WinRM TCP 5985" `
-Description "Blockiert eingehende WinRM HTTP Verbindungen." `
-Group $SecurityGroup `
-Direction Inbound `
-Action Block `
-Protocol TCP `
-LocalPort 5985 `
-Profile Any `
-Enabled True `
-EdgeTraversalPolicy Block `
-ErrorAction Stop | Out-Null
New-NetFirewallRule `
-DisplayName "SECURITY - BLOCK WinRM TCP 5986" `
-Description "Blockiert eingehende WinRM HTTPS Verbindungen." `
-Group $SecurityGroup `
-Direction Inbound `
-Action Block `
-Protocol TCP `
-LocalPort 5986 `
-Profile Any `
-Enabled True `
-EdgeTraversalPolicy Block `
-ErrorAction Stop | Out-Null
Write-Log "WinRM TCP 5985/5986 explizit blockiert." "OK"
}
catch {
Write-Log "WinRM-Blockregeln konnten nicht erstellt werden." "ERROR"
$Failures++
}
Disable-SecurityService -ServiceName "WinRM" -DisplayNamePattern "Windows-Remoteverwaltung*"
Disable-SecurityService -ServiceName "RemoteRegistry" -DisplayNamePattern "Remoteregistrierung"
# ============================================================
# TELEMETRIE & UNNÖTIGE DIENSTE DEAKTIVIEREN
# ============================================================
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " TELEMETRIE & UNNÖTIGE SYSTEMDIENSTE" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
Write-Host ""
# Windows Systemdienste
Disable-SecurityService -ServiceName "DiagTrack" -DisplayNamePattern "Benutzererfahrungen und Telemetrie im verbundenen Modus"
Disable-SecurityService -ServiceName "RetailDemo" -DisplayNamePattern "Dienst für Einzelhandelsdemos"
Disable-SecurityService -ServiceName "MapsBroker" -DisplayNamePattern "Manager für heruntergeladene Karten"
Disable-SecurityService -ServiceName "MSiSCSI" -DisplayNamePattern "Microsoft iSCSI-Initiator-Dienst"
Disable-SecurityService -ServiceName "mixedrealityopenxr" -DisplayNamePattern "Windows Mixed Reality OpenXR Service"
Disable-SecurityService -ServiceName "wisvc" -DisplayNamePattern "Windows-Insider-Dienst"
# Killer Network Services
Disable-SecurityService -ServiceName "KAPSService" -DisplayNamePattern "Killer Analytics Service"
Disable-SecurityService -ServiceName "KDBMService" -DisplayNamePattern "Killer Dynamic Bandwidth Management"
Disable-SecurityService -ServiceName "KillerSmartAP" -DisplayNamePattern "Killer Smart AP Selection Service"
Disable-SecurityService -ServiceName "KDataHelper" -DisplayNamePattern "Killer Provider Data Helper Service"
Disable-SecurityService -ServiceName "KNetworkService" -DisplayNamePattern "Killer Network Service"
# ============================================================
# LLMNR DEAKTIVIEREN (BSI IT-GRUNDSCHUTZ)
# ============================================================
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " LLMNR DEAKTIVIEREN" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
Write-Host ""
try {
$DNSClientPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient"
if (-not (Test-Path -Path $DNSClientPath)) {
New-Item -Path $DNSClientPath -Force | Out-Null
}
Set-ItemProperty `
-Path $DNSClientPath `
-Name "EnableMulticast" `
-Value 0 `
-Type DWord `
-Force `
-ErrorAction Stop
Write-Log "LLMNR erfolgreich über Registry deaktiviert." "OK"
}
catch {
Write-Log "LLMNR konnte nicht deaktiviert werden: $($_.Exception.Message)" "ERROR"
$Failures++
}
# ============================================================
# NETBIOS OVER TCP/IP DEAKTIVIEREN
# ============================================================
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " NETBIOS DEAKTIVIEREN" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
Write-Host ""
try {
$NetAdapterTcpip = Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "IPEnabled = True"
foreach ($Adapter in $NetAdapterTcpip) {
$null = Invoke-CimMethod -InputObject $Adapter -MethodName SetTCPIPNetBIOS -Arguments @{TcpipNetbiosOptions = 2}
}
Write-Log "NetBIOS over TCP/IP auf allen aktiven Adaptern deaktiviert." "OK"
}
catch {
Write-Log "NetBIOS konnte nicht deaktiviert werden: $($_.Exception.Message)" "ERROR"
$Failures++
}
# ============================================================
# SMB PRÜFUNG / SMB1 DEAKTIVIEREN
# ============================================================
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " SMB / FRITZ!NAS" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
Write-Host ""
try {
$SMB1Feature = Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -ErrorAction Stop
Write-Log "SMB1 aktueller Status: $($SMB1Feature.State)"
if ($SMB1Feature.State -eq "Enabled" -or $SMB1Feature.State -eq "Enable Pending") {
Write-Log "SMB1 ist aktiviert und wird deaktiviert." "WARN"
$DisableResult = Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestart -ErrorAction Stop
if ($DisableResult.RestartNeeded) {
$RestartNeeded = $true
Write-Log "Windows benötigt einen Neustart für die SMB1-Deaktivierung." "WARN"
}
}
$SMB1Verify = Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -ErrorAction Stop
if ($SMB1Verify.State -eq "Disabled" -or $SMB1Verify.State -eq "DisabledWithPayloadRemoved") {
Write-Log "SMB1 = DEAKTIVIERT." "OK"
}
else {
Write-Log "SMB1 konnte nicht vollständig deaktiviert werden. Status: $($SMB1Verify.State)" "ERROR"
$Failures++
}
}
catch {
Write-Log "SMB1-Prüfung fehlgeschlagen: $($_.Exception.Message)" "ERROR"
$Failures++
}
# ============================================================
# ABSCHLUSSPRÜFUNG
# ============================================================
Write-Host ""
Write-Host "============================================================" -ForegroundColor DarkCyan
Write-Host " ABSCHLUSSPRÜFUNG" -ForegroundColor Cyan
Write-Host "============================================================"
Write-Host ""
Write-Host "[1] Firewall-Profile"
try {
$Profiles = Get-NetFirewallProfile
foreach ($ProfileName in @("Domain", "Private", "Public")) {
$Profile = $Profiles | Where-Object { $_.Name -eq $ProfileName }
if (-not $Profile) {
Write-Log "$ProfileName Profil nicht gefunden." "ERROR"
$script:Failures++
continue
}
if ($Profile.Enabled -eq $true) { Write-Log "$ProfileName Firewall = AKTIV" "OK" }
else { Write-Log "$ProfileName Firewall = AUS" "ERROR"; $script:Failures++ }
if ($Profile.DefaultInboundAction -eq "Block") { Write-Log "$ProfileName Inbound = BLOCK" "OK" }
else { Write-Log "$ProfileName Inbound ist NICHT BLOCK." "ERROR"; $script:Failures++ }
}
}
catch {
Write-Log "Firewall-Profilprüfung fehlgeschlagen." "ERROR"
$Failures++
}
Write-Host ""
Write-Host "[2] SECURITY-FIREWALLREGELN"
function Test-SecurityRule {
param([string]$DisplayName, [string]$Direction, [string]$Action)
try {
$Rule = Get-NetFirewallRule -DisplayName $DisplayName -ErrorAction Stop
if ($Rule.Enabled -eq "True" -and $Rule.Direction -eq $Direction -and $Rule.Action -eq $Action) {
Write-Log "$DisplayName = OK" "OK"
} else {
Write-Log "$DisplayName = FALSCH KONFIGURIERT" "ERROR"
$script:Failures++
}
}
catch {
Write-Log "$DisplayName = FEHLT" "ERROR"
$script:Failures++
}
}
Test-SecurityRule -DisplayName "SECURITY - BLOCK Remote Desktop TCP 3389" -Direction Inbound -Action Block
Test-SecurityRule -DisplayName "SECURITY - BLOCK WinRM TCP 5985" -Direction Inbound -Action Block
Test-SecurityRule -DisplayName "SECURITY - BLOCK WinRM TCP 5986" -Direction Inbound -Action Block
Write-Host ""
Write-Host "[3] RDP, LLMNR & NETBIOS STATUS"
try {
$RdpState = Get-ItemPropertyValue -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name fDenyTSConnections -ErrorAction Stop
if ($RdpState -eq 1) { Write-Log "RDP = DEAKTIVIERT" "OK" }
else { Write-Log "RDP = AKTIVIERT" "ERROR"; $Failures++ }
}
catch {
Write-Log "RDP-Status konnte nicht geprüft werden." "ERROR"
$Failures++
}
try {
$LlmnrState = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" -Name EnableMulticast -ErrorAction Stop
if ($LlmnrState -eq 0) { Write-Log "LLMNR = DEAKTIVIERT" "OK" }
else { Write-Log "LLMNR = AKTIVIERT" "ERROR"; $Failures++ }
}
catch {
Write-Log "LLMNR-Status konnte nicht geprüft werden." "ERROR"
$Failures++
}
# ============================================================
# GESAMTERGEBNIS
# ============================================================
Write-Host ""
Write-Host "============================================================" -ForegroundColor DarkCyan
Write-Host " ERGEBNIS" -ForegroundColor Cyan
Write-Host "============================================================"
Write-Host ""
Write-Host "Firewall: AKTIV"
Write-Host "Inbound Default: BLOCK"
Write-Host "Outbound Default: ALLOW"
Write-Host "SMB2/SMB3: NICHT VERÄNDERT"
Write-Host "SMB1: DEAKTIVIERT"
Write-Host "Remote Desktop: DEAKTIVIERT"
Write-Host "WinRM: DEAKTIVIERT"
Write-Host "Remote Registry: DEAKTIVIERT"
Write-Host "LLMNR: DEAKTIVIERT"
Write-Host "NetBIOS: DEAKTIVIERT"
Write-Host "Telemetrie & Bloatware: DEAKTIVIERT"
Write-Host ""
if ($Failures -eq 0) {
Write-Host "============================================================" -ForegroundColor Green
Write-Host " KONFIGURATION ERFOLGREICH" -ForegroundColor Green
Write-Host "============================================================" -ForegroundColor Green
Write-Log "Alle kritischen Prüfungen erfolgreich." "OK"
}
else {
Write-Host "============================================================" -ForegroundColor Red
Write-Host " KONFIGURATION MIT FEHLERN ($Failures)" -ForegroundColor Red
Write-Host "============================================================" -ForegroundColor Red
Write-Log "$Failures Fehler festgestellt." "ERROR"
}
if ($RestartNeeded) {
Write-Host ""
Write-Host "============================================================" -ForegroundColor Yellow
Write-Host " NEUSTART ERFORDERLICH" -ForegroundColor Yellow
Write-Host "============================================================" -ForegroundColor Yellow
Write-Host "SMB1 wurde deaktiviert, Windows verlangt einen Neustart."
Write-Log "Neustart wegen SMB1-Deaktivierung erforderlich." "WARN"
}
Write-Host ""
Write-Host "Logdatei: $LogFile"
Write-Host ""
Write-Log "Security Center beendet."
if ($Failures -eq 0) { exit 0 } else { exit 50 }
Schritt 3: Nur Prüfen statt Verändern – Das Audit-Skript (Audit-SecurityStatus.ps1)
Wer vor dem Ausführen von Änderungen wissen möchte, wie es um die eigene Systemhärtung steht, kann ein Audit durchführen. Dieses Skript nimmt keinerlei Änderungen vor, sondern wertet lediglich alle relevanten BSI-Kriterien, Firewall-Profile und Dienste-Zustände aus.
#requires -version 5.1
<#
============================================================
AUDIT SECURITY STATUS & BSI HARDENING CHECK
Version: 1.2 (Extended Service Inspection)
Zweck:
Prüft den aktuellen Sicherheitsstatus aller Firewall-,
BSI-Hardening- und Dienst-Vorgaben, OHNE Änderungen am
System vorzunehmen.
============================================================
#>
$ErrorActionPreference = "Continue"
# ------------------------------------------------------------
# ADMINISTRATORPRÜFUNG
# ------------------------------------------------------------
$Identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$Principal = New-Object Security.Principal.WindowsPrincipal($Identity)
$IsAdmin = $Principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $IsAdmin) {
Write-Host ""
Write-Host "FEHLER: Für eine vollständige Systemprüfung wird Administratorrecht benötigt." -ForegroundColor Red
Write-Host "Bitte starte die PowerShell erneut als Administrator." -ForegroundColor Yellow
Write-Host ""
exit 10
}
# ------------------------------------------------------------
# HEADER & HILFSFUNKTIONEN
# ------------------------------------------------------------
Clear-Host
Write-Host "============================================================" -ForegroundColor DarkCyan
Write-Host " SYSTEM SECURITY AUDIT & BSI STATUS CHECK" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor DarkCyan
Write-Host ""
Write-Host "Computer: $env:COMPUTERNAME"
Write-Host "Datum: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Host ""
$PassedChecks = 0
$FailedChecks = 0
function Report-Check {
param(
[string]$Component,
[string]$Detail,
[bool]$IsSecure
)
if ($IsSecure) {
$script:PassedChecks++
Write-Host " [ PASS ] " -ForegroundColor Green -NoNewline
Write-Host "${Component}: " -ForegroundColor White -NoNewline
Write-Host $Detail -ForegroundColor DarkGray
} else {
$script:FailedChecks++
Write-Host " [ FAIL ] " -ForegroundColor Red -NoNewline
Write-Host "${Component}: " -ForegroundColor White -NoNewline
Write-Host $Detail -ForegroundColor Yellow
}
}
function Test-SecurityService {
param(
[string]$ServiceName,
[string]$DisplayName
)
try {
$Svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if (-not $Svc) {
Report-Check -Component "Dienst '${DisplayName}'" -Detail "Nicht vorhanden (Sicher)" -IsSecure $true
return
}
$IsSecure = ($Svc.StartType -eq "Disabled") -and ($Svc.Status -ne "Running")
$StatusText = "Starttyp: $($Svc.StartType) | Status: $($Svc.Status)"
Report-Check -Component "Dienst '${DisplayName}'" -Detail $StatusText -IsSecure $IsSecure
} catch {
Report-Check -Component "Dienst '${DisplayName}'" -Detail "Status konnte nicht ermittelt werden." -IsSecure $false
}
}
# ------------------------------------------------------------
# 1. FIREWALL DIENST
# ------------------------------------------------------------
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " 1. FIREWALL-DIENST" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
try {
$FwService = Get-Service -Name MpsSvc -ErrorAction Stop
$IsRunning = $FwService.Status -eq "Running"
Report-Check -Component "Firewall-Dienst (MpsSvc)" -Detail "Status: $($FwService.Status)" -IsSecure $IsRunning
} catch {
Report-Check -Component "Firewall-Dienst (MpsSvc)" -Detail "Dienst konnte nicht gelesen werden." -IsSecure $false
}
# ------------------------------------------------------------
# 2. FIREWALL PROFILE
# ------------------------------------------------------------
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " 2. FIREWALL PROFILE (Domain, Private, Public)" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
try {
$Profiles = Get-NetFirewallProfile -ErrorAction Stop
foreach ($PName in @("Domain", "Private", "Public")) {
$P = $Profiles | Where-Object { $_.Name -eq $PName }
$IsActive = ($P.Enabled -eq $true) -and ($P.DefaultInboundAction -eq "Block") -and ($P.DefaultOutboundAction -eq "Allow")
$StatusText = "Aktiv: $($P.Enabled) | Inbound: $($P.DefaultInboundAction) | Outbound: $($P.DefaultOutboundAction)"
Report-Check -Component "Profil '$PName'" -Detail $StatusText -IsSecure $IsActive
}
} catch {
Report-Check -Component "Firewall-Profile" -Detail "Profile konnten nicht ausgelesen werden." -IsSecure $false
}
# ------------------------------------------------------------
# 3. BENUTZERDEFINIERTE FIREWALL-BLOCKREGELN
# ------------------------------------------------------------
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " 3. SECURITY FIREWALL-REGELN" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
$SecurityRules = @(
"SECURITY - BLOCK Remote Desktop TCP 3389",
"SECURITY - BLOCK WinRM TCP 5985",
"SECURITY - BLOCK WinRM TCP 5986"
)
foreach ($RuleName in $SecurityRules) {
try {
$Rule = Get-NetFirewallRule -DisplayName $RuleName -ErrorAction Stop
$RuleOk = ($Rule.Enabled -eq "True") -and ($Rule.Action -eq "Block")
Report-Check -Component "Firewall-Regel" -Detail "'$RuleName' existiert und ist AKTIV" -IsSecure $RuleOk
} catch {
Report-Check -Component "Firewall-Regel" -Detail "'$RuleName' FEHLT oder ist inaktiv" -IsSecure $false
}
}
# ------------------------------------------------------------
# 4. REMOTE DESKTOP (RDP) & REMOTE SERVICES
# ------------------------------------------------------------
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " 4. REMOTE SERVICES (RDP, WinRM, Remote Registry)" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
try {
$RdpReg = Get-ItemPropertyValue -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server" -Name fDenyTSConnections -ErrorAction Stop
$RdpDenyOk = ($RdpReg -eq 1)
Report-Check -Component "RDP Registry" -Detail "fDenyTSConnections = $RdpReg (1 = Deaktiviert)" -IsSecure $RdpDenyOk
} catch {
Report-Check -Component "RDP Registry" -Detail "Wert konnte nicht ausgelesen werden." -IsSecure $false
}
Test-SecurityService -ServiceName "TermService" -DisplayName "Remotedesktoppostdienste"
Test-SecurityService -ServiceName "WinRM" -DisplayName "Windows Remote Management"
Test-SecurityService -ServiceName "RemoteRegistry" -DisplayName "Remote Registry"
# ------------------------------------------------------------
# 5. TELEMETRIE & UNNÖTIGE WINDOWS-DIENSTE
# ------------------------------------------------------------
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " 5. TELEMETRIE & SYSTEMDIENSTE" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
Test-SecurityService -ServiceName "DiagTrack" -DisplayName "Benutzererfahrungen und Telemetrie im verbundenen Modus"
Test-SecurityService -ServiceName "RetailDemo" -DisplayName "Dienst für Einzelhandelsdemos"
Test-SecurityService -ServiceName "MapsBroker" -DisplayName "Manager für heruntergeladene Karten"
Test-SecurityService -ServiceName "MSiSCSI" -DisplayName "Microsoft iSCSI-Initiator-Dienst"
Test-SecurityService -ServiceName "mixedrealityopenxr" -DisplayName "Windows Mixed Reality OpenXR Service"
Test-SecurityService -ServiceName "wisvc" -DisplayName "Windows-Insider-Dienst"
# ------------------------------------------------------------
# 6. KILLER NETWORK SERVICES
# ------------------------------------------------------------
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " 6. KILLER NETWORK SERVICES" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
Test-SecurityService -ServiceName "KAPSService" -DisplayName "Killer Analytics Service"
Test-SecurityService -ServiceName "KDBMService" -DisplayName "Killer Dynamic Bandwidth Management"
Test-SecurityService -ServiceName "KillerSmartAP" -DisplayName "Killer Smart AP Selection Service"
Test-SecurityService -ServiceName "KDataHelper" -DisplayName "Killer Provider Data Helper Service"
Test-SecurityService -ServiceName "KNetworkService" -DisplayName "Killer Network Service"
# ------------------------------------------------------------
# 7. LLMNR STATUS (BSI HARDENING)
# ------------------------------------------------------------
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " 7. LLMNR NAMENSAUFLÖSUNG" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
try {
$LlmnrRegPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient"
if (Test-Path $LlmnrRegPath) {
$LlmnrVal = Get-ItemPropertyValue -Path $LlmnrRegPath -Name EnableMulticast -ErrorAction SilentlyContinue
$LlmnrOk = ($LlmnrVal -eq 0)
Report-Check -Component "LLMNR Multicast" -Detail "EnableMulticast = $LlmnrVal (0 = Deaktiviert)" -IsSecure $LlmnrOk
} else {
Report-Check -Component "LLMNR Multicast" -Detail "Registry-Policy Pfad existiert nicht (LLMNR noch Standard/Aktiv)" -IsSecure $false
}
} catch {
Report-Check -Component "LLMNR Multicast" -Detail "Status konnte nicht ermittelt werden." -IsSecure $false
}
# ------------------------------------------------------------
# 8. NETBIOS OVER TCP/IP
# ------------------------------------------------------------
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " 8. NETBIOS OVER TCP/IP" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
try {
$Adapters = Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "IPEnabled = True" -ErrorAction Stop
$NetBiosAllDisabled = $true
$DetailsList = @()
foreach ($Adapter in $Adapters) {
if ($Adapter.TcpipNetbiosOptions -ne 2) {
$NetBiosAllDisabled = $false
$DetailsList += "$($Adapter.Description): Aktiv/Default ($($Adapter.TcpipNetbiosOptions))"
}
}
if ($NetBiosAllDisabled) {
Report-Check -Component "NetBIOS Status" -Detail "Auf allen aktiven Adaptern vollständig DEAKTIVIERT (Option 2)" -IsSecure $true
} else {
Report-Check -Component "NetBIOS Status" -Detail "Auf folgenden Adaptern noch AKTIV: $($DetailsList -join '; ')" -IsSecure $false
}
} catch {
Report-Check -Component "NetBIOS Status" -Detail "Adapter-Konfiguration konnte nicht ausgelesen werden." -IsSecure $false
}
# ------------------------------------------------------------
# 9. SMB PROTOKOLLE (SMB1 CHECK)
# ------------------------------------------------------------
Write-Host ""
Write-Host "------------------------------------------------------------" -ForegroundColor DarkCyan
Write-Host " 9. SMB PROTOKOLLE" -ForegroundColor Cyan
Write-Host "------------------------------------------------------------"
try {
$Smb1 = Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -ErrorAction Stop
$Smb1Disabled = ($Smb1.State -eq "Disabled") -or ($Smb1.State -eq "DisabledWithPayloadRemoved")
Report-Check -Component "SMB1 Feature Status" -Detail "Status: $($Smb1.State)" -IsSecure $Smb1Disabled
} catch {
Report-Check -Component "SMB1 Feature Status" -Detail "SMB1 Status konnte nicht ermittelt werden." -IsSecure $false
}
# ------------------------------------------------------------
# GESAMTERGEBNIS & AUDIT SUMMARY
# ------------------------------------------------------------
Write-Host ""
Write-Host "============================================================" -ForegroundColor DarkCyan
Write-Host " AUDIT ERGEBNIS" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor DarkCyan
Write-Host ""
Write-Host "Erfolgreiche Prüfungen [PASS]: " -NoNewline
Write-Host "$PassedChecks" -ForegroundColor Green
Write-Host "Fehlgeschlagene/Risiko-Prüfungen [FAIL]: " -NoNewline
if ($FailedChecks -eq 0) {
Write-Host "$FailedChecks" -ForegroundColor Green
} else {
Write-Host "$FailedChecks" -ForegroundColor Red
}
Write-Host ""
if ($FailedChecks -eq 0) {
Write-Host "============================================================" -ForegroundColor Green
Write-Host " RESULTAT: Das System entspricht voll den BSI-Vorgaben!" -ForegroundColor Green
Write-Host "============================================================" -ForegroundColor Green
} else {
Write-Host "============================================================" -ForegroundColor Red
Write-Host " RESULTAT: Handlungsbedarf! Es wurden Schwachstellen gefunden." -ForegroundColor Red
Write-Host "============================================================" -ForegroundColor Red
}
Write-Host ""
Schritt 4: WLAN-Dienste prüfen & störende Beacons unterdrücken (Manual_Test_WLAN_Beacon_Diag.ps1)
Ein interessantes Detail am Rande: Damit das automatische Verbinden mit dem heimischen WLAN nach der Dienstbereinigung reibungslos funktioniert, muss der Dienst wlansvc (WLAN AutoConfig) aktiv bleiben.
Hingegen führt der Dienst wcncsvc (Windows Connect Now) oft dazu, dass fremde Geräte oder Beacons unaufgefordert im Datei-Explorer auftauchen. Daher lässt sich dieser gezielt deaktivieren.
WLAN-Diagnoseskript:
#requires -version 5.1
<#
============================================================
WLAN SERVICES DIAGNOSTIC SCRIPT
Version: 1.0
Zweck:
Überprüft den Status von 'wlansvc' (WLAN AutoConfig)
und 'wcncsvc' (Windows Connect Now), um die korrekte
Funktion der automatischen WLAN-Verbindung zu bestätigen.
============================================================
#>
Clear-Host
Write-Host "============================================================" -ForegroundColor DarkCyan
Write-Host " WLAN DIENSTE-STATUS DIAGNOSE" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor DarkCyan
Write-Host ""
# 1. Hauptdienst für automatische WLAN-Verbindungen prüfen
try {
$WlanSvc = Get-Service -Name "wlansvc" -ErrorAction Stop
Write-Host "[1] WLAN AutoConfig (wlansvc) - Hauptdienst:" -ForegroundColor White
Write-Host " Status: $($WlanSvc.Status)" -ForegroundColor Green
Write-Host " Starttyp: $($WlanSvc.StartType)" -ForegroundColor Green
if ($WlanSvc.Status -eq "Running") {
Write-Host " -> ERFOLG: Automatische WLAN-Verbindungen funktionieren einwandfrei." -ForegroundColor Green
} else {
Write-Host " -> WARNUNG: Der Hauptdienst läuft nicht!" -ForegroundColor Red
}
} catch {
Write-Host " [ FEHLER ] Dienst 'wlansvc' konnte nicht abgefragt werden." -ForegroundColor Red
}
Write-Host ""
# 2. Deaktivierten Connect Now Dienst prüfen
try {
$WcnSvc = Get-Service -Name "wcncsvc" -ErrorAction Stop
Write-Host "[2] Windows Connect Now (wcncsvc) - Beacon/WPS-Dienst:" -ForegroundColor White
Write-Host " Status: $($WcnSvc.Status)" -ForegroundColor Yellow
Write-Host " Starttyp: $($WcnSvc.StartType)" -ForegroundColor Yellow
if ($WcnSvc.StartType -eq "Disabled") {
Write-Host " -> ERFOLG: Fremde WLAN-Beacons/Geräte werden im Explorer unterdrückt." -ForegroundColor Green
}
} catch {
Write-Host " [ FEHLER ] Dienst 'wcncsvc' konnte nicht abgefragt werden." -ForegroundColor Red
}
Write-Host ""
Write-Host "============================================================" -ForegroundColor DarkCyan
Einzeiler zur direkten Deaktivierung von Windows Connect Now:
Stop-Service -Name "wcncsvc" -Force
Set-Service -Name "wcncsvc" -StartupType Disabled
Fazit: Mindestmaß an Sicherheit ohne Daueraufwand
Nach einer Inplace-Reparatur ist das System zwar wieder frei von Softwarefehlern, aber eben auch ungeschützt bezüglich Telemetrie und überflüssiger Netzwerkdienste.
Mit dieser Skript-Sammlung lässt sich das Re-Härten nach BSI-Vorgaben innerhalb weniger Sekunden automatisieren. Auch Herstellersoftware wie die von Killer Network verliert ihren Schrecken, da der reine Treiber erhalten bleibt, während die leistungsmindernden Dienste dauerhaft deaktiviert werden.
Das Skript wurde mit Hilfe von Chat GPT und Gemini Geprüft. Beitragsbild ist mit Gemini Generiert.



