เพื่อตัวเอง 01: Windows User Mode vs Kernel Mode
สวัสดีครับ
ปลายทางของซีรีย์ blog นี้คืออะไร ก็ติดตามกันเอา แล้วแต่ , อยากเขียนไว้ก่อนจะย้ายไปทำเว็บไซต์ตัวเองด้วยเหตุผลหลายๆอย่าง ส่วนใครไม่ถนัด หรือไม่ชอบแนวนี้ผมขออภัยด้วย เพราะอย่างที่บอก ซีรีย์นี้ผมจะเขียนเพื่อตัวเอง
กลับมา Windows กันเถอะ
Windows Kernel Mode กับ User Mode ไล่เรียงกัน
Computer Hardware ทำหน้าที่หลายอย่าง
CPU คิดเลข , Memory จำไว้ชั่วคราว ไฟดับก็หายไป , VGA ส่งออกจอภาพ , Network Card , ส่งข้อมูลไปให้เครื่องอื่นผ่าน Media , Hard disk เก็บข้อมูลถาวร ไฟดับข้อมูลก็ยังอยู่ , Sound แปลง digital เป็น analog เพื่อส่งเสียงออกลำโพง ฯ
มีโปรแกรมมากมาย สร้างขึ้นมาเพื่อให้ทำงานกับคอมพิวเตอร์ ในระดับที่ต่างกัน ทั้ง user mode และ kernel mode และเข้าถึงทรัพยากรได้แตกต่างกัน แค่ชื่อคงพอเดาออก
แบบไวๆ
user mode = เข้าถึง hardware ได้จำกัด , ปลอดภัยกว่า
kernel mode = ใช้ทรัพยากรคอมพิวเตอร์ hardware ได้เต็มที่ , อันตรายกว่า
ก็แปลว่า mode ในการรัน app มีการใช้ทรัพยากรที่ต่างกัน โดยมี kernel จัดการให้
สำหรับซีรีย์ใน blog นี้เราจะสนใจเกี่ยวกับเรื่อง security เป็นหลัก , การทำงานปกติของ process ใน kernel / memory และการกระโดดข้าม หรือหลบเลี่ยง (evasion) เพื่อใช้ประโยชน์ (exploit) ทรัพยากรได้สูงสุด จากจุดประสงค์อะไร ก็แล้วแต่
execution file / program / process / thread
execution file = binary file ที่วางไว้เฉยๆ ในสถานที่หนึ่งของ OS พร้อมที่จะถูกสั่งประมวลผล (execute)เช่น notepad.exe ถูกวางไว้ที่ C:\Program Files\WindowsApps\Microsoft.WindowsNotepad_11.2409.9.0_x64__8wekyb3d8bbwe\Notepad\
program = “คำสั่งที่อยู่ภายใน execution file” ที่จะให้ทำอะไรต่อมิอะไร เช่น ใน notepad.exe พอเรารันขึ้นมาเพื่ออ่านข้อความไฟล์ ข้างในนี้ก็มีฟังก์ชั่นที่สามารถที่จะ ค้นหา string ในไฟล์ text ได้ เพราะใน .exe มีการเขียน program นี้อยู่ในไฟล์นี้เอาไว้
process = หลังจากทำการรัน / ดับเบิ้ลคลิก / หรือ execute ตัว executable file ขึ้นมา ก็จะมีชุดคำสั่งเพื่อไปขอจอง memory จอง windows ที่แสดงขึ้นหน้าจอ , อะไรก็ตามที่เกี่ยวข้อง (resource ต่างๆ) เช่น เราอาจจะเปิด notepad หลายๆ windows มันก็จะอยู่คนละ memory space กัน
thread = เป็นฟังก์ชั่นย่อยๆ ลงไปใน process อีกที ใช้สำหรับทำงานเล็กๆ ภายใต้ process นั้นๆ เช่น notepad.exe เปิดขึ้นมา แต่อาจจะมี thread ที่ทำอะไรสักอย่างให้
ตัวอย่าง thread ของ notepad.exe เปิดโดยใช้ process explorer จะเห็น 24960 เป็น MsSpellChecking ก็เดาได้ว่าเป็น Thread ที่ไว้สำหรับตรวจสอบคำผิด ที่ถูกเขียนไว้ช่วยผู้ใช้งานให้เขียนให้ถูกต้อง งานของมันเมื่อเจอผิดมันก็จะเป็นเส้นหยักๆ สีแดง ใต้คำๆนั้น แบบนี้เป็นต้น
Memory Layout ระหว่าง user mode กับ kernel mode
เอา user mode ก่อน
Windows จริงๆ แล้วอย่างที่บอก user mode ไม่ได้เข้าถึง hardware โดยตรง , การขอทรัพยากร (resources) เช่น memory นั้น ตัว Windows OS จึงเลือกใช้วิธีจัดการจองให้ผ่าน virtual address แทนหรือตำแหน่งแรมเสมือน , ไม่ได้ถูกจองเข้าไปใน physical memory จริง ๆ หน้าที่ในการจัดการ Memory เป็นของ OS , ซึ่ง Windows ก็เรียกสิ่งนี้่ว่า Paging System ,หรือ pages จะเรียกงี้ก็ได้ , หรือบางคนอาจจะเคยเจอ pagefile.sys นั่นแหละ มันก็ทำหน้าที่นั้นอยู่ (ก็เพราะ user mode ไม่ควรเข้าถึง hardware ได้โดยตรงไง , เหตุผลก็ตามตารางไง) โดย 1 pages จะมีขนาด 4096 bytes โดย default (4 KB) ซึ่งขนาด pages นั้นจะมากน้อยขึ้นอยู่กับ OS Setting ครับ คนที่เข้าใจก็จะไปปรับแต่งตรงนี้เพื่อให้ได้ประสิทธิภาพสูงสุด แต่ Microsoft ก็ปรับ optimized มาให้แล้วเป็นค่าเริ่มต้น ตามรุ่นของ OS ที่ออกมาขาย
โปรแกรม RamMap ของ sysinternals suit ก็ช่วยให้เรามองเห็นภาพรวม memory space ได้พอสมควร จะเห็นว่ามีสัดส่วนภาพ tab ของ pages ให้เราได้ดูด้วย
ทำให้เราเห็นว่าแต่ละ virtual address space ถูกจองโดย process อะไร นั่นเองครับ
อีกโปรแกรมชื่อว่า ProcessHacker เราก็สามารถดูรายละเอียดของ pages / memory ในแต่ละ process ได้ละเอียดเช่นเดียวกัน และยังบอกขนาดได้ด้วย
ย้อนกลับไปนิดนึงครับ อย่างที่บอก หลังจากที่ ดับเบิ้ลคลิก หรือรัน .exe file แล้วจะเกิดการจองทรัพยากรเกิดขึ้น (เน้น ว่า user mode) ตัวโปรแกรมก็จะไปเรียก API ของ OS ให้มาช่วยจองให้หน่อย (เราไม่ต้องเขียนคำสั่งเองทั้งหมด , OS มี API เตรียมไว้ให้นักพัฒนาได้เขียน call ไปเรียกใช้ได้ง่ายๆ) , เพื่อโปรแกรมจะได้ใช้งานได้ เพราะเวลารันขึ้นมามันจะไปฝาก process ไว้ตรงไหนละ ก็ต้องแปลงร่างให้เป็น process ยืนหล่อๆ อยู่บน Memory ไง , ตัวอย่าง API ที่ไปเรียกให้ OS kernel ช่วยจองให้ ก็จะมีเบื้องต้นตามนี้และเน้นนะ ว่าแบบ virtual address space บน user mode
VirtualAlloc() — จอง memory ที่ process จะใช้
VirtualFree() — คืน memory ที่จองไปจาก VirtualAlloc เช่น อาจจะประมวลผลคำสั่งนั้นๆ เสร็จแล้ว ก็คืนไป
HeapAlloc() — ส่วนของ dynamic memory ที่จะถูกใช้บ่อยๆ (คนละสไตล์กับ stack) ซึ่งมีข้อดีหลายอย่าง , user mode ก็สามารถเรียก api นี้เพื่อเพิ่มประสิทธิภาพของโปรแกรมได้
MapViewOfFile() / UnmapViewOfFile()- ใช้สำหรับทำให้ไฟล์อยู่ใน virtual address space สามารถเข้าถึงได้เร็วกว่า ต่างจากเข้าผ่าน disk , Unmap ก็เอาออกเพื่อคืน memory
user mode จะมี segment มีการแบ่งสรรปันส่วน memory pages และ api ที่ยกมาก็นิดเดียว จริงๆมีอีกหลายอัน
.
.
ส่วน memory layout ของ kernel mode นั้น……….
แบบง่ายสุด = เข้าถึงได้ทุก address ของ memory จบ !
เราจะเห็นว่า
ถ้าโปรแกรมปกติ . โปรแกรมที่ถูกสร้างขึ้นมาเพื่อจุดประสงค์ ที่ดี ก็สามารถเขียนขึ้นมาใช้งานในระดับ user mode ได้ (เช่น Discord , notepad++) หรือแม้แต่โปรแกรมใหญ่ๆ อย่าง Microsoft Office
กลับกัน ถ้าเป็นการเขียนโปรแกรมขึ้นมาเพื่อจุดประสงค์ที่ไม่ดี เช่น การเข้ามาเพื่อ ล็อคไฟล์งานของเราเพื่อเรียกค่าไถ่ (Ransomware) การเข้ามาใช้ทรัพยากรเครื่องเพื่อขุดเหรียญคริปโตโดยที่เราไม่ได้อนุญาต แล้วก็ส่งเงินเข้ากระเป๋าคริปโตตัวเอง (Crypto Malware) หรือเข้ามาสอดส่องพฤติกรรมของเราอย่างเงียบๆ ว่าเรากำลังทำอะไรบ้าง เข้าเว็บอะไรบ้าง เข้าไปถึงไฟล์ไหนบ้าง ซึ่งอาจจะมาจากการสอดส่องทั่วไป หรือมาจากเครื่องมือของรัฐบาลก็ได้ (Spyware) เป็นต้น หลากหลายจุดประสงค์นี้ถูกเรียกว่า Malicious Software คือโปรแกรมมุ่งร้าย และเราจะเรียกสั้นๆ ว่า Malware (มัลแวร์)
.
หลักใหญ่ใจความที่นักพัฒนา Malware ต้องทำมีแค่อย่างเดียวครับ คือทำยังไงก็ได้ ให้คนรัน executable file ที่อันตราย ที่เขาเขียนขึ้นมาให้สำเร็จให้ได้ โดยไม่สนวิธีการ จะโทรศัพท์หลอกคุย จะส่งอีเมลปลอม ฯลฯ สารพัดวิธี , ส่วน process อันตรายนั้น หากถูกรันสำเร็จแล้ว มันจะมีความสามารถ (capability) มากแค่ไหน หรือไต่ไปถึงไหน ไปทำอะไรได้นั้น ก็สุดแล้วแต่สิ่งที่เขียนขึ้นมาตามจุดประสงค์
ดังนั้น OS ระบบปฏิบัติการก็ต้องมีความปลอดภัยมากพอ ที่จะเอามา “ขายหาเงิน” ให้กับคน ไม่ใช่จะโดน malware บุกเข้ามาทำโน่นทำนี่ได้ง่ายๆ แบบนี้ก็ขายไม่ออก ทีมพัฒนา OS ก็ต้องเร่งทำนู่นนี่ป้องกันออกมา หนึ่งใน “เครื่องมือ” หลายๆ อย่าง ที่มีขายในท้องตลาดนั้น ที่ผมจะหยิบมาพูดใน blog ของซีรีย์นี้ คือเครื่องมือที่ชื่อว่า EDR ถ้าพูดให้สรุป แบบสั้นๆ เข้าใจง่ายที่สุด คือเครื่องมือที่จัดการตรวจจับ และป้องกัน Malware บางคนจะเรียก antivirus ก็ได้ (แต่ EDR มันทำได้มากกว่านั้น) / และเนื้อหาทั้งหมดจะเป็นเรื่อง EDR Evasion หรือการพยายามหลบการตรวจจับของ EDR ซึ่งเราก็ต้องเข้าใจ EDR ด้วยว่ามันทำงานยังไง โดย blog นี้จะเริ่มจาก ความแตกต่างของ user mode กับ kernel mode ก่อน
.
เมื่อมาถึงตรงนี้ก็จะพอมองออกแล้วว่า Malware Developer นั้น ต้องการที่จะรันไฟล์อันตรายของเขา บนเครื่องเหยื่อ ในระดับ kernel mode ให้ได้ เขาจะใช้เทคนิคหลายอย่าง เพื่อพยายามทำมัน ไม่ว่าจะเป็น หลอกให้รันในสิทธิ์สูง ตรงๆ หรือ รันในสิทธิ์ user mode ก่อนแล้วหาทางขยับเป็นสิทธิ์สูงทีหลัง (Privilege Escalation) หรือ ยิงโค้ดอันตรายผ่านเข้ามาใน network แล้วได้สิทธิ์สูง kernel mode เลย เพราะเขาอาจจะหาช่องโหว่ร้ายแรงมากเจอในเครื่องเหยื่อ และเขาก็พัฒนาโค้ดยิงนั้นได้ (Remote Code Execution) เป็นต้น
user mode นั้นไม่ดีต่อ malware developer อย่างไร ?
- EDR ทำงานใน Kernel mode , แทบจะทุกอย่างบน OS อยู่ในสายตาของ EDR
ถ้าจะรัน malware บน user mode ตัว process ของ malware จะถูกจอง Resorces ใน pages ของ memory ที่ถูกจัดไว้อย่างเป็นสัดส่วน และไปยุ่งกับ pages อื่นๆ ของ process อื่นๆ ไม่ได้เลย , ในขณะที่ EDR ที่ทำงานอยู่ตอนบูตเครื่องและได้เห็นทุกอย่างบน memory pages ถ้า process นั้นๆ เริ่มทำอะไรที่อันตราย , call api ที่ไม่ควรจะ call EDR ก็จะทำการ detect (ตรวจจับ) และ prevented (ป้องกัน) ทันที แถมยังรายงานไปยัง dashboard ของระบบภายในองค์กรเพื่อให้เครื่องอื่นๆ ได้เรียนรู้ไปอีก ดังนั้น malware developer จะไม่อยากรันไฟล์อันตรายบน user mode แต่ในหลาย กรณี ก็สามารถค้นหาเทคนิคเพื่อทำได้ เพื่อยกระดับสิทธิ์ ให้กระโดดเข้าไปใน kernel mode ทีหลัง , สุดท้าย ถ้าเป็น user mode ก็มีโอกาสสูงมากที่จะโดนตรวจจับได้ง่าย malware developer จึงเลือกที่จะหาทางไปให้ถึง kernel mode มากกว่า
2. ต้องการเข้าถึง Hardware แบบไม่ต้องแจ้งผู้ใช้
อย่างที่ผมเล่าไปบางที Malware Developer บางกลุ่ม (ส่วนมากเลย เช่น Ransomware / spyware) ต้องการให้ไฟล์อันตรายที่ตัวเองพัฒนา หลังจากรันแล้วก็ให้ส่งข้อมูลออกไปหาต้นทาง เช่น แอบมาส่องพฤติกรรม หรือกวาด user / password ในเครื่อง ฯ แต่ hacker นั่งอยู่ที่ต่างประเทศ เขาก็ต้องรับข้อมูลพวกนี้ทาง internet ผ่าน network , idea ของ malicious function นี้คือต้องส่งข้อมูลออกมาผ่าน network โดยไม่ให้ user รู้ ซึ่งวิธีที่จะทำได้คือการทำให้ malware process ติดต่อ hardware ได้โดยตรง , มีความเงียบ ไม่แสดงอะไรออกมาให้ user เห็น ซึ่งทำได้ใน kernel mode เท่านั้น ส่วนในระดับ user mode ถูกตรวจจับได้ง่ายมาก อย่าว่าแต่โปรแกรม EDR เลย พวกเราคนทั่วๆ ไปใช้โปรแกรมธรรมดา หรือ Task Manager ก็มองเห็นแล้ว
3. ต้องการฝังตัวไฟล์อันตรายให้รันทุกครั้งที่บูต
ในระดับ kernel mode โปรแกรมมากมายต้องติดต่อกับ hardware ให้ทำงานได้ เช่นพวก driver ต่าง ๆ มันก็จะถูกโหลดมาเลยตอนบูตเครื่อง , และมันก็ทำหน้าที่บริหารจัดการ hardware จริง ๆ มันก็สมควรได้รับการรันใน kernel mode , และ user ก็มักจะไม่ไปสนใจว่ามัน load driver อะไรมาบ้าง ดังนั้น malware developer จึงมีไอเดียที่จะติดตั้งตัวไฟล์อันตรายเข้าไปฝังตัว (Persistence) ให้มันบูตมากับเครื่อง ทุกๆครั้ง ไม่หายไปไหน ตัวอย่างนี้ก็แน่นอน เป็นอีกเหตุผลที่ต้องถูกใช้ใน kernel mode เหมือนกัน
4. ขอ kernel mode เพื่อต่อสู้กับระบบ ตรวจจับ และป้องกัน โดยเฉพาะ
ในยุคปัจจุบัน EDR / Antivirus ที่ดี จำเป็นที่จะต้องมีสิทธิ์สูงมาก เพื่อตรวจสอบและป้องกัน ทุกๆ ทรัพยากรของเครื่องได้ และทนทานต่อการงัดแงะ (Tampering) จาก process อื่นๆ ได้ (เพราะ EDR ก็ขายหาเงินจากคนเหมือนกัน) , Malware developer เขาก็รู้ ดังนั้นเขาก็ต้องเขียนโปรแกรมที่อันตราย ที่จะมาต่อสู้กับระบบ Detect & Prevented นี้โดยเฉพาะ แล้วค่อยไปทำพฤติกรรมอันตรายทีหลังก็ได้ เช่น การพยายามจะ uninstall antivirus , การ inject process ของตัว edr / antivirus เพื่อให้ไม่ตรวจจับอะไรบางอย่าง , การทำ exclusion เพื่อบอกให้ edr / antivirus รู้ว่า พื้นที่ตรงนี้ปล่อยผ่านได้ … แน่นอน จะต่อสู้กันมันก็ต้องชกกันในระดับเดียวกัน , kernel mode จึงเป็นเรื่องที่ malware developer อยากพัฒนา malware ของตัวเองให้ไปให้ถึง
ภาพ Tactic ที่ชื่อว่า Defense evasion คือการหลบหลีกการป้องกัน ซึ่งมี 43 เทคนิค (ภาพยาว cap มาไม่พอครับ) อยู่ใน MITRE ATT&CK framework ซึ่งในทั้งหมดของ Tactic ของ framework นี้ part ของ defense evasion มีปริมาณ เทคนิค มากที่สุด, ถือได้ว่ามากกว่า part อื่นๆ แบบเห็นได้ชัด
มีอะไรเพิ่มเติมใน user mode อีกบ้าง ?
System call หรือถ้าเรียกแบบเฉพาะเจาะจงบน Windows = System services Call อธิบายได้ว่า process ในระดับ user mode หากต้องการใช้ service / hardware ใดๆ เช่น โปรแกรมฟังเพลง สั่งให้เสียงออกลำโพง นี่ก็คือตัวอย่างการที่โปรแกรมต้องการเข้าถึง Hardware , แม้ในตอนแรกผมจะเล่าให้ทราบว่า process ใน user mode มันไม่สามารถติดต่อ Hardware โดยตรงได้ แต่จริงๆ แล้วมันทำได้แหละ ผ่านสิ่งที่เรียกว่า System service call (ต่อไปจะขอพิมพ์สั้นๆ ว่า syscall นะครับ)
ในภาพตัวอย่าง มันก็เป็น notepad.exe หนิ มันเข้าถึง hardware ยังไงล่ะ ? คำตอบคือ ไฟล์ใน Notepad ก็ต้องถูกเขียนลง disk ใช่มั้ยครับ , Disk ก็คือ hardware ดังนั้นเมื่อต้องการจะเขียนให้ไฟล์มันถูก store ไว้ใน disk ก็ต้องใช้ฟังก์ชั่นเรียกเข้ามาเพื่อบอก kernel ว่าขอเขียนไฟล์เข้า disk หน่อย จึงเป็นไปตามรูปนั่นเอง และ ในจังหวะในภาพนี้ (สำคัญมาก) มันคือการ “Switch” จาก user-mode มาเป็น kernel mode ชั่วคราว แว้บนึงเท่านั้น แล้ว พอฟังก์ชั่นมัน return ค่ากลับผ่าน API ไป ก็กลับมาสู่ user mode เหมือนเดิม , process notepad.exe ก็ไม่ได้กระโดดเข้ามาใน kernel mode ด้วย , กระบวนการคือ แค่ OS มีกลไกการปิดกั้น และเลือกเฉพาะสิ่งที่จำเป็นจริงๆ เท่านั้นมาให้ kernel mode จัดการให้ ไม่ได้เอามาทั้งหมด ในภาพจะเป็น flow ตามนี้
notepad.exe -> kernel32.dll -> kernelbase.dll -> ntdll.dll -> syscall และเขียนไฟล์ลง disk
และถ้า kernel จะจัดการ syscall จาก process ที่มากมายก่ายกองได้ยังไง ก็นอกจากจะมี SSN (System Service Number) แล้ว ก็ยังมี algorithm การจัดคิวประมวลผลของ CPU ด้วย , มาถึงตรงนี้ก็อาจจะเห็นอะไรแล้ว ใช่มั้ยว่า “จังหวะที่ขอเข้า kernel mode แป๊บนึง” ซึ่งก็คือ syscall นี่แหละ ก็มีโอกาสจะสร้างอะไร อันตรายๆ หรือขอสิทธิ์ สูงๆ ได้น่ะสิ , อืม มันก็ใช่ แต่คนเขียน OS เขาก็ต้องหาทางป้องกันไว้ด้วยเช่นกัน
เราจะเห็นได้ว่า API ที่ใช้ในระดับ kernel mode มักจะขึ้นต้นด้วย Nt เป็นส่วนใหญ่ อย่างในที่นี้ก็คือ NtCreateFile() ซึ่งตัวอักษร Nt ก็ย่อมาจากคำว่า Native นั่นเอง คือใช้ตรงๆ ไม่มีการแปลงอะไรเลย มันเลย Direct และเร็ว สุดๆ แต่ก็เสี่ยงสุดๆ เช่นเดียวกัน , malware จึงพยายามจะ call api พวกนี้ให้ได้ , เพราะตัวอย่างเราก็เห็นแล้ว ตอน call ด้วย NtCreateFile() เราไม่รู้ข้างหลัง Windows เลยว่ามันทำอะไร , แต่จริงๆ มันเขียนไฟล์ลง Disk ให้เราสำเร็จแล้ว เพราะ API นี้อยู่ใน kernel mode และมีสิทธิ์ถึง hardware แบบ Full นั่นแหละ
Hook
ถ้าแปลตามตัว คือการเกี่ยวเบ็ด หรือตกปลา , ในภาษา API computer ก็คล้าย ๆ กัน . ย้อนกลับไปนิดนึง ในตัวอย่างก่อนหน้า เราจะเห็นขั้นตอนการเรียก API ทีละสเต็ป ไปจนถึง kernel mode และกลับมา user mode อีกครั้ง , EDR ใช้เทคนิค เกี่ยวเบ็ด หรือตกปลา หรือ Hook นี่แหละ ในการ “ตรวจสอบ , ตรวจจับ พฤติกรรมน่าสงสัย (Malicious behavior detection from API Calls) ได้” โดยใช้เทคนิคในการ “ฉีด” ตัวเอง (injection, process inject) เข้าไปตรวจดู process อื่น ๆ , คือก็กูอยู่ใน kernel mode กูก็เก๋าพอตัว จึงทำได้ ! อารมณ์ประมาณนั้นเลย !!
มันเป็นยังไงครับ ? ก็ให้ภาพเล่าเลย จาก medium ของคุณ Kyle Mistele , 🙏🙏❤❤ very good ดีมากครับภาพนี้
อธิบายได้ว่า เมื่อ EDR อยู่ใน kernel mode มันสามารถที่จะถูกสั่งฉีด (inject) ตัวเองเพื่อเข้าไปเฝ้าดูการเรียก API ที่ malware มักจะใช้บ่อย ๆ ในแต่ละ process ได้ , เราจะเห็นขั้นตอนที่ 2 ที่เขียนว่า jmp Instruction to EDR code คือพอ process ปกติกำลังจะเรียก Windows API จะถูกแทรกโดย EDR ก่อน (กระโดดไปตรวจด้วยคำสั่ง = jmp ในภาษา assembly) , ซึ่งก็จะมี EDR Function ในการตัดสินใจที่จะ flag เพื่อ return ค่า ว่า api ที่เรียกมานี้ปลอดภัย หรือไม่ปลอดภัย กับ พฤติกรรมนี้ เลยกลายเป็นข้อ 3 , จากนั้นหาก detection เจอก็จะหยุด หรือป้องกันการรัน API นี้ ในทางตรงกันข้าม หาก detection ไม่พบว่าอันตรายอะไรก็ส่งต่อไปยัง syscall ต่อ
จะเห็นได้ว่า ในขั้นตอนที่ 2 มันก็คือการ hook API , ตัว API process เหมือนปลาที่กำลังว่ายน้ำ , EDR โยนเบ็ดลงไปใกล้ๆ ปลาตัวนั้น เพื่อให้งับเหยื่อ และพอปลาว่ายมาในท่าที่เหมาะสมก็จะตวัดเบ็ดขึ้นมาเพื่อดูปลา แต่พอดูแล้วปลาเป็นไง จะปล่อยไปหรือจับมากิน ก็แล้วแต่ ค่อยว่ากันตามวิธีคิดของคนตกปลา จึงเป็นแนวคิดของคำว่า hook
ในภาพคือโปรแกรม Ring3 API Hook Scanner x64 เพื่อใช้ลิสต์ดูรายการ API ที่ call และตรวจการ hook ในระดับ user mode ซึ่งไม่ใช่แค่ EDR ที่ทำตัวแบบนี้ (hook) ได้ , พวก malware ก็ hook เหมือนกัน เช่นพวก Rootkits ต่าง ๆ ที่พยายามฝังตัวเข้ามา หลังจากฝังสำเร็จ ก็เฝ้าดูการใช้ API เงียบๆ เมื่อถึง API ที่ใช่สำหรับพวกมัน ก็จะทำการ Hook ทันที , Rootkits kernel mode
User mode system process
ส่วนสุดท้ายที่ผมจะพูดถึงของ user mode แล้ว นั่นก็คือพวก process ดัง ๆ ที่เราต้องเห็นทุกเครื่องของ Windows เช่น Smss.exe / Winlogon.exe / Lsass.exe / Services.exe ซึ่งทั้ง 4 process นี้แม้จะทำงานในระดับ user mode ก็จริงแต่แนวทางที่มันทำงานก็ถือว่า ใกล้ชิดกับ kernel มากและรับส่งข้อมูลกับ kernel บ่อย เปรียบเหมือนสะพานในการเชื่อมกันระหว่าง user mode กับ kernel mode ก็ว่าได้
smss.exe คือ session manager subsystem , ถ้า systemd ของ linux เป็น pid หมายเลข 1 , smss.exe ก็คือ process หมายเลข 1 ของ windows เช่นเดียวกัน , ในระดับ user mode มันเป็น service process แรก ที่จะเริ่มต้นทำงาน เพื่อ initialize user ที่จะเตรียมเข้าสู่ระบบปฏิบัติการ , malware บางตัวก็ถือโอกาส หาจังหวะที่เหมาะสม (เช่น ตอน smss.exe มีสถานะ suspend หรือบังคับให้มัน suspend) นี้ ในการทำ process hollowing ได้ หากระบบการป้องกันไม่ดีพอ process hollowing ก็คือเหมือนกับ ส่งตัวเองไปแอบอยู่ข้างหลัง process ที่ดูเป็นหลัก อย่าง smss.exe อันนี้ โดยใช้เทคนิคที่คุ้นเคยคือการฉีดตัวเองเข้าไป (process injection)
winlogon.exe คือ Windows logon application ทำหน้าที่ดูแลเรื่องกระบวนการ logon / logoff ของ Windows เห็นแบบนี้แล้วสำคัญมากนะ เพราะการ logon สำเร็จคือแปลว่าการให้สิทธิ์ ในการรัน program ต่างๆ เข้าถึงทรัพยากรต่างๆ ของเครื่องได้ แม้จะมี user อื่นใช้งานอยู่ก็ตาม (เช่น Windows Server) เพราะหนึ่งในคอนเซ็ปหลักของระบบปฏิบัติการคือ รองรับการทำงานได้หลายๆ งาน (multi tasking) , และรองรับการใช้งานจากผู้ใช้ได้หลายๆ คน (multi users) ถึงจะเข้าคอนเซปใช้ทรัพยากรได้อย่างมีประสิทธิภาพสูงสุด , กลับมาดู winlogon.exe มันก็มีหน้าที่ดูแลเรื่องพวกนี้แหละ พวกการกด ctrl alt delete และทำการโหลดพวก user profiles ขึ้นมาหลังจาก logon สำเร็จด้วย ดังนั้น malware จึงสนใจในพวก credentials หรือพวก user password ในการเข้าใช้งาน OS ถ้าสามารถจัดการ winlogon.exe ได้ก็จะเข้าถึง credential ได้ หรือใช้ winlogon.exe บัง ให้ตัวอันตรายทำงานไปเพราะ winlogon.exe น่าเชื่อถือ
malware ประเภท ransomware ชื่อ blackcat ก็มีวิธีในการ inject process winlogon.exe ลิ้ง DFIR report = Nitrogen Campaign Drops Sliver and Ends With BlackCat Ransomware — The DFIR Report
lsass.exe คือ Local Security Authority Subsystem Service เป็น process service ที่คอยจัดการ token ในการ authentication ทั้งในระดับ local เอง (เช่น policy ของ local admin) หรือในการต่อในระบบ Active Directory ก็จะมี token เกี่ยวกับ credential ในระบบ ที่เชื่อมต่อกันแบบ secure เข้ามาเกี่ยวข้องกับ process นี้ , แน่นอนชาว red team เวลา hack AD ก็หนีไม่พ้น ต้องมีการเดินเข้ามาดูใน lsass.exe บ้างแหละ เครื่องมือยอดนิยมในการเข้ามาหาอะไรใน lsass.exe process memory ก็คือ mimikatz มีประสิทธิภาพสูง , มักจะเรียกการโจมตี lsass.exe นี้ว่า credentials dumping
services.exe คือ Service Control Manager หรือ SCM เป็น process ที่คอยจัดการ hardware ต่างๆ ในระดับสิทธิ์ user mode เช่น เปิดปิด bluetooth / enable หรือ disable ตัว status network wifi , user จะไม่ได้เข้าถึง hardware โดยตรงแต่จะส่งคำสั่งผ่าน scm นี้ และเมื่อ services.exe เกิดมาเพื่อจัดการ service ทุกครั้งที่ start up หรือบูตเครื่อง services.exe จึงพิเศษตรงที่เป็นทั้ง process ใน user mode และ kernel mode เช่น ใน EDR เมื่อบูตขึ้นมาก็ถือเป็น services ระดับ kernel mode และต้องให้ process อื่นๆ หรือ user มาสั่ง stop ไม่ได้ , services.exe ยังแตกอีกเป็นหลายๆ process เพื่อแบ่งหน้าที่กันคนละงานในด้าน hardware service หรือ system service แน่นอนสิทธิ์สูงที่มันเย้ายวนขนาดนี้ malware ก็ต้องการจะทำให้ตัวเองฝังใน services.exe ให้ได้ เช่น driver ของ hardware เขาทำโปรแกรมมาเป็น service เพื่อโหลดตอนบูต ทำให้ตอนเขียน driver ก็จะมีการ signed certificate ด้วย , malware ก็หาทางทำ fake certificate บ้าง เพื่อจะ signed ตัวเองเป็น driver และฝังตัวเป็น service ให้ได้จะได้ทำงานทุกครั้งตอนบูตเครื่อง นั่นเอง
services.exe เป็น process สำคัญ (ในมุม kernel mode) ที่เป็น parent process ทำให้เกิด svchost.exe ออกมา เป็น child process หรือ process ลูก
blog ของ Nasreddine Bencherchali ❤❤ ได้เขียนเรื่องนี้ไว้ ดีมาก 🙏🙏 แต่เราจะขยายความ svchost.exe ในภายหลัง ตอนนี้เอา map ไปดูก่อน
Kernel mode หรือ God mode (Ring0)
อันที่จริงแล้ว part นี้มันค่อนข้างอธิบายง่าย เพราะว่า …………. มันทำได้ทุกอย่างในเครื่องไงล่ะ !! process on kernel mode นั้นทำให้โปรแกรมเร็วขึ้นก็ได้ ประสิทธิภาพสูงขึ้นก็ได้ และฉันใดก็ฉันนั้น process on kernel mode ก็ทำให้ OS พังได้ มาดูกันว่า God มั้ย ?
- Read/Write All Memory Addresses อ่านและเขียนได้ทุกตำแหน่งของ memory ที่สุดของที่สุดของที่สุด ไม่ต้องบรรยายอะไรอีกแล้ว
- Direct Hardware Access: เขียนโปรแกรมสั่งงาน hardware ได้โดยตรง อยากปิด network card ไม่ใช้ network , kernel mode จัดให้ !! มี api ให้เรียกไปหา hardware เป็น 100+ api ยาวไปดิ
- Boot-Loaded Drivers (.sys Files) with Signed Digital Certificates: อุปกรณ์ hardware หลายยตัวต้องการ driver ที่เหมาะสมในการสั่งการ ผู้ผลิตได้เขียน driver ขึ้นมาและ signed มาให้ ติดตั้งแล้วก็บูตทุกครั้งที่ใช้งาน Windows ประสิทธิภาพเลยดี
- Extended Control over DLL and COM: ไม่ใช่แค่ hardware ที่เป็น driver หรือ low-level , ตัว EDR ก็ต้องมี driver ด้วย , DLL (ย่อมาจาก Dynamic Link Libraries) และ COM (ย่อมาจาก Component Object Model) อีกมากมายที่ต้องโหลดขึ้นมา ทั้งตอนบูตหรือตอนใช้โปรแกรมสิทธิ์สูงอื่น ๆ
- Full Access to System Calls: จะไปยุ่งยากอะไรกับ switching user mode / kernel mode ระหว่างเรียก API call ก็เรียก system calls ตรงๆไปเลย เร็วก็เร็วสุด พังก็พังกันไป เอาดิ
- Execution of Privileged Instructions: ถ้า cpu มีคำสั่งพิเศษให้ใช้ เช่นการทำ interrupt handling , ก็ทำไม่ได้ใน user mode ต้อง kernel mode เท่านั้น หรือพวก DMA (Direct Memory Access) user mode ไม่ไหวครับ ระบบ pages แบ่งไว้ชัดเจน , kernel mode ไปได้ทุก address
- Manage Process and Thread Context: จะมี process อะไร , จะมี thread อะไรขึ้นมา ก็เข้าไปจัดการได้หมด จัด priority , scheduling หรือ terminate process ต่างๆ
- System-Level Callbacks and Hooks: อธิบายไปแล้วเรื่อง hook
- Manage Protected Processes (PPL/PP): PPL ย่อมาจาก Protected Processes Light ส่วน PP ย่อมาจาก Protected Proesses , คือกลุ่ม process ที่ถูกป้องกันไว้ , ในระดับ kernel mode เราสามารถบริหารจัดการ PPL/PP ได้ เช่น เราปรับ priority ของ antivirus process ได้ , แน่นอน ทำได้ใน kernel mode เท่านั้น
- Direct Disk I/O Operations: ตามชื่อเลย ก็เข้าถึง disk ได้ มากถึงระดับ raw disk sectors เลยนะ (งาน forensic ก็ทำกันตรงนี้แหละ , สิทธิ์ต่ำก็เข้าถึงได้ไม่เยอะ , kernel mode เท่านั้น)
- Ability to Disable Security Mechanisms: ที่สุดเลยอันนี้ คือหยุดพวก Windows Defender ได้ หรือหาทางหยุด ETW (Event Tracing for Windows) ได้ เอาจริงๆ มันก็ยากนะ เพราะหลังๆมานี่พี่เค้าป้องกันหนัก ไม่ยอมให้ Disable ได้ง่ายๆ , แต่ kernel mode ก็ไม่มีระดับสูงกว่านี้แล้ว (Ring0) เดี๋ยวมาดูในตอนต่อๆไปครับ
- Interrupt Handling:จัดการ การขัดจังหวะ (interrrupt) ได้ , กดคีย์บอร์ดลงไปก็เป็นการ IRQ (interrupt request) พอจัดการใน level นี้ได้ก็เอา malware ไป capture keystroke ได้ไง ว่าพิมพ์อะไรบ้าง เป็นต้น ,จะทำแบบนี้ได้ก็ kernel mode สิครับ
- Control of Virtual Address Translation: เล่าไปแล้วข้างบนเรื่อว virtual address และ pages , ก็อย่างที่บอกว่า kernel mode เข้าถึงได้ทุกตำแหน่งของ memory จะโยกอะไรก็เต็มที่เลยแม้แต่ Virtual address ของ user mode ที่แปลงร่าง (translation) มาอยู่ใน pages หรือ map กับ ram จริงๆ ก็ตาม , kernel mode จัดให้ได้หมด
- Dynamic Kernel Modules/Drivers Loading:มี hardware ใหม่ๆ มาเข้ามาเชื่อมต่อ ต่อพร้อมที่จะ dynamics driver นะครับ , kernel mode ก็พร้อมให้เรียก API , โหลด driver กันแบบ แบบ dynamic เลย ไม่ต้องรอบูต , สะดวกนะ แต่ malware แบบ rootkits ก็ชอบเหมือนกัน
- Manage and Alter System Privileges and Tokens: มี process ที่สามารถปรับแต่งแก้ไขสิทธิ์ user อื่นได้เต็มพิกัด หรือจะให้เป็น kernel mode ในบาง user / บาง service ก็ได้
- Undetectable Process Creation and Manipulation: โคตรดี ! ดีมาก ๆ ! มันคือธรรมชาติของ kernel mode , เพราะการทำงานของ process ที่เรียกใช้ทรัพยากรต่างๆ ของ computer hardware ด้วย kernel mode นั้นไม่จำเป็นที่จะต้องแสดงอะไรออกมา ทำงานเงียบๆ แล้วก็จบไป ดังนั้นโปรแกรมที่อยู่ใน Ring0 จะต้องถูกออกแบบและเขียนมาอย่างดีมาก จะได้ประสิทธิภาพมาก แต่ถ้าไม่ดีก็กลายเป็น Malware หรือมุมนึงก็คือทำให้ OS พัง
Availability ก็เป็นอีกแกนสำคัญของ Cyber Security นะครับ
17. Override Critical System Hooks:ไม่ใช่มีแค่ EDR เท่านั้นที่ hook แต่ยังมี service อื่นๆ อีก จนต้องมี SDT (System Service Descriptor Table) กับ IDT (Interrupt Descriptor Table) เอาไว้ตรวจและบริหารจัดการเรื่องพวกนี้ , แน่นอนหมายเหตุไว้เหมือนเดิมว่า kernel mode นะครับ
18. Access to Kernel Debugging Tools:เขียนโปรแกรมมาใช้งาน มาขาย ก็ต้องทดสอบ ก็ต้อง debug โปรแกรมบางอย่างจำเป็นต้อง kernel mode. ถ้า developer ไม่มีสิทธิ์ตรวจสอบหรือ debug เลยจะเขียนทำแมวน้ำอะไร โปรแกรมใช้ใน kernel mode ก็ต้องสามารถ debug ได้ใน level เดียวกัน
19. Disable or Bypass Secure Boot (in some scenarios): บางสถานการณ์ก็ต้องมี process ในการ disable secure boot หรือ bypass มันให้บูตไปอีกรูปแบบนึง อาจจะเป็นจังหวะการอัพเดต bootloader firmware หรือเป็นจังหวะทดสอบโปรแกรมของเราเอง , ทำไม่ได้ใน user mode แน่นอนครับ
ส่งท้าย
เริ่มต้นกับซีรีย์นี้นะ คิดเห็นยังไงก็คอมเม้นกัน
จริงๆ ดูเผินๆ ก็รู้แล้วว่า kernel mode ทำอะไรได้มากกว่า user mode
แต่สิ่งที่เราต้องการรู้คือ มันมีขอบเขตกันและกันขนาดไหน ในรายละเอียด ?
ถ้าอยู่ใน user mode เราจะยึดระบบหรือ hack ได้มั้ย ?
ถ้าอยู่ใน user mode environment ประมาณนี้ เราจะยกระดับสิทธิ์ process ของเราไหวมั้ย ?
ถ้าอยู่ใน kernel mode เราจะหลบหลีก / ทำลาย EDR ยังไง ?
อันนี้แหละที่ต้องลุยต่อ / เจอกัน blog ต่อไป
references :
Nitrogen Campaign Drops Sliver and Ends With BlackCat Ransomware — The DFIR Report
Introduction | Red Team Notes 2.0
A Syscall Journey in the Windows Kernel — Alice Climent-Pommeret