Private/Kinds/NetworkDependencyElevated.ps1

# The NetworkDependencyElevated Kind: where the running processes are from, and the
# modules they loaded that are not on the machine's own drives, read with admin rights.
#
# The NetworkDependency Kind runs in the Main Part, where the drives of the person at the
# machine are known, and may not open a process of the system or of another account: its
# program path stays unread, and so do the modules of every process that hosts a service.
# A Report then said "not examined ... only readable with admin rights" of a Run that had
# them. This Kind reads the same with admin rights and judges nothing: the
# NetworkDependency Check is handed its reading as $Observed['NetworkDependencyElevated']
# and fills in what it could not read itself.
#
# It places nothing. The Elevated Part has its own logon and does not know what K: is, so
# a path is kept as the process has it and the Check in the Main Part resolves it.
#
# Its one Finding says that the reading was taken, so that the Check is accounted for in
# the Report like any other.

$script:NetworkDependencyElevatedNeedsAdmin = $true

# What Get-NetworkDependencyElevatedData hands its Judge. See Private/DataShape.ps1.
$script:NetworkDependencyElevatedDataShape = @{
    Processes        = 'List'
    ModuleTraces     = 'List'
    ModuleUnexamined = 'List'
}

function Get-NetworkDependencyElevatedData {
    <#
    .SYNOPSIS
        Every running process with where its program is, and the modules they loaded from
        anywhere but the machine's own drives, as an administrator may read them. Decides
        nothing.
    #>

    [CmdletBinding()]
    [OutputType([psobject])]
    param([hashtable]$Parameters = @{})

    $processes = @(Get-Process -ErrorAction SilentlyContinue | ForEach-Object {
        $path = $null
        try { $path = $_.Path } catch { }
        [pscustomobject]@{ Name = "$($_.ProcessName)"; Id = [int]$_.Id; SessionId = [int]$_.SessionId; Path = "$path" }
    })

    # Every process, and not only those that host a service: with admin rights all of them
    # can be opened, and the Main Part asks for the ones it could not.
    $ids  = @($processes | ForEach-Object { $_.Id } | Sort-Object -Unique)

    # An administrator may open any process, but Windows hands that right out switched
    # off (SeDebugPrivilege): without it the processes of the system refuse an
    # administrator as they refuse anybody. A Run with admin rights was refused 126
    # service processes that way. Switched on for this reading and off again after it;
    # what is still refused then, Windows protects from administrators too.
    $debug = $false
    try { [System.Diagnostics.Process]::EnterDebugMode(); $debug = $true } catch { }
    try {
        $read = ConvertTo-NetworkDependencyModuleTrace -LocalDrive @(Get-NetworkDependencyDriveLetter) `
            -ProcessModule @(Get-NetworkDependencyProcessModule -ServiceProcessId $ids)
    }
    finally {
        if ($debug) { try { [System.Diagnostics.Process]::LeaveDebugMode() } catch { } }
    }

    [pscustomobject]@{
        PSTypeName       = 'Gutcheck.Data.NetworkDependencyElevated'
        Processes        = $processes
        ModuleTraces     = @($read.Traces)
        # What even an administrator could not open: a protected process of Windows.
        ModuleUnexamined = @($read.Unexamined)
    }
}

function ConvertTo-NetworkDependencyElevatedFinding {
    <#
    .SYNOPSIS
        One Finding saying how much was read with admin rights. Pure.
    .DESCRIPTION
        No judgement: what a program depends on is the NetworkDependency Check's to say.
    #>

    [CmdletBinding()]
    [OutputType([psobject])]
    param([AllowNull()]$Data, [hashtable]$Parameters = @{})

    $processes = @((Get-DataCollection $Data 'Processes') | ForEach-Object { $_ })
    if (-not $processes.Count) {
        return New-UnavailableFinding -Category Network -Check (Get-Text 'Check.NetworkDependencyElevated.Reading') `
            -Hint (Get-Text 'Hint.Program.NothingRead')
    }

    $withPath = @($processes | Where-Object { "$(Get-DataProperty $_ 'Path')" }).Count
    New-Finding -Category Network -Check (Get-Text 'Check.NetworkDependencyElevated.Reading') -Severity OK `
        -Value ((Get-Text 'Value.NetworkDependencyElevated.Reading') -f $processes.Count, $withPath, (Get-DataCollection $Data 'ModuleTraces').Count)
}