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


$ErrorActionPreference = 'SilentlyContinue'

# Допустимые имена хостов: klipa1 ... klipa35
$KlipaRegex = '(?i)\bklipa(?:[1-9]|[12][0-9]|3[0-5])\b'

$Results = New-Object System.Collections.Generic.List[object]

# WScript.Shell нужен для чтения .lnk
$WshShell = New-Object -ComObject WScript.Shell

# Берем реальные папки профилей из C:\Users
$UserProfiles = Get-ChildItem -Path 'C:\Users' -Directory -Force |
    Where-Object {
        $_.Name -notin @(
            'Public',
            'Default',
            'Default User',
            'All Users'
        )
    }

foreach ($UserProfile in $UserProfiles) {

    $UserName = $UserProfile.Name

    # Только папки первого уровня профиля, кроме AppData.
    # После этого внутри каждой такой папки поиск идет рекурсивно.
    $FirstLevelFolders = Get-ChildItem -Path $UserProfile.FullName -Directory -Force |
        Where-Object {
            $_.Name -ne 'AppData'
        }

    foreach ($Folder in $FirstLevelFolders) {

        # Ищем только RDP-файлы и Windows-ярлыки
        $Files = Get-ChildItem `
            -Path $Folder.FullName `
            -File `
            -Recurse `
            -Force `
            -Include '*.rdp', '*.lnk' `
            -ErrorAction SilentlyContinue

        foreach ($File in $Files) {

            # ------------------------------------------------------------
            # .RDP
            # ------------------------------------------------------------
            if ($File.Extension -ieq '.rdp') {

                $Content = Get-Content -LiteralPath $File.FullName -Raw -ErrorAction SilentlyContinue

                if (-not $Content) {
                    continue
                }

                # Стандартная строка в RDP:
                # full address:s:klipa12
                $AddressMatch = [regex]::Match(
                    $Content,
                    '(?im)^\s*full address\s*:\s*s\s*:\s*(?<host>[^\r\n:]+)'
                )

                if ($AddressMatch.Success) {

                    $HostName = $AddressMatch.Groups['host'].Value.Trim()

                    if ($HostName -match "^$KlipaRegex$") {

                        $Results.Add([PSCustomObject]@{
                            User = $UserName
                            Host = $HostName
                            Type = 'RDP'
                            Path = $File.FullName
                        })
                    }
                }
            }

            # ------------------------------------------------------------
            # .LNK
            # ------------------------------------------------------------
            elseif ($File.Extension -ieq '.lnk') {

                try {
                    $Shortcut = $WshShell.CreateShortcut($File.FullName)

                    $TargetPath = $Shortcut.TargetPath
                    $Arguments  = $Shortcut.Arguments

                    $MatchedHost = $null

                    # Вариант 1:
                    # ярлык запускает mstsc.exe /v:klipa12
                    if (
                        $TargetPath -match '(?i)\\mstsc\.exe$' -or
                        [System.IO.Path]::GetFileName($TargetPath) -ieq 'mstsc.exe'
                    ) {
                        $ArgMatch = [regex]::Match(
                            $Arguments,
                            '(?i)(?:/v:|/v\s+)(?<host>klipa(?:[1-9]|[12][0-9]|3[0-5]))(?:\b|:)'
                        )

                        if ($ArgMatch.Success) {
                            $MatchedHost = $ArgMatch.Groups['host'].Value
                        }
                    }

                    # Вариант 2:
                    # ярлык напрямую указывает на .rdp-файл
                    if (
                        -not $MatchedHost -and
                        $TargetPath -and
                        $TargetPath.EndsWith('.rdp', [System.StringComparison]::OrdinalIgnoreCase) -and
                        (Test-Path -LiteralPath $TargetPath)
                    ) {
                        $RdpContent = Get-Content -LiteralPath $TargetPath -Raw -ErrorAction SilentlyContinue

                        if ($RdpContent) {

                            $AddressMatch = [regex]::Match(
                                $RdpContent,
                                '(?im)^\s*full address\s*:\s*s\s*:\s*(?<host>[^\r\n:]+)'
                            )

                            if ($AddressMatch.Success) {

                                $HostName = $AddressMatch.Groups['host'].Value.Trim()

                                if ($HostName -match "^$KlipaRegex$") {
                                    $MatchedHost = $HostName
                                }
                            }
                        }
                    }

                    if ($MatchedHost) {

                        $Results.Add([PSCustomObject]@{
                            User = $UserName
                            Host = $MatchedHost
                            Type = 'LNK'
                            Path = $File.FullName
                        })
                    }
                }
                catch {
                    # Битые/недоступные ярлыки просто пропускаем
                }
            }
        }
    }
}

# Убираем возможные дубли
$Results = $Results |
    Sort-Object User, Host, Type, Path -Unique

Write-Output '============================================================'
Write-Output 'RDP KLIPA SCAN'
Write-Output "Computer: $env:COMPUTERNAME"
Write-Output '============================================================'

if (-not $Results -or $Results.Count -eq 0) {

    Write-Output 'Совпадений не найдено.'
}
else {

    Write-Output "Найдено совпадений: $($Results.Count)"
    Write-Output ''

    foreach ($Result in $Results) {

        Write-Output "Пользователь : $($Result.User)"
        Write-Output "Клипа        : $($Result.Host)"
        Write-Output "Тип          : $($Result.Type)"
        Write-Output "Файл         : $($Result.Path)"
        Write-Output '------------------------------------------------------------'
    }
}

Write-Output 'Сканирование завершено.'