Dutchman Daily
907 subscribers
114 photos
16 videos
18 files
133 links
The other side of me
This is me:
@its_dutchman
Download Telegram
من کلا یک مقدار از نیازمندیم بگم،‌ اینشکلیه که ما یک سری patch داریم که حدس میزنیم اینا آسیب‌پذیرن. اما خب برای اینکه مطمئن شیم هستن یا نه نیاز هست که exploit شن. این exploit کردنشون کار خیلی ساده‌ای نیست چون هم پروژه‌ها گنده‌ن و هم کلا exploit کردن یک پروژه بزرگ خیلی سخته، لذا در نهایت می‌خوایم اونایی رو exploit کنیم که مطمئنیم آسیب‌پذیرن. حالا برای اینکه بفهمیم آسیب‌پذیرن یا نه، می‌خوایم از یک فازر استفاده کنیم که اگر اونجا توی اون نقطه از diff که ما حدس زدیم آسیب‌پذیره، اون پروژه کرش کرد، حالا ما دیگه شروع کنیم به اکسپلویت کردنش.

برای این کار نیاز به یک فازری داریم که دقیقا اون نقطه‌ای که ما مد نظرمون هست رو فاز کنه برامون. حالا فازرها کلا نوع‌های مختلفی دارن و ما به عبارتی فازری می‌خوایم که به اون نقطه برسه (یعنی مطمئن باشیم که اون نقطه و یا در واقع اون node از گراف‌مون داره cover میشه)

این aflgo یک فازریه که کدبیسش همون afl معروفه اما می‌تونه به صورت directed اون جایی که ما خودمون نیاز داریم رو هم فاز کنه.

به عبارتی این توی دیسکپریشن خودشه:
AFLGo is an extension of American Fuzzy Lop (AFL). Given a set of target locations (e.g., folder/file.c:582), AFLGo generates inputs specifically with the objective to exercise these target locations.



درکل فازر جالبیه ولی کار باهاش خیلی سخته. نه داکیومنت درستی داره نه هیچی.
این ریپوشونه:
https://github.com/aflgo/aflgo

اینم مقاله‌شون:
https://mboehme.github.io/paper/CCS17.pdf
🔥6👎1
اون آسیب‌پذیری محتمل هم که دنبالشم اینجاس:
https://github.com/libgd/libgd/blob/master/src/gd_tga.c
خط ۲۵۷

در کل این تابع gdGetBuf آسیب‌پذیره و زیاد هم ازش ریپورت شده مخصوصا برای این پروژه libgd.

آسیب‌پذیری‌هاشم خیلی احمقانه‌س اتفاقا، یعنی کل آسیب‌پذیری‌هایی که از این تابع خوندم من دلیلش برمی‌گرده به این که اینا نیومدن return value این تابع رو چک بکنن. یعنی اگر صرفا توی یک if بذارن هندل میشه ماجرا.

یک سری آسیب‌پذیری دیگه‌هم داره البته که اگر دوست داشتید می‌تونید برید بخونید توی cve mitre
🔥5👍1👎1
یک چلنج فوق‌ العادههههههههه زیبا. (بینهایت هم gdb یاد می‌گیرید با حلش.) فردا توضیحش میدم چجوری حل میشه. شوخوش.
8👎1
خب برسیم به توضیح این سوال. کد پایتونش رو اگر ببینید، اومده یک لایبرری ایمپورت کرده به اسم gdb.
خب حالا gdb چیه؟gdb یا به عبارتی GNU Debugger یک دیباگری هست که برای زبون‌های سطح پایینی مثل اسمبلی و c و cpp و اینا‌ها هست. می‌دونم که بعضا go یا جاوا هم حتی باهاش دیباگ می‌کنن. کلا یک ابزار خیلی خفنیه که روی سیستم‌های یونیکسی میتونه اجرا شه و یک باینری رو دیباگ کنه.

همه کار هم میشه باهاش کرد. از ساده‌ترین چیزا مثل بریک‌پوینت گذاشتن و رفتن به دستور بعدی و در همون لحظه دیدن مقادیر متغیرا، ورودی‌های تابع‌ها، مقادیر رجیسترها، استک، هیپ و ... هرچی که فکرشو کنید.

