PowerShell komutunun kodunu çalışan bir işlemden çözme

Bu örnek yalnızca Windows platformlarında çalışır.

Bazen, büyük miktarda kaynak alan bir PowerShell işleminiz olabilir. Bu işlem bir Görev Zamanlayıcı işi veya SQL Server Aracısı işi bağlamında çalışıyor olabilir. Birden çok PowerShell işleminin çalıştığı durumlarda, hangi işlemin sorunu temsil ettiği bilinmesi zor olabilir. Bu makalede, PowerShell işleminin çalışmakta olduğu bir betik bloğunun kodunu çözme işlemi gösterilmektedir.

Uzun süre çalışan bir işlem oluşturma

Bu senaryoyu göstermek için yeni bir PowerShell penceresi açın ve aşağıdaki kodu çalıştırın. Dakikada bir 10 dakika boyunca bir sayı veren bir PowerShell komutu yürütür.

powershell.exe -Command {
    $i = 1
    while ( $i -le 10 )
    {
        Write-Output -InputObject $i
        Start-Sleep -Seconds 60
        $i++
    }
}

İşlemi görüntüleme

PowerShell'in yürüttüğü komutun gövdesi, Win32_Process sınıfının CommandLine özelliğinde depolanır. Komut kodlanmış bir komutsa, CommandLine özelliği "EncodedCommand" dizesini içerir. Bu bilgiler kullanılarak, kodlanmış komut aşağıdaki işlemle gizlenebilir.

PowerShell'i Yönetici istrator olarak başlatın. PowerShell'in yönetici olarak çalışması çok önemlidir, aksi takdirde çalışan işlemler sorgulanırken hiçbir sonuç döndürülmüyor.

Kodlanmış bir komutu olan tüm PowerShell işlemlerini almak için aşağıdaki komutu yürütür:

$powerShellProcesses = Get-CimInstance -ClassName Win32_Process -Filter 'CommandLine LIKE "%EncodedCommand%"'

Aşağıdaki komut, işlem kimliğini ve kodlanmış komutu içeren özel bir PowerShell nesnesi oluşturur.

$commandDetails = $powerShellProcesses | Select-Object -Property ProcessId,
@{
    name       = 'EncodedCommand'
    expression = {
        if ( $_.CommandLine -match 'encodedCommand (.*) -inputFormat' )
        {
            return $matches[1]
        }
    }
}

Artık kodlanmış komutun kodu çözülebilir. Aşağıdaki kod parçacığı komut ayrıntıları nesnesi üzerinde yinelenir, kodlanmış komutun kodunu çözer ve daha fazla araştırma için kodu çözülen komutu nesnesine geri ekler.

$commandDetails | ForEach-Object -Process {
    # Get the current process
    $currentProcess = $_

    # Convert the Base 64 string to a Byte Array
    $commandBytes = [System.Convert]::FromBase64String($currentProcess.EncodedCommand)

    # Convert the Byte Array to a string
    $decodedCommand = [System.Text.Encoding]::Unicode.GetString($commandBytes)

    # Add the decoded command back to the object
    $commandDetails |
        Where-Object -FilterScript { $_.ProcessId -eq $currentProcess.processId } |
        Add-Member -MemberType NoteProperty -Name DecodedCommand -Value $decodedCommand
}
$commandDetails[0] | Format-List -Property *

Kodu çözülen komut artık kodu çözülen komut özelliği seçilerek gözden geçirilebilir.

ProcessId      : 8752
EncodedCommand : IAAKAAoACgAgAAoAIAAgACAAIAAkAGkAIAA9ACAAMQAgAAoACgAKACAACgAgACAAIAAgAHcAaABpAGwAZQAgACgAIAAkAGkAIAAtAG
                 wAZQAgADEAMAAgACkAIAAKAAoACgAgAAoAIAAgACAAIAB7ACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABXAHIAaQB0AGUALQBP
                 AHUAdABwAHUAdAAgAC0ASQBuAHAAdQB0AE8AYgBqAGUAYwB0ACAAJABpACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABTAHQAYQ
                 ByAHQALQBTAGwAZQBlAHAAIAAtAFMAZQBjAG8AbgBkAHMAIAA2ADAAIAAKAAoACgAgAAoAIAAgACAAIAAgACAAIAAgACQAaQArACsA
                 IAAKAAoACgAgAAoAIAAgACAAIAB9ACAACgAKAAoAIAAKAA==
DecodedCommand :
                     $i = 1
                     while ( $i -le 10 )
                     {
                         Write-Output -InputObject $i
                         Start-Sleep -Seconds 60
                         $i++
                     }