بخشی از مقاله
چکیده
یکی از موضوعات مطرح در فرآیند آزمودن نرمافزار، یافتن روشی برای پیدا کردن خطاهای نرمافزارها است. در زمان حاضر، نرمافزارها بسیار پیچیده وحجیمشدهاند و در یایِدن امروز، یافتن غیر خودکار این خطاها امری بسیار دشوار و در فضای عملیاتی غیرممکن تلقی میشود. درنتیجه ارائهی روشهای خودکار یافتن خطاهای نرمافزارها تبدیل به موضوع بسیار مهمی در این زمینه گشته است.
در این مقاله ابزاری ارائهشده است که تقریبا تمامی نرمافزارها را، بدون داشتن هیچ تصور فنی از نحوهی کارکرد آن نرمافزار، آزمایش مینماید. این ابزار بر چهار قسمت بنا شده است. تحلیل ایستا، ردگیری داده، تست فاز بر روی حافظه و نظارت بر خطاها. هستهی این روش بر مبنای تست فاز برنامهی اجرایی، بر روی حافظه است. به این معنا که برنامهی اجرایی در صورت صدا شدن بر روی حافظه آورده شده و سپس در حین اجرا تست فاز انجام خواهد شد. درنتیجهی این پژوهش ما موفق به تولید ابزاری شدیم که توانسته است نرمافزارهای مبتنی بر سیستمعامل Microsoft Windows را تست نماید و خود نیز بر روی این سیستمعامل کار کند.
-1 مقدمه و مفاهیم پایه
دستهبندی روشهای یافتن خطاهای نرمافزارها به روش جعبه سفید، روش جعبه خاکستری و روش جعبه سیاه تقسیم میشوند.[1] ابزار ارائهشده در این پژوهش، که آنرا ++0 نامیدیم، به صورت جعبه خاکستری طراحی شده است. ابزار ++0 از چهار مرحلهی اصلی که به ترتیب تحلیل ایستا، ردگیری داده، تست فاز در حافظه و نظارت بر خطاها نام دارند، تشکیل شده است. نوآوریهای این پژوهش بهطور خلاصه عبارتاند از:
· شرح دقیق، تعیین بدون ابهام و کارای فرآیند تست فاز بدون دانش که امکان آزمایش تمامی نرمافزارها را داراست.
· بهبود مرحلهی تحلیل ایستا در افزایش سرعت و استحکام در طراحی و پیادهسازی این مرحله و همچنین استفاده از چارچوب بهینه.
· بهبود مرحلهی ردگیری دادهها ازنظر سرعت و دقت و تعیین دقیق منظور از ردگیری دادهها و مورداستفادهی این روش در تست فاز بدون دانش.
· ایدهی تشخیص آرگومانهای توابع و آدرس آنها در مرحلهی تحلیل ایستا برای دقت بیشتر در فرآیند تست فاز بر روی حافظه و فرآیند تست فاز بر روی حافظه بدون از دست دادن سرعت و ایجاد امکان برای تنظیم منعطف کاربر.
· ایجاد راهکاری برای تشخیص خطا در برنامههای تحت تحلیل چارچوبهای ابزارمندی باینری و شرح دقیق نحوهی کار اشکالزدا* در فرآیند تست فاز بدون دانش.
· انجام تمامی مراحل بهصورت عملی، یافتن واقعی نقاط ضعف و قوت این روش و ایجاد نقشهی راه برای ادامهی آن بهجای ارائهی خام یک ایده.
· استفاده از چارچوبهای متنباز و در اختیار به جای استفاده از چارچوبهای گرانقیمت.
در ابزار ++0 از روش تست فاز بر روی حافظه[2] استفاده شده است. این روش ازجمله روشهای تست نرمافزار در حالت اجرا است. تست فاز بر روی حافظه، با تغییر آرگومانهاتوابعِی در حالِ اجرای برنامه، این توابع را تست مینماید. ایدهی اصلی این روش دور زدن محدودیتهای ایجادشده توسط تجزیهکنندهها، سازوکارهای حفاظت از برنامه، شبکه، سامانههای تشخیص نفوذ، پروتکلهای ناشناخته و غیره است.
در ابزار ++0 مفهوم دیگری که باید موردتوجه قرار بگیرد، مفهوم ردگیری پویای داده[4] ,[3] است. این مفهوم با استفاده از روش تعقیب پویای جریان اطلاعات[5] پیاده میشود. در این روش به تعقیب جریان موردعلاقهی اطلاعات در سطح برنامه با بررسی دستورالعملهای در حال اجرا میپردازیم. بخشهای این مقاله به این شرح است: در بخش دوم به روشهای مشابه در زمینهی تست نرمافزار با استفاده از ردگیری داده و تست فاز بر روی حافظه را بررسی میکنیم.
در بخش سوم به بررسی قطعات اصلی ابزار ++0 خواهیم پرداخت که به ترتیب اجرا، ابتدا به قسمت تحلیل ایستا پرداخته و سپس در قسمت بعدی ردگیری داده را بهصورت دقیق بررسی مینماییم. به همین ترتیب در قسمت بعد، به بررسی مفهوم تست فاز بر روی حافظه پرداخته و چالشهای این موضوع را بررسی کرده و راهحلهای ارائهشده برای این چالش ها را در ابزار ++0 تحلیل مینماییم. در قسمت آخر این بخش نیز به بررسی قسمت مشترک بین تمام فازرها یعنی نظارت بر خطا میپردازیم و مشکلات پیش رو در این زمینه برای ابزار خود را بررسی مینماییم و در بخشی چهارم به ارزیابی این ابزار پرداخته و در بخش آخر به شرح مشکلات باقیمانده و کارهای پیش رو خواهیم پرداخت.
-2 بررسی روشهای مشابه
تست فاز تکنیکی است که برای تست و ارزیابی نرمافزارها به کار گرفته میشود. باید متذکر شد که در این زمینه روشهای بسیاری ارائهشده است. از برخی روشهای معروف در این حوزه، میتوان به تست فاز فایل[6] و تست فاز پروتکل[7] اشاره کرد. با پیشرفت این روش، برخی افراد به فکر استفاده از جهش در این زمینه افتادند.[8] در این روش بهجای عوض کردن مقادیر با مقادیر از پیش تعیینشده، مقادیر را با تغییریافتهی خودشان تغییر میدادند.[8]
این نگرش آغازی برای تست فاز هوشمند[9] بود. در اینگونه روشها تمرکزی بر مقادیر دادهشده نداشته و بیشتر به چگونگی تغییر مقادیر و استفاده هر چه بیشتر از دانش منابع در دسترس تکیه میکنند. زیرا به این نتیجه رسیدهبودند که تست فاز هوشمند معمولاً نتایج بیشتری را در بردارد.[10] از طرفی دیگر، در سال 2010 مبحث تست فاز بر روی حافظه مطرح شد و مورد استقبال تحلیلگران قرار گرفت و حتی چارچوبهایی که در بعضی موارد برای کارهای دیگری ساختهشده بودند، در این مبحث به کار گرفته شدند. اما تکیه بر ردگیری داده و ادغام آن با تست فاز، در چند نمونه مقالهی محدود بیشتر به چشم نمیخورد.
[13]- [11] ردگیری داده بیشتر در قسمت تحلیل خطا و رسیدن به آسیبپذیری و تحلیل آن کاربرد دارد[14] تا درزمینهی کشف خطا در نرمافزار. شبیهترین کار به ++0 روشی موسوم به 0-knowledge-fuzzing[11] هست. 0-knowledge fuzzing دارای ابهامات بسیار زیادی در مورد طراحی و پیادهسازی است و شاید بتوان گفت که تفاوتهای بسیاری با ++0 دارد که از این اختلافات میتوان به تفاوت معماری کلی و نحوهی استفاده از مراحل مختلف کار، تفاوت در تشخیص اشارهگرهای تابع در تحلیل ایستا، تفاوت در تشخیص تعداد آرگومانهای توابع در تحلیل ایستا، تفاوت در بهرهگیری از چارچوب IDA-Pro[15] بهجای چارچوب BinNavi[16] به دلیل افزایش چشمگیر سرعت و از همه مهمتر شرح دقیق و سادهی این ابزار و غیره نام برد.
قابل توجه است که در روش 0-knowledge fuzzing جزییات ابزار بسیار مبهم هستند. ابزارهای دیگری شبیه به ابزار ++0 نیز عرضهشدهاند. یکی از نزدیکترین آنها TaintScope[12] نام دارد. تفاوت روش ++0 با روش TaintScope رویکرد آن است. در ++0 ابتدا در شناسایی توابع مستعد و سپس تست فاز بر روی حافظهی این توابع بهصورت آزادانه سعی خواهیم کرد. درصورتیکه در TaintScope تمرکز بر یافتن checksum[1] ها و تصحیح آنها برای پویش عمق بیشتری از کد است. یکی دیگر از تفاوتهای عمیق این دو ابزار، استفادهی ++0 از روش تست فاز بر روی حافظه است درحالیکه TaintScope از روش اجرای سمبلیک بهره میگیرد.
-3 سیستم ارائه شده
این ابزار، مانند ایدهی ارائه شده در [11]، دارای چهار مرحلهی اصلی است. مرحلهی اول تحلیل ایستا نام دارد که به تحلیل برنامهی اجرایی در حالت ایستا و به دست آوردن پارامترهایی جهت هوشمند سازی تست فاز پرداخته میشود .مرحلهی دوم ردگیری داده ** است که با اجرای برنامه به همراه تحلیل پویا، جهت ردگیری داده و به دست آوردن توابعی که ورودی برنامه در آنها مؤثر است میانجامد.
مرحلهی سوم تست فاز بر روی حافظه نام دارد که وظیفهی تشخیص نوع ورودی آرگومانهای توابع و تست کردن انواع دادهای بهجای آرگومانهای اصلی و باز اجرای توابع در حالت اجرا را بر عهده دارد. مرحلهی چهارم نیز مرحلهی نظارت بر خطا و محاسبهی پوشش کد است که با نظارت بر اجرای برنامه و اعلام خطا در صورت بروز خطا در اجرای برنامه به همراه مستند کردن اطلاعات لازم برای تحلیل نوع خطا و وضعیت ابزار آزمایشگر و نوع ورودی منجر به خطا در برنامه همراه است. این مراحل در بخشهای زیر مورد بررسی قرار گرفته است.
-1-3 تحلیل ایستا
تحلیل ایستا، تحلیل برنامه بدون اجرا کردن آن است.[17] در ++0 به دلیل عدم وابستگی به کد منبع، میبایست برای اجرای تحلیل ایستا با استفاده از تکنیکهای مهندسی معکوس از کدهای اجرایی برنامه به اطلاعاتی پیرامون نحوهی کار برنامه رسید. در این پژوهش، سعی شده است تا در این مرحله، برخی پارامترها برای توابع برنامه محاسبه شود. درنتیجهی این عمل توابعی مستعدتر در داشتن خطا، که مقادیر پارامترهای بهتری دارند برای مراحل بعدی آماده میشود.
-1-1-3 نکاتی پیرامون پیادهسازی مرحلهی تحلیل ایستا
در پیادهسازی تحلیل ایستا، در [11]، از چارچوب BinNavi استفاده شده است. این چارچوب پیاده شده تحت زبان Java است و بر مبنای دادههای تحلیلی توسط چارچوبIDA-Pro کار میکند. BinNavi را میتوان چارچوبای بر روی چارچوب IDA-Pro و در سطح بالاتر دانست که دارای قابلیتهای بیشتری است که این قابلیتها توسط تولیدکنندگان این چارچوب پیادهسازی شده است و سهولت کار با IDA-Pro را بسیار بیشتر مینماید اما با بررسیهای انجامشده و آزمایشهای بهعملآمده، استفاده از این چارچوب بسیار وقتگیر و کند است.
لذا به این نتیجه رسیدیم که با استفاده از همان چارچوب IDA-Pro به تحلیل ایستا بپردازیم و موارد موردنیاز را خودمان پیادهسازی نماییم. تفاوت مدت زمان محاسبهی پیچیدگی دورهای در هر دو رویکرد در جدول 1 ذکر شده است. همچنین کد [11] بهدلیل بهروزشدن چارچوب BinNavi قابل اجرا نبوده و توسط نگارندهی مقاله بازنویسی شد.
-2-1-3 محاسبه پیچیدگی دورهای
در فرآیند محاسبهی پیچیدگی دورهای در ++0 دو قسمت اصلی وجود دارد: اول پیدا کردن توابع از روی قسمتهای مختلف برنامه اجرایی و دوم محاسبهی پیچیدگی دورهای برای هر تابع. در قسمت پیدا کردن توابع از روی قسمتهای مختلف برنامهی اجرایی، با استفاده از امکانات چارچوبIDA، برنامهی اجرایی را ابتدا به تکههای بزرگی از کد اجرایی و سپس آن قطعات را به توابع تقسیم میکنیم. سپس توابع را داخل یک لیست نگهداری میکنیم. در قسمت محاسبهی پیچیدگی دورهای برای هر تابع بلوکهای اصلی داخل هر تابع و روابط جریان اجرایی بین آنها را شمارش میکنیم و پیچیدگی دورهای هر تابع را محاسبه مینماییم.
در مراحل بعد، یعنی ردگیری داده و تست فاز بر روی حافظه به دلیل پویا بودن تحلیل، رسیدن از یک خط کد به ابتدای تابع آن، که اشارهگر به تابع هم نامیده میشود، کاری بیدقت است. و به دلیل آنکه بیشتر کار ما بر روی توابع انجام میگیرد، بیدقتی در تشخیص توابع میتواند ضرر جبرانناپذیری به نتایج کار ما بزند. درنتیجه در قسمت تحلیل ایستا ما این کار را نیز انجام میدهیم.
در قسمت انجام تست فاز، ما نیاز به داشتن تعداد آرگومانهای توابع داریم. این کار در این قسمت نیز بهسادگی و با دقت بالا نیست، اما با آزمایشهای انجامشده تحلیل ایستا نتایج بهتری را نسبت به تحلیل پویا به بار آورد. زیرا در حالت اجرا، امکان یافتن تعداد آرگومانها بهسادگی و با دقت میسر نیست. در برخی از کارهای گذشته پیرامون تست فاز بر روی حافظه دیده شده است که در زمان صداشدن تابع رجیسترهایی را که امکان وجود آرگومانها در آن است بهصورت تصادفی تغییر داده میشود. این راهکار آنقدر دارای خطا است که به نظر نمیرسد نیازی به مقایسه باشد.
در ضمن باید یادآور شد که در حالت پویا امکان تشخیص دادن تعداد بیشتر آرگومانها نسبت به حالت واقعی نیز وجود دارد که در حالت ایستا امکانپذیر نیست. این مسئله بسیار خطرناک است. یعنی در صورت محاسبه کردن بیشتر تعداد آرگومانها، امکان تغییر آدرسهای دیگر که باعث خراب شدن نحوهی کار برنامه میشود، وجود دارد ولی در صورت کمتر محاسبه کردن تعداد آرگومانهای توابع تنها برخی آرگومانهای آن تابع فاز نمیشوند.
-2-3 ردگیری دادهها
ردگیری دادهها تکنیکی است برای به دست آوردن جریان داده در برنامه. ورود این مبحث به دنیای تست نرمافزار به دلیل یافتن و تحلیل مشکل در نرمافزار آسیبدیده بوده است. در آن روش با داشتن ورودی مشکلساز و با استفاده از این تکنیک، تحلیلگر با ردگیری دادهی مشکلساز، تشخیص میدهد که در صورت تغییر کدام قسمت از آن ورودی، میتواند از برنامه سوءاستفاده شود یا اینکه خطای پیداشده نمیتواند توسط ورودی کنترل شود و قابلیت سوءاستفاده ندارد.[14] استفاده از این تکنیک در ++0 متفاوت از موارد شناختهشده است.