تا یک سری کارای خفن‌تر، مثلا در لحظه (runtime) عوض کردن مقادیر. مثلا ورودی یک تابع اگر هست ۲ اون رو تغییر بدید به ۵. یا در لحظه اگر روی خط ۵ برنامه هستید جامپ کنید برید به خط ۱۰.

کلا تقریبا هرکاریییی که دلتون بخواد با این دیباگر با اون برنامه می‌تونید انجام بدید
👍41👎1
برای حل این سوال حقیقتا یک دانش پایه‌ای از c اگر داشته باشید و با gdb مقداری کار کرده باشید و یک مقدار خیلی کوچک و ریزی هم os بلد باشید (نباشید هم با سرچ در میاد) کار تمومه
👍41👎1
در نهایت مثل باقی سوالا، هدف پیدا کردن فلگ هست.
👍41👎1
اگر کد پایتون رو نگاه کنید، داره چکار میکنه؟ داره
/bin/cat

رو اجرا می‌کنه. بیایید یکم دیپ‌تر شیم که با این کار دقیقا چه اتفاقی میوفته.

دستور cat یک کامند هست که شما باهاش می‌تونید محتوای یک فایل رو بخونید. مثلا cat flag.txt میاد محتوایی که توی فایل flag.txt هست رو براتون چاپ میکنه.

اما خود دستور cat خالی رو اگر بزنید چی میشه؟ اگر دستور cat خالی رو بزنید، هر ورودی‌ای که بهش بدید،‌همونو بهتون خروجی میده. به عبارتی میاد هرچی از stdin هست رو میگیره و میریزه تو stdout
یه نمونه‌ش رو پایین بهتون نشون میدم.
👍51👎1
اینجا من وقتی cat رو زدم، بعدش منتظر ورودی میمونه. من نوشتم hello و همون رو مجدد خروجی داد. من نوشتن dutchman و همون رو مجدد خروجی داد.
👍51👎1
خب بذارید یکم بیشتر باهاش ور بریم. زمانی که دستور cat صدا زده میشه، چه توابعی از libc کال میشن؟ منطقا اگر خیلی ابسترکت نگاه کنیم، باید بیاد اون فایل رو open کنه، read کنه و در نهایت write می‌کنه که ما بتونیم خروجی رو ببینیم. حالا یک دستور trace روی این cat می‌زنیم تا ببینیم واقعا چه توابعی از libc دارن صدا زده می‌شن.
من برای تست یک فایل می‌نویسم به اسم flag که توی اون فایل محتواش رو می‌نویسم hello
👍41👎1🔥1
اگر ببینید واقعا همین اتفاق داره میوفته. یعنی داره open رو صدا میزنه بعد read رو صدا میزنه و بعد write رو
👍31👎1🔥1
بیایید یکم دیپ‌تر شیم باز.
زمانی که دستور open صدا زده میشه، میاد اون فایل رو باز می‌کنه و یک فایل‌دیسکریپتور براش میسازه و الان یک فایل‌دیسکریپتور داریم که یک عددی داره (۰ مال stdin هست و ۱ ماه stdout و ۲ مال stderr) پس زمانی که میخواد flag رو open کنه شماره‌ی فایل‌دیسکریپتور بعدی، میشه ۳. یعنی زمانی که فایل flag رو open کردیم و لینک کردیم به فایل‌دیسکریپتور ۳، حالا تابع read از فایل‌دیسکریپتور ۳ میره شروع میکنه به خوندن و در نهایت هم میره writeش میکنه.
👍31👎1🔥1
اما زمانی که ما دستور cat خالی بزنیم، همونجور که دیدیم، همون چیزی که ما بهش دادیم رو میره پرینت میکنه. دیدید که گفتیم دقیقا همونی که میخونه رو میره مینویسه دوباره. یعنی اگر دقت کنید، زمانی که اون read داره صدا زده میشه، فایل‌دیسکریپتوری که بهش پاس داده میشه، فایل‌دیسکپریتور 0 یا همون stdin هست. ولی خب این به کار ما نمیاد که. ما می‌خوایم اون فایل‌دیسکریپتوری که به فلگ میرسه رو بره بخونه و read کنه و مجدد write کنه. حالا پس باید چکار کنیم؟ اینجاس که دیگه چلنج تازه شروع میشه و ما نیاز داریم به gdb که بتونیم یک سری مقادیر رو عوض بکنیم در لحظه که بتونیم اون چیزی نیاز داریم رو پرینت کنیم دقیقا.
👍31👎1🔥1
اون پایتونه داره چکار میکنه؟ میاد gdb رو ران میکنه. دستور cat خالی رو اجرا می‌کنه و سر تابع read یک break point میذاره. البته چلنجش یک مقدار سخته. یعنی گفته شما هر دستوری نمی‌تونید بزنید و صرفا دستور break و set و continue رو می‌تونید صدا بزنید. چلنجش اینجوری محدود شده خلاصه.

