Home

Published

- 8 min read

Hypervisor Internals 101

img of Hypervisor Internals 101

บทนำ

ในปัจจุบันผู้ผลิต Processor หรือ CPU ได้มีการรองรับการทำ Hardware Virtualization เช่น ฝั่ง Intel ก็จะมี Intel VT-x (Intel Virtualization Technology) ฝั่ง AMD ก็จะมี AMD-V ที่ทำหน้าที่เหมือนกันกับ Intel VT-x คือ การอนุญาตให้ software สามารถจำลองสภาพแวดล้อมของ hardware ได้ ซึ่งชุด software ที่ว่าก็คือ Hypervisor หรือ Virtual Machine Monitor (VMM) ที่จะคอยทำหน้าที่เป็นตัวกลางระหว่างฮาร์ดแวร์จริง (Physical Hardware) และระบบปฏิบัติการที่รันใน VMs (Guest OS) ซึ่งในมุมมองด้านความปลอดภัย Hypervisor ถือเป็นหัวข้อที่หน้าสนใจอย่างยิ่ง

Hypervisor Type-1 และ Type-2 คืออะไร

Hypervisor Type-1 และ Type-2 เป็นสองประเภทหลักของ Hypervisor ซึ่งเป็นซอฟต์แวร์ที่ใช้สำหรับจัดการ Virtual Machines (VMs) โดยมีความแตกต่างกันในแง่ของการทำงานและโครงสร้างพื้นฐาน ดังนี้

  • Hypervisor Type-1 (Bare-Metal Hypervisor) Hypervisor Type-1 รันโดยตรงบนฮาร์ดแวร์ของเครื่องคอมพิวเตอร์โดยไม่ต้องมีระบบปฏิบัติการ (OS) ระหว่าง Hypervisor และฮาร์ดแวร์ ตัวอย่างเช่น VMware ESXi , Microsoft Hyper-V (ในโหมด Bare Metal), Xen และ KVM (Kernel-based Virtual Machine)

  • Hypervisor Type-2 (Hosted Hypervisor) Hypervisor Type-2 รันบนระบบปฏิบัติการที่มีอยู่แล้ว (Host OS) และทำหน้าที่เป็นแอปพลิเคชันที่สร้าง Virtual Machines ตัวอย่างเช่น VMware Workstation, Oracle VirtualBox, Parallels Desktop และ QEMU (Quick Emulator)

ซึ่งในบทความนี้จะโฟกัสที่ Hypervisor Type-2 เป็นหลัก เพราะเป็น Hypervisor ที่ Programmer สามารถพัฒนาขึ้นมาเองได้ง่าย (ไม่จริง) เพื่อใช้ในวัตถุประสงค์ที่ดี และไม่ดี (Attack and Defense) และจะอธิบายแค่ในส่วนของ Intel VT-x (Intel Virtualization Technology)

ข้อควรรู้ในบทความนี้

