รูปปกบทความ

1. 🎯 ตอนที่ 6: Windows API และประตูสู่ระบบ

แกะรอยการสื่อสารระหว่างแอปพลิเคชันกับระบบปฏิบัติการ ทำความรู้จัก Win32 API และความลับของ Native API ที่ซ่อนอยู่เบื้องหลัง

2. 📖 เปิดฉาก (The Hook)

จิบกาแฟแล้วมาลุยกันต่อครับน้องๆ… เวลาที่เราเขียนโปรแกรม ไม่ว่าจะใช้ภาษา C++, C# หรือ Python แล้วสั่งให้มันทำงานพื้นฐานอย่างเช่น การเปิดไฟล์ (Read File), การจองหน่วยความจำ (Allocate Memory) หรือการสร้าง Process ใหม่ น้องๆ เคยสงสัยไหมครับว่า โปรแกรมกิ๊กก๊อกของเราที่รันอยู่ใน User Mode (ซึ่งไม่มีสิทธิ์แตะต้องฮาร์ดแวร์เลย) มันไปสั่งให้ฮาร์ดดิสก์หมุน หรือสั่งให้แรมจองพื้นที่ได้อย่างไร?

คำตอบแบบกำปั้นทุบดินที่ Programmer ทั่วไปรู้ก็คือ “อ๋อ… เราก็เรียกใช้ Windows API สิ!” แต่ในฐานะที่เราเป็นสาย Hardcore Internals แค่คำว่า Windows API มันยังตื้นเกินไปครับ เพราะเบื้องหลังคำสั่งง่ายๆ อย่าง CreateFile มันมีการส่งไม้ต่อผ่าน “ประตูลับ” ที่ไมโครซอฟท์ซ่อนไว้ไม่ให้คนทั่วไปเห็น เพื่อกระโดดข้ามกำแพงเข้าสู่ Kernel Mode วันนี้พี่จะพาไปเจาะลึกโครงสร้างของ API และเปิดโปงหน้าตาของประตูบานนี้กันครับ

3. 🧠 แก่นวิชา (Core Concepts)

เพื่อให้แอปพลิเคชันสามารถคุยกับระบบปฏิบัติการได้อย่างเป็นมาตรฐาน Windows ได้ออกแบบชั้นของการสื่อสาร (Layers) ไว้เป็นทอดๆ ดังนี้ครับ:

  • Windows API (Win32 API) - หน้าฉากที่สวยงาม: มันคือชุดคำสั่ง (Functions) อย่างเป็นทางการที่ไมโครซอฟท์จัดทำเป็นเอกสาร (Documented) ให้ Developer นำไปใช้งาน API เหล่านี้ถูกฝังอยู่ในไฟล์ที่เราเรียกว่า Subsystem DLLs เช่น kernel32.dll, user32.dll, advapi32.dll หน้าที่ของมันคือทำให้การเขียนโปรแกรมง่ายขึ้นและเข้ากันได้กับ Windows ทุกเวอร์ชัน แต่รู้หรือไม่ครับว่า… ฟังก์ชันอย่าง CreateProcess หรือ ReadFile ใน kernel32.dll แทบจะไม่ได้ทำงานระดับลึกด้วยตัวเองเลย มันเป็นแค่นายหน้า (Wrapper) เท่านั้น!
  • NTDLL.DLL (The Lowest User-Mode Layer): นี่คือไฟล์ DLL ที่สำคัญที่สุดในโลกของ User Mode ทุก Process บน Windows “ต้อง” มีไฟล์ ntdll.dll แฝงตัวอยู่เสมอ มันคือด่านสุดท้ายก่อนที่จะข้ามไปยัง Kernel Mode หน้าที่หลักของมันคือการบรรจุสิ่งที่เรียกว่า Native API
  • Native API (Undocumented API) - ประตูลับสู่ Kernel: Native API คือชุดคำสั่งที่ซ่อนอยู่ใน ntdll.dll (มักจะขึ้นต้นด้วยคำว่า Nt หรือ Zw เช่น NtCreateFile) ไมโครซอฟท์ ไม่เปิดเผยเอกสาร (Undocumented) การใช้งานฟังก์ชันเหล่านี้สำหรับฝั่ง User Mode อย่างเป็นทางการ เพราะพวกเขาต้องการอิสระในการปรับเปลี่ยนโครงสร้าง Kernel ในอนาคตโดยไม่ทำให้แอปพลิเคชันพัง (เพราะแอปพลิเคชันคุยกับ Win32 API แทน)
  • System Call - การกระโดดข้ามพรมแดน: เมื่อโปรแกรมเรียก Native API ใน ntdll.dll โค้ดในนั้นจะทำการบรรจุหมายเลขประจำตัวของฟังก์ชัน (System Service Number) ลงใน CPU Register แล้วเรียกใช้คำสั่งระดับฮาร์ดแวร์พิเศษ (เช่น syscall บน x64 หรือ sysenter บน x86) เพื่อให้ CPU สลับบริบทการทำงาน (Mode Transition) จาก User Mode พุ่งตรงเข้าไปหา System Service Dispatcher ภายในแก่นของ OS (Ntoskrnl.exe) ในระดับ Kernel Mode ทันที!
รูปประกอบ Architecture ของ Windows API สู่ Native API

4. 💻 ร่ายมนต์โค้ดและคำสั่ง (Show me the Code/Commands)