break
که میاد یک آدرس می‌گیره و روی اون چیزی که می‌خوایم break point میذاره.

continue
میاد ادامه میده تا برسه سر break point بعدی و ایست کنه.

set
جلوش یه سری چیز میاد که یه سری مقادیر رو ست کنه. مثلا
set $rax=0x0
یعنی توی رجیستر rax بریز ۰
👍3👎21
خب یکم بریم وارد gdb شیم.
👍31👎1
اینجا من اومدم gdb زدم روی catخالی (من اکستنشن gef هم دارم واسه همین با gdb یک مقدار فرق داره چیزی که می‌بینید.)
👍2👎21
من یک break point روی read هم گذاشتم. تابع read رو که ببینید. fd یا همون فایل‌دیسکریپتورش همونجوری که گفتیم 0هست. یعنی stdin. یک بافری هم داره که آدرسش هست 0x7ffff7f88000 که مقداری که خوند رو بریزه توی این آدرسه.
💩3👍21
چلنح در واقع از همینجا شروع میشه و حدودا دیشب ۳ ۴ ساعت وقت گرفت از من. لذا من دیگه از اینجا تخصصی‌تر و خلاصه‌تر میگم که نخوام ۴۰۰تا پیام بدم دیگه.
2👍2💩2
کاری که باید برای حلش کرد چیه؟ ما در نهایت باید کاری کنیم که به جای اینکه این cat خالی صرفا همون ورودی‌ای که ما میدیم خروجی بده، بیاد محتوای فایل مدنظر ما که اسمش هست flag.txt رو چاپ کنه.

پس ما باید یه سری کار کنیم. اینکه بریم فایل flag.txt رو open کنیم تا fdش ساخته شه و لینک شه تا ما بتونیم readش کنیم چرا که read از روی یک fd اتفاق میوفته.

بعد که read کردیم بیاییم بریزیمش توی یک مقداری که همون مقدار بافر خودش کافی هست، و حالا write رو صدا بزنیم که بره مقداری که از read داره رو برامون write کنه.
👍2💩21
تابع open یک ورودی می‌گیره که اونم اسم فایل هست و مقدار توی rdi ریخته میشه. یعنی ما زمانی که می‌خوایم open رو صدا بزنیم باید مقدار rdi مون برابر با اسم فایلی باشه که می‌خوایم openش کنیم. یعنی همون flag.txt.
2💩2👍1
خب حالا ما چجوری این مقدار رو بگیریم و بریزیم توی rdi؟ همونطور که گفتیم، این cat خالی میاد ورودی مارو خروجی میده. پس اگر یه دور ما cat خالی رو صدا بزنیم و بدیم flag.txt، این میره توی بافرش می‌نویسه flag.txt و تنها کاری که ما نیازه بکنیم اینه که آدرس اون flag.txt رو بیاییم بریزیم توی rdi و سپس open رو صدا بزنیم که بره فایل flag.txt رو برامون open کنه و fdشو بسازه.
2💩2👍1