ค้นหาเว็บไซต์

ถอดรหัสคำสั่ง PowerShell จากกระบวนการที่กำลังทำงานอยู่


ตัวอย่างนี้ทำงานบนแพลตฟอร์ม Windows เท่านั้น

ในบางครั้ง คุณอาจมีกระบวนการ PowerShell ที่ทำงานอยู่ซึ่งใช้ทรัพยากรจำนวนมาก กระบวนการนี้อาจทำงานในบริบทของงาน Task Scheduler หรืองาน SQL Server Agent ในกรณีที่มีกระบวนการ PowerShell หลายกระบวนการทำงานอยู่ อาจเป็นเรื่องยากที่จะทราบว่ากระบวนการใดแสดงถึงปัญหา บทความนี้แสดงวิธีการถอดรหัสบล็อกสคริปต์ที่กระบวนการ PowerShell กำลังทำงานอยู่

สร้างกระบวนการที่ใช้เวลานาน

เพื่อสาธิตสถานการณ์นี้ ให้เปิดหน้าต่าง PowerShell ใหม่และเรียกใช้รหัสต่อไปนี้ โดยจะรันคำสั่ง PowerShell ที่จะส่งออกตัวเลขทุกๆ นาทีเป็นเวลา 10 นาที

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

ดูกระบวนการ

เนื้อความของคำสั่งที่ PowerShell กำลังดำเนินการถูกจัดเก็บไว้ในคุณสมบัติ CommandLine ของคลาส Win32_Process หากคำสั่งเป็นคำสั่งที่เข้ารหัส คุณสมบัติ CommandLine จะมีสตริง "EncodedCommand" การใช้ข้อมูลนี้ คำสั่งที่เข้ารหัสสามารถยกเลิกการสร้างความสับสนได้โดยผ่านกระบวนการต่อไปนี้

เริ่ม PowerShell ในฐานะผู้ดูแลระบบ จำเป็นอย่างยิ่งที่ PowerShell จะทำงานในฐานะผู้ดูแลระบบ ไม่เช่นนั้นจะไม่มีการส่งคืนผลลัพธ์เมื่อสอบถามกระบวนการที่กำลังทำงานอยู่

ดำเนินการคำสั่งต่อไปนี้เพื่อรับกระบวนการ PowerShell ทั้งหมดที่มีคำสั่งที่เข้ารหัส:

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

คำสั่งต่อไปนี้สร้างวัตถุ PowerShell แบบกำหนดเองที่มี ID กระบวนการและคำสั่งที่เข้ารหัส

$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++
                     }

บทความที่เกี่ยวข้อง