X86_64 จากซอร์สโค้ดสู่ไบนารี: ทำความเข้าใจ GCC และ DEP/NX
เจาะลึกกระบวนการทำงานของ GCC ในระบบ x86_64 สำรวจกลไก Buffer Overflow และความสำคัญของการตั้งค่าสแต็กให้ไม่สามารถรันโค้ดได้ (NX/DEP)

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
- สแต็กโอเวอร์ฟลอกเกิดขึ้นเมื่อข้อมูลล้นความจุจนไปทับตำแหน่งแอดเดรสส่งกลับ
- ฟังก์ชันอย่าง strcpy และ memcpy มักเป็นจุดเริ่มต้นของช่องโหว่ความปลอดภัยนี้
- ตัวเลือก -z ของ GCC ควบคุมการส่งผ่านคำสั่งไปยังตัวเชื่อมโยงหรือลิงเกอร์
- NX/DEP ทำหน้าที่ป้องกันไม่ให้ระบบปฏิบัติการรันโค้ดที่อยู่บนสแต็กโดยตรง
บทความนี้ต่อยอดจากการอธิบายตัวเลือก -fstack-protector ของ GCC โดยจะพาทุกท่านไปทำความเข้าใจเชิงลึกเกี่ยวกับวิธีตั้งค่าสแต็กให้ไม่สามารถรันโค้ดได้ (Non-Executable Stack) พร้อมทั้งสำรวจกลไกเบื้องหลังที่โปรแกรมคอมพิวเตอร์แปลงร่างจากซอร์สโค้ดภาษา C ไปเป็นไฟล์ไบนารีบนสถาปัตยกรรม x86_64
ปัญหาช่องโหว่ประเภท Buffer Overflow มักเกิดขึ้นเมื่อโปรแกรมเขียนข้อมูลลงในบัฟเฟอร์เกินกว่าขนาดที่จัดสรรไว้ ส่งผลให้หน่วยความจำข้างเคียงเกิดความเสียหาย โดยเฉพาะส่วนของ saved return address บนสแต็ก ซึ่งแฮกเกอร์สามารถใช้ฟังก์ชันอย่าง strcpy หรือ memcpy ในการโจมตีเพื่อเปลี่ยนทิศทางกระแสการทำงานของโปรแกรมได้

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
ในภาษา C ตัวอย่างเช่น การคัดลอกข้อมูลคำขอขนาด 256 ไบต์ ลงในตัวแปรบัฟเฟอร์ที่มีพื้นที่เพียง 64 ไบต์ ด้วยคำสั่ง strcpy(buffer, request); จะทำให้เกิดการทับซ้อนของหน่วยความจำ และเปิดช่องให้ผู้ไม่หวังดีเข้ามาควบคุมการทำงานได้ เนื่องจากตัวแปรดังกล่าวถูกจัดสรรไว้บนสแต็ก จึงเรียกปรากฏการณ์นี้ว่า Stack-based Buffer Overflow
การทำความเข้าใจกลไก NX (No-Execute) หรือ DEP (Data Execution Prevention) ถือเป็นรากฐานสำคัญของความปลอดภัยในระบบคอมพิวเตอร์ยุคใหม่ ในอดีตหน่วยความจำทุกส่วนมักถูกอนุญาตให้รันโค้ดได้ทั้งหมด แต่วิธีนี้เปิดช่องให้ผู้โจมตีฝังโค้ดอันตรายลงในหน่วยความจำข้อมูลแล้วสั่งรันได้โดยตรง การบังคับให้สแต็กเก็บได้เฉพาะข้อมูลแต่ห้ามรันคำสั่ง จึงเป็นเกราะป้องกันด่านแรกที่หยุดยั้งการโจมตีลักษณะนี้ได้อย่างชะงัด
สำหรับการใช้งานคอมไพเลอร์ GCC นั้น ตัวเลือก -z จะทำหน้าที่ส่งอาร์กิวเมนต์ต่อไปยังลิงเกอร์ โดยออปชัน execstack จะไปลบกลไกการป้องกันเริ่มต้นที่กำหนดให้โปรแกรมห้ามรันโค้ดจากสแต็ก ซึ่งโดยทั่วไปแล้ว เราจะใช้ตัวเลือกนี้เพื่อวัตถุประสงค์ในการศึกษาและวิเคราะห์กลไกของช่องโหว่เท่านั้น ไม่แนะนำให้เปิดใช้งานจริงในการพัฒนาโปรแกรมทั่วไป
โครงสร้างไฟล์ ELF (Executable and Linkable Format) ประกอบด้วยองค์ประกอบหลักหลายส่วน เช่น ELF Header ทำหน้าที่เปรียบเสมือนบัตรประจำตัวของไฟล์, Program Header Table ที่จำเป็นสำหรับการรันโปรแกรมเพื่อบอกระบบปฏิบัติการว่าต้องแมปไฟล์ลงในหน่วยความจำอย่างไร รวมถึงส่วนของ Sections ต่างๆ เช่น .text สำหรับโค้ดคำสั่ง, .data และ .bss สำหรับตัวแปรประเภทต่างๆ
ที่มา: Dev.to
พบข้อมูลผิดพลาดในบทความนี้? แจ้งปัญหาบทความนี้
ความคิดเห็น
แสดงความคิดเห็น