Загрузка данных


#requires -version 2.0

<#
.SYNOPSIS
    Проверка отключения протокола SMB v1 (клиент и сервер).

.DESCRIPTION
    Клиентская сторона (исходящие):
      - Драйвер mrxsmb10: Start = 4 (Disabled) или отсутствует
      - ИЛИ LanmanWorkstation\Smb1 = 0
      Любое из условий = PASS.

    Серверная сторона (входящие):
      - LanmanServer\SMB1 = 0
      - На Windows 10+ параметр может отсутствовать (отключён по умолчанию).
      - На Windows 7 отсутствие параметра = FAIL (включён по умолчанию).

    Обе стороны должны дать PASS для общего PASS.

    Включает случайную задержку 1-30 минут для новых машин.
#>

# ============================================================
# CONFIGURATION
# ============================================================

$ResultDirectory = "\\192.168.6.7\report\smbv1\"
$ComputerName = $env:COMPUTERNAME
$MarkerFile = Join-Path $ResultDirectory ($env:COMPUTERNAME + ".txt")

# ============================================================
# INITIALIZATION
# ============================================================

$ErrorActionPreference = "SilentlyContinue"

# ============================================================
# MARKER CHECK (проверяем сразу, без задержки)
# ============================================================

$ExistingMarker = Get-ChildItem `
    -Path $ResultDirectory `
    -Filter ($ComputerName + "_*.txt") `
    -ErrorAction SilentlyContinue |
    Select-Object -First 1

if ($null -ne $ExistingMarker) {

    Write-Host ""
    Write-Host "============================================================"
    Write-Host "SMB v1 DISABLE AUDIT"
    Write-Host "============================================================"
    Write-Host ""
    Write-Host "Computer: $ComputerName"
    Write-Host ""
    Write-Host "Audit already completed."
    Write-Host "Marker file:"
    Write-Host $ExistingMarker.Fullname
    Write-Host ""
    Write-Host "No action required."
    Write-Host "============================================================"

    exit 0
}

# ============================================================
# RANDOM DELAY (1-30 минут, только для новых машин)
# ============================================================

$MinDelaySeconds = 60
$MaxDelaySeconds = 60

$Random = New-Object System.Random
$Delay = $Random.Next($MinDelaySeconds, $MaxDelaySeconds)

Write-Host "Waiting $Delay seconds before audit (load balancing)..."

Start-Sleep -Seconds $Delay

# ============================================================
# VARIABLES
# ============================================================

$Results = New-Object System.Collections.ArrayList

$FailCount = 0
$WarnCount = 0
$PassCount = 0

$script:IsWin7 = $false
$script:PatchesOk = $false

# ============================================================
# FUNCTIONS
# ============================================================

function Add-Result {
    param(
        [string]$Status,
        [string]$Name,
        [string]$Details
    )

    $Line = "[{0}] {1}: {2}" -f `
        $Status, `
        $Name, `
        $Details

    [void]$Results.Add($Line)

    switch ($Status) {
        "PASS" { $script:PassCount++ }
        "FAIL" { $script:FailCount++ }
        "WARN" { $script:WarnCount++ }
    }
}

function Add-Section {
    param(
        [string]$Title
    )

    $Separator = ""
    $Separator = $Separator.PadLeft(60, "-")

    [void]$Results.Add("")
    [void]$Results.Add($Separator)
    [void]$Results.Add($Title)
    [void]$Results.Add($Separator)
}

