Thursday, May 10, 2012

0x201 Intro Buffer Overflow

ช่องโหว่บัฟเฟอร์โอเวอร์โฟลว์นั้นมีมานานแล้ว นับตั้งแต่การถือกำเนิดของคอมพิวเตอร์และก็ยังไม่อยู่ในปัจจุบัน

ในขณะที่ความง่ายของภาษา 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