เพื่อพิสูจน์ให้เห็นภาพ เรามาใช้ WinDbg แกะรอยคำสั่งพื้นฐานอย่างการเปิดไฟล์ (CreateFileW) ดูกันครับว่า สุดท้ายแล้วมันไปจบที่ไหน

// 1. ตั้ง Breakpoint ที่ Win32 API ทั่วไปใน kernel32.dll (หรือ kernelbase.dll ในยุคใหม่)
0:000> bp KERNEL32!CreateFileW

// 2. เมื่อโปรแกรมเรียกเปิดไฟล์ จะพบว่ามันไปเรียก Native API ใน ntdll.dll ต่อ
0:000> u ntdll!NtCreateFile
ntdll!NtCreateFile:
// ย้ายหมายเลข System Service Number (เช่น 55 หรือ 0x55) ใส่ใน Register EAX
00007ff8`34f23130 4c8bd1          mov     r10,rcx
00007ff8`34f23133 b855000000      mov     eax,55h      <-- นี่คือ ID ของ NtCreateFile

// 3. ใช้คำสั่ง syscall เพื่อข้ามกำแพงเข้าสู่ Kernel Mode!
00007ff8`34f23138 0f05            syscall              <-- กระโดดเข้า Ring 0 ทันที
00007ff8`34f2313a c3              ret

คอมเมนต์สไตล์คุยกัน: เห็นไหมครับน้องๆ! ไม่ว่าเราจะใช้ภาษาอะไรเขียนแอปพลิเคชัน หรือเรียก Win32 API หรูหราแค่ไหน ท้ายที่สุดทุกเส้นทางจะมาบรรจบกันที่ ntdll.dll เพื่อยัดตัวเลขใส่ Register แล้วยิงคำสั่ง syscall ส่งไปให้ Kernel จัดการให้เสมอ นี่แหละครับความจริงของระบบ!

5. 🛡️ เคล็ดลับจากคัมภีร์ลับ (Under the Hood / Pro-Tips)

Trick สำหรับ Security Researcher และ Malware Analyst: มัลแวร์ระดับ User-mode Rootkit มักจะใช้วิธี API Hooking เพื่อซ่อนตัว (เช่น ซ่อน Process ของตัวเองไม่ให้ Task Manager เห็น) โดยพวกมันมักจะไปแอบฝังโค้ดดักจับอยู่ที่ kernel32.dll หรือ advapi32.dll

Pro-Tip: ถ้าน้องเขียนเครื่องมือสแกนไวรัส แล้วไปเรียกใช้ Win32 API ธรรมดาเพื่อตรวจหามัลแวร์ น้องจะโดนหลอกเอาได้ง่ายๆ ครับ! บรรดาโปรแกรม Security ระดับเทพ (หรือแม้แต่เครื่องมืออย่าง Sysinternals) มักจะมองข้าม Win32 API แล้วยิงตรงลงไปเรียกใช้ Native API (NtQuerySystemInformation) ใน ntdll.dll เลย เพื่อมุดหลบการดักจับของมัลแวร์ที่อยู่ชั้นบน หรือบางทีอาจจะเขียนโค้ดเพื่อยิง syscall ด้วยตัวเองเลยเพื่อความชัวร์ (Direct Syscall) ครับ!

ข้อควรระวังสำหรับ Developer: การเรียกใช้ Native API โดยตรงในโปรแกรม Production เป็นเรื่องที่ “อันตรายและไม่แนะนำ” เพราะตัวเลข System Service Number (อย่าง 55h ในตัวอย่าง) มีการเปลี่ยนแปลงเสมอใน Windows แต่ละเวอร์ชัน (หรือแม้แต่แค่ลง Service Pack) ถ้าเขียนฮาร์ดโค้ดไว้ โปรแกรมมีสิทธิ์จอฟ้าหรือแครชได้เลยครับ ควรเรียกผ่าน Win32 API ปลอดภัยที่สุด

6. 🏁 บทสรุป (To be continued…)

Windows API (Win32) คือหน้าต่างต้อนรับที่ทำให้โปรแกรมเมอร์ทำงานง่าย ส่วน Native API (ntdll.dll) คือประตูลับที่ใช้คุยกับสถาปัตยกรรมระดับล่างของระบบอย่างแท้จริง การเข้าใจโครงสร้างการส่งไม้ต่อตรงนี้ จะช่วยให้น้องๆ เข้าใจพฤติกรรมของโปรแกรม การทำงานของมัลแวร์ และการทำ Reverse Engineering ได้อย่างทะลุปรุโปร่ง

ในตอนต่อไป เราจะข้ามกำแพง syscall นี้เข้าไปดูฝั่ง Kernel Mode กันเต็มๆ ว่าเมื่อข้อมูลไปถึง Ntoskrnl.exe แล้ว มันมีชิ้นส่วนไหนรับช่วงต่อบ้าง ห้ามพลาดนะครับ!


ต้องการที่ปรึกษาและพัฒนาระบบ Automation หรือ Enterprise Infrastructure ให้กับธุรกิจของคุณ? ทีมงาน WP Solution พร้อมให้บริการออกแบบและติดตั้งระบบแบบครบวงจร ดูรายละเอียดบริการของเราได้ที่: www.wpsolution2017.com หรือพูดคุยปรึกษาเบื้องต้นได้ที่ Line: wisit.p