เจาะลึกเทคนิคถอดรหัส PowerShell -EncodedCommand เมื่อเจออักษรเว้นวรรคประหลาด
ไขข้อข้องใจปัญหาถอดรหัส Base64 ของ PowerShell แล้วเจอช่องว่างระหว่างตัวอักษร พร้อมวิธีแก้อย่างรวดเร็วด้วย UTF-16LE และการจัดการ payload ซ้อน gzip

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
- พารามิเตอร์ -EncodedCommand หรือ -enc ของ PowerShell ใช้รูปแบบ Base64 ของ UTF-16LE
- อาการตัวอักษรเว้นวรรคหรือมีอักขระ null เกิดจากการอ่านผลลัพธ์แบบ UTF-8 แทนที่จะเป็น UTF-16LE
- หากถอดรหัสแล้วยังเจอข้อมูลขยะ ให้ตรวจสอบรูปแบบการบีบอัดแบบ gzip ที่ขึ้นต้นด้วย H4sI
- การถอดรหัสและการขยายข้อมูลเหล่านี้มีความปลอดภัยเนื่องจากเป็นเพียงการแปลงข้อมูลโดยไม่มีการรันคำสั่ง
ระหว่างกระบวนการตรวจสอบความปลอดภัยหรือ Incident Response นักวิเคราะห์มักจะต้องเผชิญหน้ากับคำสั่งแปลกปลอม เช่น powershell.exe -nop -w hidden -enc JABjACAAPQAg... ซึ่งเป็นรูปแบบที่พบบ่อยในการซ่อนคำสั่งอันตราย วิธีการทั่วไปคือการนำชุดข้อมูล Base64 นี้ไปถอดรหัสเพื่ออ่านสคริปต์ข้างใน แต่เมื่อนำไปแปลงกลับมักจะได้ข้อความที่มีช่องว่างหรืออักขระว่างคั่นระหว่างตัวอักษรทุกตัว ทำให้เข้าใจผิดว่าชุดข้อมูลนี้ถูกเข้ารหัสซ้ำซ้อนหรือถูกเข้ารหัสลับแบบอื่น ทั้งที่จริงแล้วนี่คือกับดักที่พบบ่อยที่สุดในการใช้งานพารามิเตอร์ -EncodedCommand
สาเหตุของปัญหานี้มาจากตัว PowerShell เองที่กำหนดให้ -enc ต้องใช้ชุดอักขระแบบ UTF-16LE หรือ little-endian Unicode ในระบบ .NET แทนที่จะเป็น UTF-8 ในมาตรฐาน UTF-16LE นี้ ตัวอักษรภาษาอังกฤษหรือ ASCII แต่ละตัวจะถูกจัดเก็บโดยใช้ไบต์คู่ คือตัวอักษรตามด้วยไบต์ null 0x00 เช่น ตัวอักษร c จะถูกเก็บเป็น 0x63 0x00 เมื่อนำไปถอดรหัส Base64 แล้วอ่านด้วยการเข้ารหัสแบบ UTF-8 ไบต์ null เหล่านี้จึงแสดงผลออกมาเป็นช่องว่างหรืออักขระควบคุมที่มองไม่เห็น ส่งผลให้ข้อความกระจายตัวออกห่างกัน

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
การเข้าใจกลไกการเข้ารหัสแบบ UTF-16LE ถือเป็นทักษะสำคัญสำหรับผู้เชี่ยวชาญด้านความมั่นคงปลอดภัยไซเบอร์ เนื่องจากระบบปฏิบัติการ Windows และ .NET Framework ใช้การเข้ารหัสนี้เป็นมาตรฐานภายในระดับลึก การที่มลแวร์หรือแม้แต่สคริปต์อัตโนมัติทั่วไปเลือกใช้ -EncodedCommand จึงไม่ใช่เพราะต้องการหลบเลี่ยงการตรวจสอบเพียงอย่างเดียว แต่เพราะเป็นวิธีการที่สะอาดและปลอดภัยที่สุดในการส่งผ่านสคริปต์หลายบรรทัดผ่านอาร์กิวเมนต์ตัวเดียวโดยไม่ต้องกังวลเรื่องปัญหาเครื่องหมายคำพูดตีกัน
การแก้ไขปัญหานี้สามารถทำได้ง่ายโดยระบุรูปแบบการถอดรหัสให้ถูกต้องตามชุดข้อมูล ดังนี้:
- ใน PowerShell: ใช้คำสั่ง [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($enc))
- ในภาษา Python: ถอดรหัสไบต์ Base64 แล้วแปลงด้วย utf-16-le
- ในเครื่องมือ CyberChef: เลือกสูตร From Base64 ไปยัง Decode text แบบ UTF-16LE หรือเลือก From Base64 แล้วทำการ Remove null bytes
อย่างไรก็ตาม ในบางครั้งเมื่อถอดรหัสสำเร็จแล้วอาจยังคงพบข้อมูลไบนารีขยะ ซึ่งเกิดจากเทคนิคชั้นถัดไปที่มักพบได้บ่อย นั่นคือสคริปต์จริงถูกนำไปบีบอัดด้วย gzip ก่อนจะนำมาแปลงเป็น Base64 อีกทอดหนึ่ง ตัวสคริปต์ภายนอกที่เพิ่งถอดรหัสออกมาจึงเป็นเพียงตัวโหลดขนาดเล็กที่มีหน้าที่ขยาย payload ด้านในให้อยู่ในหน่วยความจำ จุดสังเกตสำคัญคือชุดข้อมูล Base64 ภายในที่ขึ้นต้นด้วย H4sI ซึ่งแสดงถึงเลขมายากลของ gzip หรือ 1f 8b ในรูปแบบ Base64 หากพบรูปแบบนี้จะต้องทำการถอดรหัส Base64 ซ้ำอีกครั้งและทำการคลายบีบอัด gzip เพื่อเข้าถึงสคริปต์ตัวจริง ซึ่งกระบวนการซ้อนชั้นเช่นนี้อาจลึกถึงสองหรือสามชั้น
ที่มา: Dev.to
พบข้อมูลผิดพลาดในบทความนี้? แจ้งปัญหาบทความนี้
ความคิดเห็น
แสดงความคิดเห็น