ในขณะที่ความง่ายของภาษา C ได้เพิ่มระดับการควบคุมโปรแกรมให้กับโปรแกรมเมอร์และเพิ่มประสิทธิ์ภาพของโปรแกรมที่ผ่านการคอมไพล์ มันยังช่วยเพิ่มโอกาสในการที่โปรแกรมจะได้รับผลกระทบต่อปรากฏการณ์บัฟเฟอร์โอเวอร์โฟลว์ และปัญหาการขาดแคลนหน่วยความจำด้วย ถ้าโปรแกรมเมอร์ไม่ระมัดระวังพอ นี่หมายความว่า ทันที่ได้รับการจองเนื้อที่หน่วยความจำได้ถูกจัดสรรสำหรับตัวแปรหนึ่งๆแล้ว มันจะไม่มีกลไลป้องกันภายในใดๆ ที่จะรับประกันได้ว่าข้อมูลที่จะนำไปเก็บในตัวแปรนั้น มีขนาดเหมาะสมพอดีกับเนื้อที่หน่วยความจำที่ได้จัดเตรียมไว้ ถ้าโปรแกรมเมอร์ต้องการบรรจุข้อมูลขนาดสิบไบต์เข้าไปในบัฟเฟอร์หน่วยความจำที่มีขนาดเพียงแปดไบต์เท่านั้น พฤติกรรมนี้จะอนุญาตให้เกิดขึ้นได้ แต่ทว่ามันจะเป็นไปได้สูงมากที่โปรแกรมจะแครชและพังลงไป ปรากฏการณ์นี้เรียกว่า บัฟเฟอร์โอเวอร์โฟลว์ เนื่องจากข้อมูลอีกสองไบต์ที่ล้นเกินมานั้นจะไปโอเวอร์โฟลว์ และทำให้หน่วยความจำล้น อีกทั้งยังมีโอกาสไปเขียนทับข้อมูลใดๆ ที่ได้ถูกเก็บไว้ต่อจากพื้นที่หน่วยความจำนั้น ถ้าข้อมูลสำคัญได้ถูกเขียนทับ โปรแกรมจะแครช
ตัวอย่างโปรแกรม overflow_example.c
/* * Compile * gcc -fno-pie -fno-stack-protector -z norelro -z execstack -mpreferred-stack-boundary=2 -o overflow_example overflow_example.c * */ #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { int value = 5; char buffer_one[8], buffer_two[8]; strcpy(buffer_one, "one"); /* put "one" into buffer_one */ strcpy(buffer_two, "two"); /* put "two" into buffer_two */ printf("[BEFORE] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two); printf("[BEFORE] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one); printf("[BEFORE] value is at %p and is %d (0x%08x)\n", &value, value, value); printf("\n[STRCPY] copying %d bytes into buffer_two\n\n", strlen(argv[1])); strcpy(buffer_two, argv[1]); /* copy first argument into buffer_two */ printf("[AFTER] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two); printf("[AFTER] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one); printf("[AFTER] value is at %p and is %d (0x%08x)\n", &value, value, value); }
หลังจากคอมไฟล์โปรแกรมแล้ว เราได้ทดลองสำเนาสิบไบต์จากอากิวเมนต์แบบบรรทัดคำสั่ง อากิวเมนต์แรกเข้าไปในต้วแปร buffer_two ซึ่งตัวแปรนี้ได้จัดสรรพื้นที่หน่วยความจำไว้เพียงแปดไบต์เท่านั้น
root@bt:~/Hacking# ./overflow_example 1234567890 [BEFORE] buffer_two is at 0xbffff514 and contains 'two' [BEFORE] buffer_one is at 0xbffff51c and contains 'one' [BEFORE] value is at 0xbffff524 and is 5 (0x00000005) [STRCPY] copying 10 bytes into buffer_two [AFTER] buffer_two is at 0xbffff514 and contains '1234567890' [AFTER] buffer_one is at 0xbffff51c and contains '90' [AFTER] value is at 0xbffff524 and is 5 (0x00000005)
สังเกตว่าตัวแปร buffer_one ดได้รับการจัดเก็บไว้โดยตรงทันทีต่อจากตัวแปร buffer_two ในหน่วยความจำ ดังนั้นเมื่อสิบไบต์ถูกสำเนาไปไว้ที่ buffer_two อีกสองไปต์ที่เหลือคือ 90 ก็จะไปโอเวอร์โฟลว์ในตัวแปร buffer_one และจะเขียนทับอะไรก็ตามที่อยู่ในตัวแปรนี้
โดยธรรมชาติแล้ว บัฟเฟอร์หน่วยความจำขนาดใหญ่ขึ้นมันโอเวอร์โฟลว์ล้นไปอยู่ในพื้นที่หน่วยความจำที่เก็บตัวแปรอื่น แต่ถ้าบัฟเฟอร์มีขนาดใหญ่มากขึ้นอีกถึงจุดหนึ่ง โปรแกรมอาจจะแครชและตายลงได้
root@bt:~/Hacking# ./overflow_example AAAAAAAAAAAAAAAAAAAAAAAAAAAAA [BEFORE] buffer_two is at 0xbffff504 and contains 'two' [BEFORE] buffer_one is at 0xbffff50c and contains 'one' [BEFORE] value is at 0xbffff514 and is 5 (0x00000005) [STRCPY] copying 29 bytes into buffer_two [AFTER] buffer_two is at 0xbffff504 and contains 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAA' [AFTER] buffer_one is at 0xbffff50c and contains 'AAAAAAAAAAAAAAAAAAAAA' [AFTER] value is at 0xbffff514 and is 1094795585 (0x41414141) Segmentation fault
No comments:
Post a Comment