function Get-RegistryValueSafe {
    param(
        [string]$Path,
        [string]$Name
    )

    try {
        $Property = Get-ItemProperty `
            -Path $Path `
            -Name $Name `
            -ErrorAction Stop

        return $Property.$Name
    }
    catch {
        return $null
    }
}

# ============================================================
# OS & PATCH CHECK
# ============================================================

function Test-OSandPatches {

    $OS = Get-WmiObject Win32_OperatingSystem
    $OSCaption = $OS.Caption
    $OSVersion = $OS.Version

    if ($OSVersion -like "6.1*") {
        $script:IsWin7 = $true
    }
    else {
        $script:IsWin7 = $false
    }

    if ($script:IsWin7) {

        $CutoffDate = [datetime]"2017-05-01"

        try {
            $HotFixes = Get-HotFix -ErrorAction Stop |
                Sort-Object InstalledOn -Descending

            $LatestHotFix = $HotFixes | Select-Object -First 1

            if ($null -ne $LatestHotFix -and $null -ne $LatestHotFix.InstalledOn) {

                $PatchDate = [datetime]$LatestHotFix.InstalledOn

                if ($PatchDate -ge $CutoffDate) {
                    $script:PatchesOk = $true
                    Add-Result -Status "PASS" -Name "OS & Patches" `
                        -Details "Windows 7. Последнее обновление: $($LatestHotFix.HotFixID) от $($LatestHotFix.InstalledOn). Патчи от 2017+ установлены."
                }
                else {
                    $script:PatchesOk = $false
                    Add-Result -Status "FAIL" -Name "OS & Patches" `
                        -Details "Windows 7. Последнее обновление: $($LatestHotFix.HotFixID) от $($LatestHotFix.InstalledOn). Патчи до мая 2017 — требуется установка обновлений."
                }
            }
            else {
                $script:PatchesOk = $false
                Add-Result -Status "FAIL" -Name "OS & Patches" `
                    -Details "Windows 7. Не удалось определить дату последнего обновления."
            }
        }
        catch {
            $script:PatchesOk = $false
            Add-Result -Status "FAIL" -Name "OS & Patches" `
                -Details "Windows 7. Не удалось получить список обновлений."
        }
    }
    else {

        $script:PatchesOk = $true
        Add-Result -Status "PASS" -Name "OS & Patches" `
            -Details "$OSCaption (версия $OSVersion). Проверка патчей не требуется."
    }
}

# ============================================================
# CLIENT SIDE CHECK
# ============================================================

