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


$ErrorActionPreference = 'SilentlyContinue'

$Results = @()

# klipa1 ... klipa35
$KlipaPattern = '^klipa(?:[1-9]|[12][0-9]|3[0-5])$'

$WshShell = New-Object -ComObject WScript.Shell

$UserProfiles = Get-ChildItem -LiteralPath '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 `
        -LiteralPath $UserProfile.FullName `
        -Directory `
        -Force `
        -ErrorAction SilentlyContinue |
        Where-Object {
            $_.Name -ne 'AppData'
        }

    foreach ($Folder in $FirstLevelFolders) {

        # ВАЖНО:
        # не используем -Include, сначала получаем все файлы
        $Files = Get-ChildItem `
            -LiteralPath $Folder.FullName `
            -File `
            -Recurse `
            -Force `
            -ErrorAction SilentlyContinue |
            Where-Object {
                $_.Extension -ieq '.rdp' -or
                $_.Extension -ieq '.lnk'
            }

        foreach ($File in $Files) {

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

                try {
                    $Content = Get-Content `
                        -LiteralPath $File.FullName `
                        -Raw `
                        -ErrorAction Stop

                    # Ищем:
                    # full address:s:klipa1
                    # full address:s:klipa1:3389
                    # full address:s:klipa1.domain.local
                    $AddressMatch = [regex]::Match(
                        $Content,
                        '(?im)^\s*full\s+address\s*:\s*s\s*:\s*(?<address>[^\r\n]+)'
                    )

                    if ($AddressMatch.Success) {

                        $Address = $AddressMatch.Groups['address'].Value.Trim()

                        # Убираем порт
                        $HostName = ($Address -split ':')[0].Trim()

                        # Если FQDN вида klipa1.domain.local,
                        # берем короткое имя klipa1
                        $ShortHost = ($HostName -split '\.')[0].Trim()

                        if ($ShortHost -match $KlipaPattern) {

                            $Results += [PSCustomObject]@{
                                User    = $UserName
                                Host    = $ShortHost
                                Type    = 'RDP'
                                Path    = $File.FullName
                                Address = $Address
                            }
                        }
                    }
                }
                catch {
                    Write-Output "Не удалось прочитать RDP: $($File.FullName)"
                }
            }

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

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

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

                    $MatchedHost = $null
                    $Address     = $null

                    # ----------------------------------------------------
                    # mstsc.exe /v:klipa1
                    # mstsc.exe /v klipa1
                    # mstsc.exe /v:klipa1:3389
                    # ----------------------------------------------------
                    if (
                        [System.IO.Path]::GetFileName($TargetPath) -ieq 'mstsc.exe'
                    ) {
                        $ArgMatch = [regex]::Match(
                            $Arguments,
                            '(?i)/v(?::|\s+)\s*(?<address>[^\s"]+)'
                        )

                        if ($ArgMatch.Success) {

                            $Address = $ArgMatch.Groups['address'].Value.Trim()

                            $HostName = ($Address -split ':')[0]
                            $ShortHost = ($HostName -split '\.')[0]

                            if ($ShortHost -match $KlipaPattern) {
                                $MatchedHost = $ShortHost
                            }
                        }
                    }

                    # ----------------------------------------------------
                    # Ярлык непосредственно на .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\s+address\s*:\s*s\s*:\s*(?<address>[^\r\n]+)'
                            )

                            if ($AddressMatch.Success) {

                                $Address = $AddressMatch.Groups['address'].Value.Trim()

                                $HostName = ($Address -split ':')[0]
                                $ShortHost = ($HostName -split '\.')[0]

                                if ($ShortHost -match $KlipaPattern) {
                                    $MatchedHost = $ShortHost
                                }
                            }
                        }
                    }

                    if ($MatchedHost) {

                        $Results += [PSCustomObject]@{
                            User    = $UserName
                            Host    = $MatchedHost
                            Type    = 'LNK'
                            Path    = $File.FullName
                            Address = $Address
                        }
                    }
                }
                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) {

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

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

    foreach ($Result in $Results) {

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

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