به نام خدا
در این مجموعه از پست ها قراره که CTF جدیدی که شرکت امنیتی Flare همین هفته پیش برگزار کرد رو خدمت دوستان مرحله به مرحله حل کنیم.
این دوره از مسابقات که به صورت آنلاین سالانه برگزار میشه جزو معتبرترین مسابقات در حوزه مهندسی معکوس و تحلیل بدافزار هست.
هدف من از این کار اینه که دوستانی که علاقه به مباحث مهندسی معکوس و تحلیل بدافزار دارند، بتونند مرحله به مرحله با ابزارها و تکنیک های این حوزه آشنا بشن و مقدمه ای باشه برای ورود به مباحث پیشرفته تر. قطعا شما نمیتونید با به اتمام رسوندن این CTF به یک تحلیل گر بدافزار تبدیل بشید ولی بهترین نقطه شروع شما به نظر من همینجاست که میتونه شما رو از آسون ترین مباحث به حرفه ای ترین مباحث منتقل کنه و یک دید کلی و خوبی بهتون بده.
قبل از شروع چندتا نکته وجود داره در مورد این پست:
این پست برای کسانی نوشته میشه که علاقه دارند تو حوزه های تحلیل بدافزار، آنالیز فایلهای باینری، مهندسی معکوس و دیباگ کردن کرنل ویندوز فعالیت داشته باشند.
پیش نیازهای مورد نظر برای درک و فهم این پست ها:
برای اینکه علاقه مندان این حوزه بتونند مباحثی که گفته میشه رو درک کنند، نیاز هست که دوستان در ابتدا با زبان شیرین اسمبلی آشنایی کافی رو داشته باشند. در ادامه نیاز هست که دوستان با زبان های برنامه نویسی C/C++ ، پایتون نیز به خوبی کار کرده باشند و حداقل درکی از این زبان ها داشته باشند. چونکه بعضی جاها ممکنه نیاز بشه که ما برای حل یک چالش کد بنویسیم.
آشنایی با سیستم عامل ویندوز، فرآیند کارکرد حافظه رم، و آشنایی با دیباگر و دیس اسمبلرها از پیش نیازهای دیگه این دوره هست که البته من سعی کردم تا حد خوبی توی این پست ها این مطالب رو هم به صورت کلی مرور کنم.
این CTF شامل 12 مرحله هست که از آسان شروع میشه و در آخرین مرحله یعنی مرحله 12 به اوج سختی خودش میرسه که مباحث دیباگ کرنل، درایور، بررسی ترافیک شبکه برای پیدا کردن بدافزار و … رو شامل میشه. پس خودتونو آماده کنید برای یه چالش سخت و نفس گیر که کلی اطلاعات به علم شما اضافه میکنه.
در این پست ها بنده سعی میکنم که همه مطالب رو از پایه توضیح بدم که دوستانی که اطلاعات پایه مناسبی دارند تو این حوزه بتونن مطالب رو درک کنند.
قبل از هر چالش نیاز به یک سری ابزار هست، که من تو پیش نیازهای هر کدوم از مراحل اینارو میزارم و یه توضیح مختصری در مورد هرکدوم میدم.
با توجه به کمبود زمان، طبق برنامه ریزی که من کردم احتمالا بتونم هر هفته دوتا چالش رو حل کنم و اینجا راه حلشو بنویسم.
پسورد تمام فایلهای زیپ flare هست.
در آخر توصیه میکنم که تمامی مراحل این CTF رو بر روی ویندوز اصلی یا Host اجرا کنید، چونکه ممکنه بعضی از فایلها از تکنیک های Anti VM استفاده کنند که در صورت اجرا در ماشین مجازی روند کار رو برای شما مختل کنند. اصلا هم نیاز نیس احساس خطر بکنید چون هیچ چیز خطرناکی ویندوز شما رو تهدید نمیکنه.
چالش شماره 1 : Memecat Battlestation
فایلهای مربوط به این چالش
لینک دانلود
پیش نیازها:
ویندوز 7 یا بالاتر −
نرم افزار dnSpy −
آشنایی با زبان برنامه نویسی C# −
خب شما یک فایل زیپ دارید که داخلش دوتا فایل هست یه فایل exe که هدف اصلی سوال هست و یک فایل Message که اطلاعاتی در مورد چالش به ما میده.
در ابتدا وقتی فایل Message رو باز میکنیم به ما گفته شده که این مساله خیلی راحته و شما باید بتونی با دوتا دشمن که توی این برنامه به شما حمله میکنن بجنگی و اونارو از بین ببرید. البته شاید خنده دار به نظر برسه این چالش ولی همیشه توی اکثر CTF ها سعی میشه که اولین چالش رو یه مقدار Fun بسازند و خیلی آسون که خب اینجا هم همینو داریم.
وقتی شما فایل exe رو باز میکنید یه انیمیشن براتون نمایش داده میشه که یه گربه ای ثابت هست و یه گربه دیگه با دهن باز به سمت این یکی حمله میکنه. و در پایین صفحه شما یه textbox و یک Button میبینید. با توجه به چیزی که توی راهنما گفته شده، شما باید یک کلمه رو داخل این textbox وارد کنید که بتونید اون گربه وحشی رو از بین ببرید. پس الان قطعا متوجه شدید که هدف پیدا کردن یک رمز هست و وارد کردن اون و رفتن به مرحله بعد.
طبق توضیحاتی که توی فایل راهنما داده شده، این فایل exe با زبان .net نوشته شده. برای اینکه ما بتونیم رمز مرحله رو پیدا کنیم و گربه وحشی رو از بین ببریم نیاز هست که این فایل exe رو reverse کنیم و اون رمز رو پیدا کنیم. در اینجا نیاز هست که من توضیحاتی در مورد نحوه reverse کردن فایلهای .net خدمتتون بگم:
زبان های برنامه نویسی مفسری، مانند .net ( C#,VB,F#) و یا java به صورتی اجرا میشن که ابتدا کدی که برنامه نویس مینویسه تبدیل میشه به یک زبان میانی و سپس یه ماشین مفسر یا همون interpreter میاد و اون زبان میانی رو تبدیل میکنه به زبان ماشین و اجرا میکنه. این به معنی هست که وقتی شما یه برنامه با زبان مثلا C# مینویسید، این برنامه به تنهایی قادر به اجرا شدن نیست و مفسر اون یعنی .net framework باید روی سیستم موجود باشه. Reverse کردن این برنامه ها به شدت آسون تر و راحت تر از برنامه هایی هست که با زبان های Native یا کامپایلری نوشته میشن چونکه زمانی که شما یه برنامه با زبان C/C++ مینویسید، این برنامه توسط کامپایلر مستقیم به زبان ماشین تبدیل میشه و بنابراین برای reverse کردن اینها باید زمان زیادی گذاشت تا بتونیم از زبان ماشین تبدیلشون کنیم به زبان اسمبلی و در نهایت ما باید از روی زبان اسمبلی تولید شده رفتار برنامه رو بررسی کنیم. اما reverse کردن برنامه های مفسری بسیار ساده تر هست چونکه قراره که کد میانی تولید شده تبدیل بشه به زبان برنامه نویسی که این کار به مراتب ساده تر هست.
حالا با توجه به توضیحاتی که دادم، الان برنامه ای که باهاش مواجه هستیم از نوع مفسری به زبان .net نوشته شده که خب به راحتی میتونیم کدش رو استخراج کنیم و بررسی کنیم.
برای reverse کردن فایلهای .net بهترین ابزاری که میتونم معرفی کنم و به شدت کارآمد هست، ابزار dnSpy هست که میتونید آخرین نسخه اونو از ادرس گیتش بگیرید.
خب بعد از اینکه نرم افزار dnspy رو باز کردیم فایل exe رو داخلش drag and drop میکنیم و نرم افزار dnspy شروع میکنه برای ما decompile کردن.
در سمت چپ شما میتونید تمام فرم ها و Object های برنامه رو به صورت مجزا ببینید.
خب بعد از این ما برا اینکه بتونیم نقطه شروع برنامه یا همون entryPoint رو پیدا کنیم، روی پروژه کلیک راست میکنیم و گزینه Go to EntryPoint رو میزنیم و ما میبینیم که کد مربوط به تابع main به ما نشون داده میشه. با توجه به اینکه ما باید یه متن رو داخل textbox وارد کنیم و بعد از اون دکمه fire رو بزنیم تا کد وارد شده بررسی بشه، پس میشه فهمید که ما باید ببینیم که بعد از کلیک کردن روی دکمه fire چه اتفاقی میافته و چه کدی اجرا میشه تا بتونیم بفهمیم رمز چی هست. پس من برای اینکه بتونم کد مربوط به دکمه fire رو پیدا کنم، از توی صفحه سمت چپ دنبال یه object میگردم که فرایند Click کردن رو داشته باشه
همونطور که تو عکس مشخصه، تابع مربوط به فرایند کلیک کردن، دکمه fire پیدا شد. کافیه روش کلیک کنیم تا کدش به ما نشون داده بشه.
خب اینجا دیگه کاملا جواب مثه روز روشنه. همونجور که توی کد میبینید، محتویات TextBox با عبارت RAINBOW مقایسه شده و ادامه کار انجام شده. پس ما متوجه میشیم که رمز RAINBOW هست. برنامه رو باز میکنیم و این رمز رو داخل TextBox میزنیم. خب میبینید که گربه اول با سلاح رنگین کمان گربه وحشی رو داغون کرد.
ولی اینجا میبینیم که یه گربه سیاه تازه وارد شد. این دشمن دوم هست. پس هنوز این مرحله تموم نشده و باید گربه دوم رو هم از بین برد بازم با یه رمز، ولی این بار این گربه سخت جون تره و با رنگین کمان از بین نمیره.
خب اگه دقت کنیم، متوجه میشیم که توی لیست فرم هایی که dnspy برامون لیست کرده، 2 تا فرم موجوده، و زیرمنوی هر فرم یه دونه دکمه fire داریم. پس ما دوتا فرم داریم که فرم اول اون گربه وحشی حمله میکنه و در فرم دوم که الان باهاش مواجه هستیم، گربه سیاه حمله میکنه. بنابراین برای پیدا کردن رمز کشتن این گربه، باید Event مربوط به کلیک دکمه fire رو توی فرم 2 بررسی کنیم.
خب همونطور که توی عکس مشخصه، میبینیم که مثل دکمه مرحله قبل این هم یه کد داره که محتوای TextBox رو بررسی میکنه، ولی این بار دیگه یه کلمه معمولی نیست و میبینیم که محتویات داخل TextBox به عنوان ورودی به تابع isValidWeaponCode ارسال شده و اگر این رمز معتبر باشه توسط این تابع مقدار true برگشت داده میشه. پس برای فهمیدن رمز باید وارد تابع بشیم و کد تابع رو بررسی کنیم.
private bool isValidWeaponCode(string s)
{
char[] array = s.ToCharArray();
int length = s.Length;
for (int i = 0; i < length; i++)
{
char[] array2 = array;
int num = i;
array2[num] ^= ‘A’;
}
return array.SequenceEqual(new char[] { ‘\u0003′,’ ‘,’&’,’$’,”,’\u001e’,\u0002′,’ ‘,’/’,’/’,’.’,’/’});
}
خب اینجا میبینیم که مقدار ورودی تابع که یه رشته هست وارد یه حلقه شده و با مقدار A عملیات XOR شده و سپس با اون مقدار رشته ای که در انتهای تابع اومده مقایسه میشه و اگر برابر با این مقدار بود ، true برگشت داده میشه. اینجا نیاز هست که یه مقدار رمزنگاری یاد بگیریم .
یکی از متدهای ساده رمزنگاری، عملیات XOR هست. به این صورت هست اگر به صورت منطقی اگر یک مقدار باینری یا همون دودویی رو با 0 یا 1 XOR کنیم، جدول زیر رو خواهیم داشت.
خب به صورت کلی اگه بخوام یه مثال ساده و واضح از XOR بگم اینجوریه که اگه شما یه رشته رو با یه کلید XOR کنی و جواب رو دوباره با همون کلید، XOR کنید میرسید به رشته اصلی:
مثال:
1100 XOR 1111 = 0011 <---- result
در اینجا کلید ما 1111 هست و رشته مورد نظر برای رمزنگاری 1100 هست و جواب 0011 هست.
حالا کافیه ما رشته حاصل رو که همون 1100 هست رو با کلید که 1111 دوباره XOR کنیم تا به رشته اصلی برسیم:
0011 XOR 1111 = 1100 <--- plaintext
خب برگردیم به مساله خودمون. ما الان رشته ای که داخل TextBox بوده رو میبینیم که با کارکتر A، XOR شده، پس اینجا A در واقع کلید ما هست. و نتیجه این عملیات با اون رشته مورد نظر برنامه مقایسه میشه. پس میتونیم با Xor کردن اون رشته با A به اون رمزی برسیم که باید وارد کنیم.
رشته جواب :
یه نکته ای اینجا هست که باید بگم اونم اینکه بعضی وقتا dnspy توی تشخیص رشته ها، اشتباه میکنه. اینجا ما میبینیم که رشته زیر رو برا ما بعضی از کارکترهاشو به صورت یونیکد نمایش داده ولی در حقیقت اینها مقادیر HEX یه که البته مشکل خاصی هم پیش نمیاد ولی ما باید حواسمون باشه که، اینها رو اول تبدیل کنیم به کد Hex Ascii بعد عملیات XOR رو انجام بدیم. خب من یه سایت معرفی میکنم که انواع coding ها رو برای شما تبدیل میکنه به هم.
من اینجا توی این جدول مقادیر Hex اون کارکترهای اسکی رو براتون نوشتم ولی توصیه میکنم خودتون حتما اینارو از جدول اسکی پیدا کنید
Hex value | Char |
03 | \u0003 |
20 | ‘ ‘ or space |
26 | & |
24 | $ |
2d | – |
1e | 1e |
02 | 02 |
20 | ‘ ‘ or space |
2f | / |
2f | / |
2e | . |
2f | / |
2f | 2e | 2f | 2f | 20 | 02 | 1e | 2d | 24 | 26 | 20 | 03 | Hex |
/ | . | / | / | space | 02 | 1e | – | $ | & | space | 03 | Char |
وارد این سایت میشیم و کلید رو A میزاریم و تمام اون کارکترهای رشته جواب رو به صورت Hex وارد میکنیم.
همونطور که میبینید رشته رمزگشایی شده مشاهده میشه و با وارد کردن این رشته داخل TextBox دوم، گربه سیاه رو هم شکست میدیم و فلگ یا همون پرچم ورود به مرحله بعد رو برنامه به ما نشون میده.
خب شاید یه کم این چالش خنده دار باشه ولی هدف این چالش اینه که نحوه تحلیل کردن و Reverse کردن برنامه های .net رو بتونه به صورت کلی نشون بده، که به نظر من خیلی ایده جالبی بوده.