次の方法で共有


実行中のプロセスからの PowerShell コマンドをデコードする

このサンプルは、Windows プラットフォームでのみ実行されます。

場合によっては、大量のリソースを占有している PowerShell プロセスが実行されている場合があります。 このプロセスは、 タスク スケジューラ ジョブまたは SQL Server エージェント ジョブのコンテキストで実行できます。 複数の PowerShell プロセスが実行されている場合、問題を表すプロセスを把握するのは困難な場合があります。 この記事では、PowerShell プロセスが現在実行されているスクリプト ブロックをデコードする方法について説明します。

実行時間の長いプロセスを作成する

このシナリオを示すには、新しい PowerShell ウィンドウを開き、次のコードを実行します。 1 分ごとに 10 分間の数値を出力する PowerShell コマンドを実行します。

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

プロセスを表示する

PowerShell が実行しているコマンドの本文は、Win32_Process クラスの CommandLine プロパティに格納されます。 コマンドがエンコードされたコマンドの場合、 CommandLine プロパティには文字列 "EncodedCommand" が含まれます。 この情報を使用して、エンコードされたコマンドを次のプロセスで難読化解除できます。

管理者として PowerShell を起動します。 PowerShell が管理者として実行されていることが重要です。それ以外の場合は、実行中のプロセスに対してクエリを実行しても結果は返されません。

次のコマンドを実行して、エンコードされたコマンドを持つすべての PowerShell プロセスを取得します。

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

次のコマンドは、プロセス ID とエンコードされたコマンドを含むカスタム PowerShell オブジェクトを作成します。

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

エンコードされたコマンドをデコードできるようになりました。 次のスニペットは、コマンドの詳細オブジェクトを反復処理し、エンコードされたコマンドをデコードし、デコードされたコマンドをオブジェクトに追加してさらに調査します。

$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 *

デコードされたコマンド プロパティを選択して、デコードされたコマンドを確認できるようになりました。

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