เนื่องจากการที่จะอธิบายเรื่อง hypervisor นั้นมีคำศัพท์ทาง technical ที่เยอะมาก เพื่อเข้าใจตรงกัน ผู้เขียนขออนุญาตใช้คำเหล่านี้สลับกัน แต่ให้รับทราบไว้ว่ามันคือสิ่งเดียวกัน

  • คำว่า Hypervisor, Virtual Machine Monitor (VMM) และคำว่า Host หรือ Host OS จะมีความหมายเดียวกัน คือหมายถึงชุด software hypervisor ที่ถูกพัฒนาขึ้นเพื่อเหตุผลบางอย่าง
  • คำว่า Processor, Physical Processor และคำว่า CPU หรือ CPU Core จะมีความหมายเดียวกัน คือหมายถึง Core ใน CPU
  • เนื่องจาก concept ของการทำ Hypervisor นั้นส่วนมากจะเป็น abstract และต้องใช้ความรู้พื้นฐานจำนวนมาก แนะนำให้ผู้อ่านไปข้ามดู video demo คร่าวๆเพื่อ satisfy ตัวเอง และควรศึกษา source code ตัวอย่างไปพร้อมๆกับการอ่านบทความนี้ (https://github.com/un4ckn0wl3z/SimpleHypervisor)

Hypervisor Internals 101

Hypervisor หรือที่เรียกอีกชื่อว่า Virtual Machine Monitor (VMM) เป็นซอฟต์แวร์ที่ทำหน้าที่จัดการและควบคุม Virtual Machines (VMs) โดย Hypervisor ในระดับต่ำสุดมักจะพัฒนาในรูปแบบ Kernel Mode Driver ซึ่งเป็นส่วนหนึ่งของระบบปฏิบัติการที่ทำงานในระดับ Ring 0 ของ CPU

เหตุผลที่ Hypervisor ต้องเป็น Kernel Mode Driver

  • การเข้าถึง VMX Instructions CPU ที่รองรับการใช้งาน Virtualization (เช่น Intel VT-x หรือ AMD-V) จะมีชุดคำสั่งพิเศษที่เรียกว่า VMX Instructions ซึ่งใช้สำหรับจัดการการทำงานของ VMs คำสั่งเหล่านี้สามารถใช้งานได้เฉพาะในระดับ Ring 0 เท่านั้น ซึ่งเป็นระดับสิทธิ์สูงสุดในระบบปฏิบัติการ

  • การควบคุมทรัพยากรฮาร์ดแวร์ Hypervisor ต้องการควบคุมทรัพยากรฮาร์ดแวร์ทั้งหมด เช่น CPU, หน่วยความจำ, และอุปกรณ์ I/O การทำงานในระดับ Kernel Mode ช่วยให้ Hypervisor สามารถเข้าถึงทรัพยากรเหล่านี้ได้โดยตรงและมีประสิทธิภาพสูง

  • การแทรกแซงและจัดการการทำงานของ Guest OS Hypervisor มีหน้าที่แทรกแซงการทำงานของ Guest OS (ระบบปฏิบัติการที่ทำงานบน VM) รวมถึงการสลับ Context ระหว่าง VMs ต่าง ๆ เพื่อให้การทำงานราบรื่น

Hypervisor Initialization

หลังจากที่ Hypervisor ทำการ Initialize เสร็จสิ้น หรือหลังจากที่ทำการติดตั้ง Hypervisor Driver แล้ว

Hypervisor จะทำการ deprivilege ตัวเองจากการทำงานใน Ring 0 ของ OS ที่รันอยู่ และจะลดระดับสิทธิ์ลงไปยัง Ring -1 ซึ่งเป็นระดับ privileged ที่ถูกเพิ่มเข้ามาใน CPU รุ่นใหม่ โดยเฉพาะในเทคโนโลยี Virtualization เช่น Intel VT-x หรือ AMD-V

การทำงานใน Ring -1

  • Ring -1 เป็นระดับสิทธิ์พิเศษที่ใช้สำหรับการทำงานของ Hypervisor เพื่อควบคุมและจัดการ Guest OS ที่ทำงานภายใต้ Hypervisor โดยไม่ให้เกิดการแทรกแซงจาก Operating System ที่รันอยู่ใน Ring 0
  • การที่ Hypervisor ย้ายตัวเองไปยัง Ring -1 ช่วยให้สามารถทำการควบคุม VM และทรัพยากรต่าง ๆ ได้โดยไม่ถูกจำกัดหรือขัดขวางจาก OS หลัก ซึ่งทำให้สามารถดำเนินการต่าง ๆ ได้อย่างมีประสิทธิภาพ

ใน Ring -1 ตัว Hypervisor สามารถ redefine หรือ แก้ไขคำสั่ง (instructions) ของ CPU ได้ผ่าน Driver ที่เราสร้างขึ้นเอง โดยมีความสามารถในการควบคุมการทำงานของ CPU อย่างละเอียดในระดับที่สูงขึ้น

การแบ่งแยกระหว่าง Host และ Guest OS

  • Host OS คือระบบที่ทำงานในระดับสูงสุดหรือ Hypervisor ซึ่งจะทำหน้าที่ในการควบคุมและจัดการ Guest OS ที่ทำงานอยู่ภายใต้การดูแล
  • Guest OS คือระบบปฏิบัติการที่ทำงานภายใน Virtual Machine ซึ่งได้รับการจัดสรรทรัพยากรและการควบคุมจาก Host แต่มีการจำกัดสิทธิ์ในการเข้าถึงฮาร์ดแวร์และระบบภายใน Host OS

การ Virtualize CPU

หลังจากที่ทำการ launch ตัว Hypervisor, Operating System ปัจจุบันที่เรากำลังใช้งานอยู่ เช่น Windows, จะกลายเป็น Guest OS และตัว Hypervisor จะกลายเป็น Host

ตามทฤษฎีแล้ว, Guest OS จะไม่สามารถเข้าถึง physical processor หรือ CPU ได้โดยตรงอีกต่อไป เนื่องจาก Hypervisor ถูก deprivileged ไปยัง Ring -1 ซึ่งเป็นระดับสิทธิ์พิเศษที่ต่ำกว่า Ring 0 ของ OS

การที่ Hypervisor ถูก deprivileged และทำงานใน Ring -1 ช่วยให้มันสามารถควบคุมและ virtualize การทำงานทั้งหมดของ CPU ซึ่งหมายความว่า Hypervisor จะจัดการการทำงานของ Guest OS โดยไม่ให้ Guest OS เข้าถึง hardware resources หรือ CPU โดยตรงอีกต่อไป

การจัดการและดัดแปลงค่า Register

นอกจากการควบคุมคำสั่งของ CPU แล้ว Hypervisor ยังสามารถ ดัดแปลงค่า register ของ CPU ได้อีกด้วย ซึ่งใน VMM (Virtual Machine Monitor) การควบคุมและการปรับค่าเหล่านี้ช่วยให้ Hypervisor สามารถจัดการการทำงานของ Virtual Machines มีประสิทธิภาพ โดยไม่ให้ Guest OS หรือโปรแกรมอื่น ๆ ที่ทำงานอยู่ภายใน VM รู้ถึงการปรับเปลี่ยนที่เกิดขึ้น อาจรวมไปถึงการหลบเลี่ยง security features ต่างๆของ Guest OS ด้วยเช่นกัน

การเลือก Virtualization ที่จำเป็น

แต่ในทางปฏิบัติแล้ว, เราสามารถ virtualize บางสิ่งที่เราสนใจได้ โดยไม่จำเป็นต้อง virtualize ทุกอย่างทั้งหมด เช่น, เราอาจสนใจแค่บาง event หรือบางส่วนของการทำงานของ CPU เท่านั้น

การเลือก virtualize เฉพาะบางสิ่งที่ต้องการช่วยให้เราสามารถปรับแต่งการทำงานของ Hypervisor ได้อย่างมีประสิทธิภาพ โดยไม่ต้องจำลองหรือจัดการทุกอย่าง ซึ่งสามารถช่วยลดความซับซ้อนและเพิ่มประสิทธิภาพในการจัดการกับทรัพยากร

Blue Pill Hypervisor

และด้วยความสามารถเหล่านี้ของ Hypervisor ซึ่งมีความสำคัญอย่างมากในมุมมองเกี่ยวกับ OS Security, ในแง่ของการโจมตี จะมีสิ่งที่เรียกว่า Blue Pill Hypervisor ที่ถูกออกแบบมาเพื่อโจมตีและหลบหลีกการตรวจจับจาก OS

Blue Pill Hypervisor

Blue Pill Hypervisor เป็นเทคนิคการโจมตีที่ใช้ Hypervisor ในการควบคุม CPU และแทรกแซงการทำงานของ Operating System ในระดับที่ลึกที่สุด โดยทำให้ OS หรือโปรแกรมที่ทำงานภายใน Guest OS ไม่สามารถรู้ถึงการเปลี่ยนแปลงที่เกิดขึ้นภายในระบบได้ เทคนิคนี้สามารถหลบหลีกการตรวจจับจากเครื่องมือรักษาความปลอดภัยต่าง ๆ และทำให้แฮกเกอร์สามารถควบคุมเครื่องได้โดยไม่ถูกตรวจพบ

การทำงานของ Blue Pill Hypervisor

Blue Pill จะถูกโหลดเข้าไปในระดับ Ring -1 ซึ่งเป็นระดับที่ต่ำกว่าระบบปฏิบัติการที่ทำงานใน Ring 0 ของ OS โดยทำให้ Hypervisor สามารถควบคุมและจัดการการทำงานของ Guest OS โดยที่ Guest OS ไม่สามารถรู้ถึงการเปลี่ยนแปลงที่เกิดขึ้นจาก Hypervisor

ที่มาของชื่อ Blue Pill มาจากภาพยนตร์เรื่อง The Matrix ซึ่งในเรื่องนี้มีการเลือกเส้นทางให้กับตัวละครหลัก Neo โดยใช้เม็ดยาสองเม็ด ได้แก่ Red Pill และ Blue Pill

  • Red Pill จะทำให้ Neo รู้ความจริงเกี่ยวกับโลกที่เขาอาศัยอยู่ ซึ่งเป็นโลกจำลองที่ถูกสร้างขึ้นโดยเครื่องจักร
  • Blue Pill จะทำให้เขายังคงอยู่ในโลกจำลองและไม่รู้ถึงความจริงที่ซ่อนอยู่

ในทางเทคนิค, Blue Pill Hypervisor ได้รับชื่อมาจากแนวคิดใน The Matrix ที่กล่าวถึงการจำลองหรือการซ่อนความจริง โดย Blue Pill Hypervisor จะทำการสร้างการจำลองของ Operating System โดยที่ Guest OS ไม่สามารถรับรู้ถึงการควบคุมหรือการเปลี่ยนแปลงที่เกิดขึ้นจาก Hypervisor ได้ สามารถอ่านเพิ่มเติมเกี่ยวกับ Blue Pill ได้ที่ Wikipedia - https://en.wikipedia.org/wiki/Blue_Pill_(software)

Hypervisor VMCS

Hypervisor จะมี data structure ตัวหนึ่งที่ชื่อว่า VMCS หรือ Virtual Machine Control Structure ซึ่งสามารถเปรียบเสมือนกระดูกสันหลังของ Hypervisor เนื่องจากมันเป็นส่วนสำคัญที่ช่วยในการควบคุมการทำงานของ Virtual Machine

การทำงานของ VMCS

  • VMCS ถูกใช้โดย Physical Processor หรือ CPU Core ซึ่งทำหน้าที่ในการเก็บข้อมูลที่จำเป็นสำหรับการสลับการทำงานระหว่าง Guest OS และ Host OS เช่น การเก็บ state ของ CPU ทั้งในฝั่ง Guest และ Host

  • VMCS จะเกาะอยู่กับแต่ละ core ใน CPU เพื่อให้ core ใช้ในการควบคุมการทำงานของตนเอง เมื่อมีการสลับการทำงานระหว่าง Host และ Guest OS, VMCS จะช่วยเก็บ state ที่เกี่ยวข้องกับการทำงานของ CPU รวมถึงการจัดการ registers และ flags ที่จำเป็นสำหรับการสลับคอนเท็กซ์

การเข้าถึง VMCS

VMCS (Virtual Machine Control Structure) ไม่สามารถเข้าถึงได้โดยตรงผ่านการ memory access ตามปกติ แต่จะต้องใช้คำสั่ง VMX เช่น vmx_read และ vmx_write เพื่อจัดการกับข้อมูลภายใน VMCS นั่นหมายความว่า การทำงานกับ VMCS ต้องทำผ่านคำสั่งพิเศษที่ CPU รองรับในการจัดการกับ VMX mode เท่านั้น

โครงสร้างของ VMCS

VMCS เป็น data structure ที่มีขนาดใหญ่และประกอบด้วยหลายฟิลด์ที่สำคัญ โดยแบ่งออกเป็นส่วนต่างๆ ดังนี้:

  1. Guest State Field ส่วนนี้จะเก็บข้อมูลที่เกี่ยวข้องกับสถานะของ Guest OS ซึ่งรวมถึงข้อมูลสำคัญเช่น:
  • Guest RIP (Instruction Pointer ของ Guest)
  • Guest RSP (Stack Pointer ของ Guest)
  • และฟิลด์อื่นๆ ที่เกี่ยวข้องกับการทำงานของ Guest OS
  1. Host State Field ส่วนนี้จะเก็บข้อมูลที่เกี่ยวข้องกับสถานะของ Host OS ซึ่งรวมถึง:
  • Host RIP (Instruction Pointer ของ Host)
  • Host RSP (Stack Pointer ของ Host)
  • และข้อมูลอื่นๆ ที่เกี่ยวข้องกับการทำงานของ Host OS
  1. Control Field ฟิลด์นี้เกี่ยวข้องกับการควบคุมการทำงานของ VMExit ซึ่งคือการส่งการควบคุมจาก Guest OS ไปยัง Hypervisor (Host)

  2. VMX Information Field ฟิลด์นี้จะเก็บข้อมูลที่เกี่ยวข้องกับ VMX เช่น การตั้งค่าต่างๆ ที่เกี่ยวข้องกับการ virtualize รวมถึงข้อมูลที่ใช้ในการตรวจสอบและควบคุมการทำงานของ VMCS

VMExit และ VMEntry

เมื่อ Hypervisor พบ event ที่มันกำลังสังเกตอยู่, จะเข้าสู่กระบวนการที่เรียกว่า VMExit ซึ่งเป็นกระบวนการที่ Guest OS กำลังจะเข้าสู่ Host Area โดย control flow จะถูก transfer จาก Guest OS ไปยัง Host OS

การทำงานของ VMExit

ยกตัวอย่างเช่น, Host กำลัง monitor การเกิด Interrupt 3, ซึ่งเป็น breakpoint ในฝั่ง Guest เมื่อ Guest OS รันคำสั่ง int 3 (breakpoint), แทนที่คำสั่งนี้จะถูกส่งไปยัง CPU เพื่อทำการประมวลผล, มันจะถูกส่งไปยัง VMM (Virtual Machine Monitor) หรือ Hypervisor

จากนั้น, Hypervisor สามารถดักจับการทำงานนี้และทำการแก้ไข event ดังกล่าวได้ เช่น, การเลือก skip การทำงานของ breakpoint หรือการแก้ไขพฤติกรรมของ breakpoint เพื่อให้เหมาะสมกับการควบคุมที่ต้องการ

VMExit และ VMCS

กระบวนการ VMExit จะทำการ initialize ตัว VMCS (Virtual Machine Control Structure) ซึ่งเป็นโครงสร้างข้อมูลที่ช่วยในการจัดการการสลับการทำงานระหว่าง Guest OS และ Host OS ในระหว่างที่ Hypervisor ดักจับและจัดการ event ที่มันสนใจ

การกลับไปยัง Guest OS (VMEntry)

หลังจากที่ Hypervisor ได้จัดการกับ event ที่มันสนใจแล้ว, Hypervisor จะ transfer control flow กลับไปยัง Guest OS ซึ่งจะเป็นการดำเนินการคำสั่งถัดไปในโค้ดของ Guest OS

กระบวนการที่ Hypervisor จะ transfer control flow กลับไปยัง Guest OS เรียกว่า VMEntry ซึ่งจะทำให้การทำงานของ Guest OS กลับมาดำเนินต่อไปตามปกติ

VMX Instructions เบื้องต้น

ในหัวข้อนี้จะหยิบคำสั่ง VMX มาอธิบายคร่าวๆดังนี้

VMXON / VMXOFF VMPTRLD / VMPTRST / VMCLEAR VMREAD / VMWRITE VMLAUNCH / VMRESUME / INVEPT

VMX Instructions เป็นคำสั่งพิเศษที่ CPU รองรับสำหรับการทำงานในโหมด Virtualization ซึ่งช่วยให้ Hypervisor สามารถควบคุมและจัดการการทำงานของ Guest OS ภายใน Virtual Machine ได้ โดยคำสั่งเหล่านี้จะทำงานในระดับ Ring -1 ที่เป็นสิทธิ์พิเศษสำหรับการควบคุม Virtualization

คำสั่ง VMXON

คำสั่ง VMXON ใช้ในการเปิดการทำงานของ Processor จาก Protected Mode ไปยัง Protected VMX Mode ซึ่งเป็นโหมดที่เปิดใช้งาน Virtualization บน CPU โดยตรง

การทำงานของ VMXON

เมื่อเรียกใช้คำสั่ง VMXON, CPU Core จะทำการเตรียมสิ่งที่จำเป็นในการทำงานในโหมด Virtualization เช่น การเตรียม EPT (Extended Page Tables) และคำสั่ง VMX Instructions ที่เกี่ยวข้อง ซึ่งการทำงานนี้จะเป็นการเตรียมพร้อมให้ CPU สามารถสลับการทำงานระหว่าง Guest OS และ Host OS ได้

ในส่วนของการทำงานจริงๆ ของ CPU Core, เราจะไม่สามารถรู้ได้ทั้งหมดว่ามันทำอะไรบ้างในระหว่างการเตรียมตัว เพราะเป็นการทำงานภายในของ CPU เองที่จัดการให้เรา เช่น VMXON จะเป็นเหมือนการแจ้งเตือน CPU ว่าตอนนี้เรากำลังจะเริ่มต้นการ virtualize CPU Core ซึ่ง CPU จะเตรียมสิ่งที่จำเป็นเพื่อรองรับการทำงานในโหมด VMX

การเตรียม Memory Address

ในกระบวนการเตรียมการ, CPU จะต้องขอ memory address ของ memory region ที่จะถูกใช้สำหรับการ VMXON ซึ่งจะเป็นส่วนที่ CPU ใช้ในการตั้งค่าต่างๆ เพื่อรองรับการทำงานในโหมด VMX

คำสั่งจริงๆ ที่ใช้ใน VMXON คือ __vmx_on ซึ่งเป็นคำสั่ง Assembly ที่ทาง Microsoft เตรียมเอาไว้ให้ และเป็นคำสั่งที่ใช้ในระดับ CPU สำหรับการเปิดใช้งาน Virtualization

คำสั่ง #VMPTRLD, #VMPTRST, และ #VMCLEAR

หลังจากที่เราเรียกคำสั่ง VMXON เพื่อเปิดใช้งาน VMX Mode, คำสั่งถัดไปที่สำคัญในการทำงานกับ VMCS (Virtual Machine Control Structure) ได้แก่ VMPTRLD, VMPTRST, และ VMCLEAR ซึ่งเป็นคำสั่งที่ช่วยในการจัดการ VMCS ในระดับ CPU

VMPTRLD

คำสั่ง VMPTRLD ใช้เพื่อ load VMCS structure เข้าไปยัง processor ซึ่ง VMPTRLD จะต้องการ physical address ของ VMCS structure เพื่อให้ CPU ใช้งานได้ โดย VMCS นี้สามารถถูกเก็บใน heap ของ VMM หรือ Virtual Machine Monitor ได้

เมื่อ VMPTRLD ถูกเรียก, CPU จะทำการโหลด VMCS ที่เกี่ยวข้องกับ Guest OS และ Host OS เพื่อเตรียมพร้อมสำหรับการสลับการทำงานระหว่างกัน

VMPTRST

คำสั่ง VMPTRST ใช้เพื่อ store VMCS structure ที่ VMM กำลังใช้งาน โดยส่ง physical address ของ VMCS กลับไปยังที่ที่มันถูกเก็บไว้ ซึ่งคำสั่งนี้จะช่วยให้สามารถบันทึกสถานะของ VMCS ขณะนั้นได้เพื่อการใช้งานในภายหลัง

VMCLEAR

คำสั่ง VMCLEAR มีหน้าที่ในการ clear flag ต่างๆ ของ VMCS ก่อนที่จะนำไปใช้งาน ซึ่งเป็นขั้นตอนสำคัญในการเตรียม VMCS สำหรับการ load ใหม่ด้วยคำสั่ง VMPTRLD หาก VMCS ไม่ถูก clear ก่อนใช้งาน จะไม่สามารถใช้คำสั่ง VMPTRLD เพื่อโหลด VMCS ให้ processor ได้

คำสั่ง #VMREAD และ #VMWRITE

คำสั่ง VMREAD และ VMWRITE เป็นคำสั่งที่ใช้สำหรับการ อ่าน และ เขียน ค่าใน VMCS structure ซึ่งเป็นส่วนสำคัญในการควบคุมการทำงานของ Virtual Machine ผ่าน Hypervisor

VMWRITE

คำสั่ง VMWRITE ใช้สำหรับการ เขียนค่า ไปยัง VMCS ที่กำหนด เมื่อเราใช้คำสั่ง VMWRITE, CPU จะทำการเขียนค่าที่เรากำหนดลงใน VMCS structure ตามตำแหน่งที่เราระบุไว้ โดยที่ VMCS นี้จะเก็บข้อมูลที่ใช้ในการควบคุมการทำงานของ Guest OS และ Host OS

VMREAD

คำสั่ง VMREAD ใช้สำหรับการ อ่านค่า จาก VMCS โดยที่ CPU จะทำการอ่านข้อมูลจาก VMCS ที่กำหนดและส่งค่ากลับมาให้ Hypervisor โดยที่เราจะไม่ต้องไปอ่านข้อมูลจาก memory ด้วยตัวเอง

การทำงานของ CPU

ทั้งคำสั่ง VMWRITE และ VMREAD เป็นคำสั่งที่ CPU จะทำการจัดการให้เอง ดังนั้นเราไม่ต้องกังวลเรื่องการจัดการ memory หรือ addressing โดยตรง เพราะ CPU จะเป็นผู้ดำเนินการเหล่านี้ภายในระดับ hardware ให้เรา

คำสั่ง #VMLAUNCH และ #VMRESUME

คำสั่ง VMLAUNCH และ VMRESUME เป็นคำสั่งที่ทำงานในลักษณะเดียวกันโดยมีหน้าที่ในการดำเนินการในขั้นตอน VMEntry, ซึ่งหมายถึงการส่ง control flow กลับไปยัง Guest OS หลังจากที่ Hypervisor ได้เริ่มการทำงาน

VMLAUNCH

คำสั่ง VMLAUNCH ใช้เพื่อเริ่มต้นการ run guest โดยจะส่ง control flow กลับไปยัง Guest OS หลังจากที่คำสั่ง VMLAUNCH ถูกเรียก Hypervisor จะหยุดการทำงานของตัวเองและส่งการควบคุมไปยัง Guest OS ผ่าน Guest RIP (Guest Instruction Pointer)

หากไม่มีข้อผิดพลาดเกิดขึ้น, หลังจากที่ VMLAUNCH ถูกเรียก Hypervisor จะไม่ทำงานต่อจนกว่าจะมีการคืนค่าควบคุมกลับจาก Guest OS

VMRESUME

คำสั่ง VMRESUME ใช้เพื่อ resume การทำงานของ Guest OS หลังจากที่มีการทำงานเสร็จในขั้นตอน VMExit ซึ่งหมายถึงการที่ Hypervisor ได้รับการควบคุมชั่วคราวแล้วส่ง control flow กลับไปยัง Guest OS

การกลับมาควบคุมใหม่หลังจาก VMExit

หลังจากที่ Hypervisor ได้ส่งการควบคุมกลับไปยัง Guest OS, Hypervisor ก็สามารถกลับมาควบคุม Guest OS ได้อีกครั้งในกรณีที่เกิดเหตุการณ์ที่ต้องการให้ Hypervisor เข้ามาจัดการ เช่น เมื่อ Guest OS รันคำสั่งที่ Hypervisor ต้องการจะจับหรือควบคุม การทำงานจะกลับเข้าสู่ลูปเดิมของ VMExit และ VMEntry

EPT (Extended Page Table) และ INVEPT

EPT (Extended Page Table) เป็น paging structure ที่เป็นฟีเจอร์เพิ่มเติมใน Intel CPUs ซึ่งช่วยให้การทำ paging สามารถทำได้ใน 4 ระดับเหมือนกับการ paging ปกติใน CPU Protected Mode โดยมีการแยกการแปลงที่อยู่ในระดับต่างๆ ชัดเจนยิ่งขึ้น

ใน EPT, ที่อยู่แบบ EPT-based จะถูกเก็บไว้ใน VMCS (Virtual Machine Control Structure) ซึ่งเป็นข้อมูลสำคัญที่ใช้ในการควบคุมการทำงานของ Hypervisor

การแปลงที่อยู่ในหน่วยความจำ (Memory Address Translation)

ก่อนที่มี EPT (ในโหมดปกติ)

การแปลงที่อยู่แบบเดิมในระบบมีลำดับดังนี้:

  • Virtual Address → CR3 (Page Table) → Physical Address

เมื่อเปิดใช้งาน EPT

ในกรณีที่มีการเปิดใช้งาน EPT, เนื่องจากมี Guest และ Host ที่ทำงานแยกจากกัน เราจึงต้องแยกที่อยู่ของแต่ละส่วนให้ชัดเจน โดยมีขั้นตอนการแปลงที่อยู่ดังนี้:

  • Virtual Address → CR3 (Page Table) → Guest Physical Address → EPT → Physical Address จากกระบวนการนี้, Guest จะคิดว่าได้รับ Physical Address จริงๆ แล้ว แต่ในความเป็นจริงจะมีการแปลงอีกชั้นหนึ่งผ่าน EPT โดยที่อยู่ที่ Guest ใช้จะไม่ตรงกับที่อยู่จริงๆ ที่ระบบใช้งาน

การเปิดใช้งาน EPT ใน Hypervisor

เมื่อ Hypervisor เปิดใช้งาน EPT, CPU จะทำการแปลงที่อยู่เพิ่มเติมจาก page table ของ Guest OS โดยใช้ EPT ที่เราสร้างขึ้นมาใหม่

ผลลัพธ์คือ, Physical Address ของ Guest จะไม่เหมือนกับ Physical Address จริงๆ ของระบบ ซึ่ง Hypervisor สามารถควบคุมและจัดการได้ตามต้องการ

INVEPT

คำสั่ง INVEPT ใช้สำหรับการล้าง EPT cache ของ CPU และทำการโหลดข้อมูลใหม่จาก EPT ที่กำหนดไว้ เพื่อให้การแปลงที่อยู่จาก EPT เป็นข้อมูลที่ทันสมัยและแม่นยำ

Demo: แก้ไขผลลัพธ์ของคำสั่ง CPUID (Spoofing __cpuid results)

คำสั่ง __cpuid เป็นคำสั่งของ x86/x86-64 ที่ใช้ในการดึงข้อมูลจาก CPUID instruction โดยตรงจาก CPU ซึ่งจะทำการเรียกข้อมูลเกี่ยวกับคุณสมบัติของ CPU เช่น รุ่น, ความสามารถของ CPU, สัญญาณ, และข้อมูลอื่นๆ ที่เกี่ยวข้องกับ CPU ของระบบนั้นๆ

การทำงานของคำสั่ง __cpuid ในระดับ OS ปกติ จะไม่ผ่าน syscall หรือการเรียกฟังก์ชันในระบบปฏิบัติการ เพราะมันทำงานใน user mode หรือ privileged mode ของ CPU โดยตรง โดยที่โปรแกรมใน user space สามารถเข้าถึงคำสั่ง cpuid ได้จาก CPU โดยไม่ต้องการการอนุญาตจาก kernel หรือ syscall

การทำงานของคำสั่ง __cpuid

cpuid เป็นคำสั่งที่ทำงานใน Ring 0 หรือ Ring 3 โดยที่ไม่ต้องทำการร้องขอจาก syscall หรือจากการอนุญาตของ kernel เมื่อเรียก cpuid CPU จะตอบกลับข้อมูลที่เกี่ยวกับคุณสมบัติของ CPU เช่น เวอร์ชัน, คุณสมบัติการรองรับต่างๆ, การสนับสนุนคำสั่งเฉพาะ, และอื่นๆ คำสั่ง cpuid ทำงานโดยตรงบน CPU และไม่มีการพึ่งพา OS จึงทำให้ข้อมูลที่ได้มาจากคำสั่งนี้เป็นข้อมูลที่ตรงจาก hardware โดยไม่มีการผ่านการปรับแต่งจาก OS หรือโปรแกรมภายนอก

ในกรณีของ Hypervisor

เมื่อทำงานใน Hypervisor mode, คำสั่ง cpuid จะยังคงให้ข้อมูลที่เป็น physical processor แบบเดิม โดย Hypervisor สามารถทำการ spoofing หรือดัดแปลงผลลัพธ์ของคำสั่ง cpuid ได้ เช่น การทำให้ OS หรือโปรแกรมภายใน Guest OS คิดว่ามีคุณสมบัติของ CPU ที่ไม่ตรงกับ physical hardware ที่จริง

สิ่งนี้ทำให้ Hypervisor สามารถควบคุมผลลัพธ์ที่ Guest OS หรือโปรแกรมใน Guest มองเห็นได้ ซึ่งมีประโยชน์ในการทดสอบหรือการปกปิดคุณสมบัติของ CPU ในบางกรณี เช่น การทำให้ Guest OS มองไม่เห็นว่า virtualization ถูกเปิดใช้งานอยู่ หรือทำให้มันเห็นว่า CPU รองรับคำสั่งหรือคุณสมบัติบางประการที่ไม่ได้รับการรองรับจริงๆ

Video Demo:

Source code:

https://github.com/un4ckn0wl3z/SimpleHypervisor

End

ขอจบบทความไว้ประมาณนี้ก่อนนะครับ ยังมีอีกหลายอย่างที่ยังไม่ได้กล่าวถึงเช่น การทำ Hypercall หรือ การทำ EPT Hook เพื่อหลบเลี่ยงการตรวจจับต่างๆ ถ้าเกิดมีเวลาว่าง อาจจะมีมีบทความอื่นๆ ตามออกมานะครับ

Happy Hacking :)

References

https://rayanfam.com/tutorials/ https://en.wikipedia.org/wiki/Blue_Pill_(software) https://nordvpn.com/cybersecurity/glossary/blue-pill-attack/ https://tandasat.github.io/Hypervisor_Development_for_Security_Researchers.html https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html https://memn0ps.github.io/hypervisor-development-in-rust-part-1/ https://nixhacker.com/developing-hypervisior-from-scratch-part-1/ https://edu.51cto.com/lecturer/13733346.html http://www.woaidaima.com/thread-95446-1-1.html https://solutionshub.epam.com/blog/post/hypervisor-in-cloud-computing https://medium.com/swlh/negative-rings-in-intel-architecture-the-security-threats-youve-probably-never-heard-of-d725a4b6f831 https://www.intel.com/content/www/us/en/developer/articles/technical/increase-performance-of-vm-workloads-with-thp.html https://applied-programming.github.io/Operating-Systems-Notes/9-Virtualization/ https://www.bbc.com/news/entertainment-arts-57572152

Related Posts

There are no related posts yet. 😢