function Test-Smb1ClientSide {

    # 1. Проверяем драйвер mrxsmb10

    $DriverPath = "HKLM:\SYSTEM\CurrentControlSet\Services\mrxsmb10"
    $DriverStart = Get-RegistryValueSafe -Path $DriverPath -Name "Start"

    $DriverDisabled = $false

    if ($null -eq $DriverStart) {
        $DriverDisabled = $true
        Add-Result -Status "PASS" -Name "Client mrxsmb10" `
            -Details "Драйвер mrxsmb10 отсутствует. Исходящие SMB v1 невозможны."
    }
    elseif ([int]$DriverStart -eq 4) {
        $DriverDisabled = $true
        Add-Result -Status "PASS" -Name "Client mrxsmb10" `
            -Details "Start = 4 (Disabled). Драйвер отключён. Исходящие SMB v1 невозможны."
    }
    elseif ([int]$DriverStart -eq 2) {
        Add-Result -Status "FAIL" -Name "Client mrxsmb10" `
            -Details "Start = 2 (Automatic). Драйвер включён — исходящие SMB v1 активны."
    }
    elseif ([int]$DriverStart -eq 3) {
        Add-Result -Status "FAIL" -Name "Client mrxsmb10" `
            -Details "Start = 3 (Manual). Драйвер доступен — исходящие SMB v1 могут быть активированы."
    }
    else {
        Add-Result -Status "FAIL" -Name "Client mrxsmb10" `
            -Details "Start = $DriverStart. Не удалось определить состояние — считается уязвимым."
    }

    # 2. Проверяем параметр Smb1 в LanmanWorkstation

    $ClientPath = "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters"
    $Smb1Value = Get-RegistryValueSafe -Path $ClientPath -Name "Smb1"

    if ($DriverDisabled) {
        # Драйвер уже отключил клиентскую сторону.
        # Параметр Smb1 не критичен, но проверяем для полноты картины.

        if ($null -eq $Smb1Value) {
            Add-Result -Status "PASS" -Name "Client Smb1" `
                -Details "Параметр отсутствует. Драйвер mrxsmb10 уже отключён — исходящие SMB v1 невозможны."
        }
        elseif ([int]$Smb1Value -eq 0) {
            Add-Result -Status "PASS" -Name "Client Smb1" `
                -Details "Значение = 0. Дополнительно отключено и через параметр."
        }
        else {
            Add-Result -Status "PASS" -Name "Client Smb1" `
                -Details "Значение = $Smb1Value, но драйвер mrxsmb10 отключён — исходящие SMB v1 невозможны."
        }
    }
    else {
        # Драйвер активен — параметр Smb1 критичен

        if ($null -eq $Smb1Value) {
            if ($script:IsWin7) {
                if ($script:PatchesOk) {
                    Add-Result -Status "FAIL" -Name "Client Smb1" `
                        -Details "Параметр отсутствует, драйвер активен. Патчи есть — нужно создать Smb1 = 0 или отключить драйвер."
                }
                else {
                    Add-Result -Status "FAIL" -Name "Client Smb1" `
                        -Details "Параметр отсутствует, драйвер активен. Патчей до 2017 нет — ключ Smb1 не отработает. Нужно отключить драйвер mrxsmb10."
                }
            }
            else {
                Add-Result -Status "FAIL" -Name "Client Smb1" `
                    -Details "Параметр отсутствует, драйвер активен. На данной ОС нужно создать Smb1 = 0 или отключить драйвер."
            }
        }
        elseif ([int]$Smb1Value -eq 0) {
            Add-Result -Status "PASS" -Name "Client Smb1" `
                -Details "Значение = 0. SMB v1 на клиенте отключён через параметр."
        }
        else {
            Add-Result -Status "FAIL" -Name "Client Smb1" `
                -Details "Значение = $Smb1Value. SMB v1 на клиенте включён."
        }
    }
}

# ============================================================
# SERVER SIDE CHECK
# ============================================================

function Test-Smb1ServerSide {

    $ServerPath = "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters"
    $SMB1Value = Get-RegistryValueSafe -Path $ServerPath -Name "SMB1"

    if ($null -eq $SMB1Value) {

        # Параметр отсутствует

        if ($script:IsWin7) {
            # Windows 7: параметр по умолчанию отсутствует = SMB v1 включён
            Add-Result -Status "FAIL" -Name "Server SMB1" `
                -Details "Параметр отсутствует. На Windows 7 SMB v1 на сервере включён по умолчанию. Нужно создать SMB1 = 0."
        }
        else {
            # Windows 10+: SMB v1 на сервере отключён по умолчанию (начиная с 1709)
            Add-Result -Status "PASS" -Name "Server SMB1" `
                -Details "Параметр отсутствует. На данной версии ОС SMB v1 на сервере отключён по умолчанию."
        }
    }
    elseif ([int]$SMB1Value -eq 0) {
        Add-Result -Status "PASS" -Name "Server SMB1" `
            -Details "Значение = 0. SMB v1 на сервере отключён."
    }
    else {
        Add-Result -Status "FAIL" -Name "Server SMB1" `
            -Details "Значение = $SMB1Value. SMB v1 на сервере включён."
    }
}

# ============================================================
# SYSTEM INFORMATION
# ============================================================

$OS = Get-WmiObject Win32_OperatingSystem
$ComputerSystem = Get-WmiObject Win32_ComputerSystem

$DateTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"

$OSCaption = $OS.Caption
$OSVersion = $OS.Version
$OSBuild = $OS.BuildNumber

$Domain = $ComputerSystem.Domain

$CurrentUser = `
    $env:USERDOMAIN + "\" + $env:USERNAME

$OSArchitecture = $OS.OSArchitecture

if ([string]::IsNullOrEmpty($OSArchitecture)) {
    if ([IntPtr]::Size -eq 8) {
        $OSArchitecture = "64-bit"
    }
    else {
        $OSArchitecture = "32-bit"
    }
}

# ============================================================
# REPORT HEADER
# ============================================================

[void]$Results.Add("============================================================")
[void]$Results.Add("SMB v1 DISABLE AUDIT")
[void]$Results.Add("============================================================")
[void]$Results.Add("")
[void]$Results.Add("Computer     : $ComputerName")
[void]$Results.Add("Domain       : $Domain")
[void]$Results.Add("OS           : $OSCaption")
[void]$Results.Add("Version      : $OSVersion")
[void]$Results.Add("Build        : $OSBuild")
[void]$Results.Add("Architecture : $OSArchitecture")
[void]$Results.Add("User         : $CurrentUser")
[void]$Results.Add("Date         : $DateTime")

# ============================================================
# 0. OS & PATCH PREREQUISITE CHECK
# ============================================================

Add-Section "0. OS & PATCH PREREQUISITE CHECK"

Test-OSandPatches

# ============================================================
# 1. CLIENT SIDE (исходящие SMB v1)
# ============================================================

Add-Section "1. CLIENT SIDE (исходящие SMB v1)"

Test-Smb1ClientSide

# ============================================================
# 2. SERVER SIDE (входящие SMB v1)
# ============================================================

Add-Section "2. SERVER SIDE (входящие SMB v1)"

Test-Smb1ServerSide

# ============================================================
# FINAL RESULT
# ============================================================

Add-Section "FINAL RESULT"

[void]$Results.Add("PASS : $PassCount")
[void]$Results.Add("WARN : $WarnCount")
[void]$Results.Add("FAIL : $FailCount")
[void]$Results.Add("")

if ($FailCount -eq 0 -and $WarnCount -eq 0) {

    $OverallStatus = "PASS"

    [void]$Results.Add("RESULT: PASS")
    [void]$Results.Add("SMB v1 полностью отключён (клиент и сервер).")
}
elseif ($FailCount -eq 0) {

    $OverallStatus = "PASS WITH WARNINGS"

    [void]$Results.Add("RESULT: PASS WITH WARNINGS")
    [void]$Results.Add("Критических нарушений не обнаружено, но присутствуют предупреждения.")
}
else {

    $OverallStatus = "FAIL"

    [void]$Results.Add("RESULT: FAIL")
    [void]$Results.Add("SMB v1 включён на клиенте и/или сервере. Требуется отключение.")
}

# ============================================================
# PREPARE OUTPUT
# ============================================================

$Header = ""
$Header = $Header.PadLeft(70, "=")

$Output = New-Object System.Collections.ArrayList

[void]$Output.Add("")
[void]$Output.Add($Header)
[void]$Output.Add("COMPUTER: $ComputerName")
[void]$Output.Add("DATE: $DateTime")
[void]$Output.Add($Header)

foreach ($Line in $Results) {
    [void]$Output.Add($Line)
}

[void]$Output.Add($Header)
[void]$Output.Add("END OF AUDIT: $ComputerName")
[void]$Output.Add($Header)
[void]$Output.Add("")

# ============================================================
# WRITE DETAILED RESULT / MARKER
# ============================================================

$ComputerResultFile = Join-Path `
    $ResultDirectory `
    ($ComputerName + ".txt")

$ResultSavedToNetwork = $false

try {
    $Output | Out-File `
        -FilePath $ComputerResultFile `
        -Encoding UTF8 `
        -Force

    $ResultSavedToNetwork = $true
}
catch {

    $LocalLogDirectory = "C:\smb_v1_check"

    if (-not (Test-Path $LocalLogDirectory)) {
        New-Item `
            -Path $LocalLogDirectory `
            -ItemType Directory `
            -Force | Out-Null
    }

    $LocalResult = Join-Path `
        $LocalLogDirectory `
        ($ComputerName + ".txt")

    $Output | Out-File `
        -FilePath $LocalResult `
        -Encoding UTF8 `
        -Force
}

# ============================================================
# RENAME NETWORK RESULT TO STATUS FILE
# ============================================================

if ($ResultSavedToNetwork) {

    $StatusForFileName = $OverallStatus.Replace(" ", "_")

    try {
        Rename-Item `
            -Path $ComputerResultFile `
            -NewName (
                $ComputerName + "_" +
                $StatusForFileName + ".txt"
            ) `
            -Force

        $MarkerFile = Join-Path $ResultDirectory ($ComputerName + "_" + $StatusForFileName + ".txt")
    }
    catch {
        $MarkerFile = $null
    }
}

# ============================================================
# CONSOLE OUTPUT
# ============================================================

Write-Host ""
Write-Host "============================================================"
Write-Host "SMB v1 DISABLE AUDIT"
Write-Host "============================================================"
Write-Host ""

foreach ($Line in $Results) {
    Write-Host $Line
}

Write-Host ""
Write-Host "============================================================"
Write-Host "Computer result:"
Write-Host $MarkerFile
Write-Host ""
Write-Host "Overall status:"
Write-Host $OverallStatus
Write-Host "============================================================"