اگه علاقمند به آنالیز بدافزار در حوزه ی محصولات اپل باشید، احتمالا زنجیره حمله ی معروف Triangulation رو شنیدید. این حمله شبکه داخلی کسپرسکی رو هدف قرار داده بود و علاوه بر تارگت و مباحث پیچیده حمله، با ادعای FSB روسیه که اپل زیرودی در اختیار مهاجمین قرار میده، خیلی سروصدا داشت.
اپل این آسیب پذیری هارو در بروزرسانی های ، 31 خرداد، 20 تیر و 2 مرداد اصلاح کرد.
در این پست به گزارش محققین کسپرسکی در خصوص کلیات این زنجیره و شرح آسیب پذیری CVE-2023-38606 پرداختیم. این گزارش بخشی از ارائه ی اونا در 37امین رویداد Chaos Communication Congress (37C3) هستش. ویدیوی این ارائه رو میتونید با عنوان ” Operation Triangulation: What You Get When Attack iPhones of Researchers ” در سایتشون مشاهده کنید. ویدیوهای دیگه این رویداد رو هم میتونید از اینجا مشاهده کنید.
این اولین ارائه ای هستش که در اون جزییات کامل آسیب پذیری ها و اکسپلویتهای این حمله بصورت عمومی منتشر میشه. محققا گفتن که روزانه با حملات و اکسپلویتهای مختلفی روبرو هستن و بیش از 30 زیرودی در محصولات گوگل ، اپل ، مایکروسافت و Adobe کشف و گزارش کردن، اما این قطعا پیچیده ترین زنجیره حمله ای بوده که کشف کردن.
زنجیره حمله ی Operation Triangulation :
اینجا خلاصه ای از این حمله ی زیروکلیک iMessage ، که از 4 آسیب پذیری زیرودی تشکیل شده بود و تا iOS 16.2 رو تحت تاثیر قرار میداد رو داریم:
- مهاجم یه پیوست مخرب iMessage به قربانی ارسال میکنه و برنامه بدون نمایش چیزی به کاربر ، اونو پردازش میکنه.
- این پیوست از یه آسیب پذیری اجرای کد از راه دور ، به شناسه CVE-2023-41990 در دستورالعمل فونت بدون مستند و مختص اپل ، TrueType استفاده میکنه. این دستور از اوایل دهه 90 ، قبل از اینکه توسط یه اصلاحیه ای حذف بشه، وجود داشته.
- از return/jump oriented programming و در چندین مرحله که در NSExpression/NSPredicate query language نوشته شده ، استفاده میکنه و محیط کتابخونه ی JavaScriptCore رو دستکاری میکنه تا بتونه یه اکسپلویت افزایش امتیاز توسعه داده شده در جاوااسکریپت رو اجرا کنه.
- این اکسپلویت جاوااسکریت مبهم شده تا، قابل خوندن نباشه و همچنین سایزش هم کم بشه. با این حال حدود 11هزار خط کد هستش، که عمدتا برای JavaScriptCore و تجزیه و دستکاری حافظه کرنل اختصاص داره.
- از ویژگی دیباگینگ JavaScriptCore یعنی DollarVM ($vm) ، برای دستکاری حافظه ی JavaScriptCore و اجرای توابع native API سوء استفاده میکنه.
- مدلهای جدید و قدیم آیفون رو پشتیبانی میکنه و برای اکسپلویت مدلهای اخیر ، امکان دور زدن Pointer Authentication Code (PAC) رو هم داره.
- از آسیب پذیری integer overflow و به شناسه CVE-2023-32434 در XNU memory mapping syscalls (mach_make_memory_entry and vm_map) برای دسترسی خواندن/نوشتن به کل حافظه ی فیزیکی دستگاه در سطح کاربر سوء استفاده میکنه.
- از رجیسترهای سخت افزاری MMIO برای دور زدن Page Protection Layer (PPL) سوء استفاده میکنه. برای این مورد اپل شناسه ی CVE-2023-38606 رو اختصاص داده.
- بعد از اکسپلویت همه ی آسیب پذیری ها ، مهاجم میتونه هر کاری بکنه از جمله اجرای یه جاسوس افزار ، اما مهاجم تصمیم گرفته کارهایه زیر ور انجام بده :
- پروسس IMAgent رو اجرا کرده و یه پیلودی رو توش تزریق کرده که شواهد اکسپلویت شدن رو پاک میکنه.
- پروسس Safari رو بصورت مخفی اجرا میکنه و از یه صفحه ی وبی که مرحله ی بعدی حمله هست، بازدید میکنه.
- صفحه ی وب بعد از تایید قربانی، یسری موارد رو بررسی میکنه و مرحله ی بعدی حمله که اکسپلویت Safari هست رو ارائه میده.
- این اکسپلویت از آسیب پذیری شناسه ی CVE-2023-32435 برای اجرای یه شلکد استفاده میکنه.
- خود شلکد یه اکسپلویت کرنلی رو در قالب فایل Mach اجرا میکنه. برای اینکار هم از همون آسیب پذیری های CVE-2023-32434 و CVE-2023-38606 استفاده میکنه . از نظر اندازه و عملکرد بزرگتره و با اکسپلویت کرنلی نوشته شده در جاوااسکریپت کاملا متفاوت هست. یه بخشی از کدها برای اکسپلویت این دو آسیب پذیری هستن اما بخش زیادیش برای دستکاری حافظه ی کرنل اختصاص داره. شامل سه ابزار post-exploit که عمدتا بدون استفاده هستن.
- این اکسپلویت امتیاز Root رو میگیره و مراحل بعدی حمله که لوود جاسوس افزار هست رو اجرا میکنه. جزییات این مراحل رو میتونید اینجا ببینید.
محققا اعلام کردن که مهندسی معکوس همه ی زنجیره های این حمله رو تموم کردن و در سال 2024 ، جزییاتی از آسیب پذیری ها و نحوه ی اکسپلویت اونا منتشر میکنن.
بررسی آسیب پذیری CVE-2023-38606 :
مدلهای اخیر آیفون، دارای یه مکانیسم امنیتی بیشتر و مبتنی بر سخت افزار، برای مناطق حساس حافظه ی کرنل هستن. این مکانیسم امنیتی باعث میشه، اگه مهاجم بتونه دسترسی خوندن و نوشتن به حافظه ی کرنل رو هم داشته باشه، نتونه کنترل کامل دستگاه رو بدست بیاره. چیزی که در این زنجیره توسط آسیب پذیری CVE-2023-32434 ، اکسپلویت شده. نکته جالب ماجرا اینه که ، مهاجمین برای دور زدن این ویژگی امنیتی مبتنی بر سخت افزار ، از یه ویژگی سخت افزاری دیگه ،طراحی شده توسط اپل بنام System-On-Chip (SoC) سوء استفاده میکنن.
نحوه ی اکسپلویت این آسیب پذیری بطور خلاصه اینجوریه که ، مهاجم امکان نوشتن داده ها در یه آدرس فیزیکی خاص داره، با این نوشتن داده ها ، آدرس مقصد و هش داده ها در رجیسترهای سخت افزاری ناشناخته که توسط فریمور هم استفاده نمیشه، تونستن این مکانیسم امنیتی مبتنی بر سخت افزار رو دور بزنن.
محققا حدس میزنن که این ویژگی سخت افزاری ناشناخته، به احتمال زیاد برای اهداف دیباگ و یا تست محصول و توسط مهندسین اپل یا کارخونه مورد استفاده قرار میگیره یا کلا به اشتباه ارائه شده. نکته جالبتر اینکه ، اگه این ویژگی توست فریمور استفاده نمیشه، پس مهاجم ها چطوری تونستن بفهمن که این ویژگی چطوری کار میکنه ؟!
محققا اعلام کردن که هدف از نشر این گزارشها، اینه که بقیه ی محقیین iOS هم یافته هاشون رو تایید کنن و توضیحات احتمالی در خصوص اینکه مهاجمین از کجا تونستن به جزییاتی از این ویژگی امنیتی برسن، ارائه بدن.
آنالیز فنی :
system-on-chip (SoC)ها یه تراشه هایی هستن که، اغلب یا همه ی اجزای رایانه یا سیستم الکترونیکی رو ، با هم ادغام میکنن. همیشه دارای CPU ، رابط حافظه ، رابط و دستگاههای I/O و رابط حافظه های جانبی هستن. SoCها در تضاد با معماری مادربردن که در اونا ،همه اجزاء براساس عملکرد از هم جدا میشن و از طریق یه مدار رابط مرکزی به هم متصل میشن. یه SoC معمولاً یه CPU، رابطهای گرافیکی و حافظه، حافظه جانبی و اتصالات USB، رابطهای I/O رو ،روی یه تراشه ادغام میکنه، در حالی که مادربرد این ماژولها رو بعنوان اجزای مجزا یا کارتهای توسعه (expansion cards) ارائه میده.
دستگاههای جانبی قابل دسترس در SoC، ممکنه رجیسترهای سخت افزاری خاصی رو ارائه بده ، که امکان استفاده توسط CPU ، برای کار با این دستگاهها رو بده. برای انجام این کار ، این رجیسترهای سخت افزاری به حافظه ی قابل دسترس توسط CPU نگاشت میشن و با عنوان memory-mapped I/O (MMIO) شناخته میشن.
محدوده آدرس برای دستگاههای جانبی در محصولات اپل (آیفون ، مک و … ) در فرمت های فایل خاصی بنام DeviceTree ذخیره میشن. این فایلهای Device tree رو میشه از فریمور استخراج و با ابزار dt ، میشه محتوای اونا رو مشاهده کرد. شکل زیر یه نمونه از نحوه ی ذخیره ی MMIO در DeviceTree رو نشون میده .
برای مثال در تصویر بالا ، محدوده شروع (0x210f00000) ، سایز محدوده acc-impl MMIO (0x50000) ، برای cpu0 رو مشاهده کنید.
محققا موقع آنالیز اکسپلویت Operation Triangulation ، متوجه شدن که اغلب MMIOهایی که توسط مهاجم برای دور زدن مکانیسم امنیتی مبتنی بر سخت افزار حافظه کرنل استفاده شده، به هیچ محدوده MMIO تعریف شده در devicetree تعلق نداره. اکسپلویت، SoCهای Apple A12–A16 Bionic و بلوکهای ناشناخته ای از MMIO های رجیسترهایی که در آدرسهای 0x206040000, 0x206140000, 0x206150000 قرار دارن رو هدف قرار میده.
محقق اومده موارد زیر رو بررسی کرده تا بتونه یه رفرنس به این آدرسها پیدا کنه ، اما چیزی پیدا نکرده.
- بررسی فایلهای مختلف devicetree در دستگاههای مختلف و فایلهای فریمور مختلف
- ببرسی سورس کدی که بصورت عمومی در دسترس هستش
- بررسی ایمیجهای کرنل ، kernel extensionها ، iboot و فریمور coprocessor
چطوری ممکنه اکسپلویت، از MMIOهایی استفاده کرده که توسط فریمور استفاده نمیشن؟ مهاجم چطوری از اونا مطلع شده؟ این آدرس های MMIO متعلق به چه دستگاه (های) جانبی هستش؟
محقق این ایده به ذهنش رسیده که بیاد بررسی کنه و ببینه که کدوم MMIO های شناخته شده ای نزدیک این بولکهای ناشناخته ی قرار دارن و از این ایده تونسته به نتایجی برسه.
در ادامه گزارش، محقق اومده devicetree مرتبط با gfx-asc که یه GPU coprocessor هستش رو بررسی کرده.
در شکل بالا دو محدوده ی MMIO رو مشاهده میکنید :
- 0x206400000–0x20646C000
- 0x206050000–0x206050008
این محدوده ها رو با مواردی که اکسپلویت استفاده میکنه اگه بررسی کنیم :
برای بررسی دقیقتر، این اکسپلویت از آدرس های ناشناخته ی زیر استفاده میکنه :
0x206040000, 0x206140008, 0x206140108, 0x206150020, 0x206150040, 0x206150048
میتونیم ببینیم که بیشتر اینا بین دو ناحیه ی gfx-asc و یسریشونم نزدیک به ابتدای ناحیه ی اول gfx-asc قرار دارن. این نشون میده که همه ی این رجیسترهای MMIO به احتمال زیاد متعلق به GPU coprocessor ها هستن.
محقق اومده روی اکسپلویت آنالیز بیشتری انجام داده و یسری چیز جدید کشف کرده که این نظریه اش رو تایید میکنه. اولین کاری که اکسپلویت در مقداردهی اولیه میکنه، یه چیزایی رو در یه رجیستر MMIO دیگه مینویسه که در یه آدرس دیگه ای ، از هر SoC قرار داره.
کد زیر شبه کد GFX power manager control از اکسپلویت هستش.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
if (cpuid == 0x8765EDEA): # CPUFAMILY_ARM_EVEREST_SAWTOOTH (A16) base = 0x23B700408 command = 0x1F0023FF elif (cpuid == 0xDA33D83D): # CPUFAMILY_ARM_AVALANCHE_BLIZZARD (A15) base = 0x23B7003C8 command = 0x1F0023FF elif (cpuid == 0x1B588BB3): # CPUFAMILY_ARM_FIRESTORM_ICESTORM (A14) base = 0x23B7003D0 command = 0x1F0023FF elif (cpuid == 0x462504D2): # CPUFAMILY_ARM_LIGHTNING_THUNDER (A13) base = 0x23B080390 command = 0x1F0003FF elif (cpuid == 0x07D34B9F): # CPUFAMILY_ARM_VORTEX_TEMPEST (A12) base = 0x23B080388 command = 0x1F0003FF if ((~read_dword(base) & 0xF) != 0): write_dword(base, command) while(True): if ((~read_dword(base) & 0xF) == 0): break |
با استفاده از devicetree و ابزار pmgr ، محقق به این کشف رسیده که همه ی این آدرسها با رجیستر GFX در محدوده ی power manager MMIO مطابقت داره.
محقق وقتی میخواسته به رجیسترهایی که در این ناحیه ی ناشناخته دسترسی پیدا کنه، تاییدیه دیگه ای از فرضیه خودش رو گرفته. تقریبا بلافاصله ، GPU coprocessor خطای زیر رو داده :
1 |
GFX SERROR Exception class=0x2f (SError interrupt), IL=1, iss=0 – power(1) |
بنابراین محقق به این نتیجه رسیده که همه ی رجیسترهای ناشناخته MMIO مورد استفاده ی اکسپلویت ، متعلق به GPU coprocessor هستن. در نتیجه محقق رفته این فریمور که در ARM توسعه داده شده و رمزنگاری هم نشده، رو عمیقتر بررسی کنه اما چیزی در خصوص این رجیسترها پیدا نکرده.
در نتیجه محقق رفته نحوه ی عملکرد این رجیسترهای ناشناخته ی MMIO رو در اکسپلویت بیشتر بررسی کنه. رجیستر 0x206040000 با بقیه موارد یکمی متفاوت تره، چون نسبت به رجیسترهای دیگه، در یه بلوک MMIO متفاوتی قرار داره. همچنین در مراحل اولیه و نهایی اکسپلویت مورد استفاده قرار میگیره، یعنی اولین رجیستریه که در زمان مقداردهی اولیه تنظیم میشه و همچنین آخرین رجیستری هم هستش که در مرحله ی آخر تنظیم میشه.
براساس تجربه، محقق حدس میزنه که این رجیستر ، یا ویژگی های سخت افزاری مورد استفاده ی اکپسلویت رو فعال/غیرفعال میکنه و یا وقفه ها رو کنترل میکنه. محقق رفته سراغه وقفه ها و تونسته این رجیستر ناشناخته ی 0x206040000 شناسایی کنه، همچنین بصورت دقیق فهمیده که بین محدوده ی آدرس 0x206000000–0x206050000، دقیقا چی نگاشت شده. در زیر کد مهندسی معکوس شده ای، از نحوه ی استفاده از رجیستری 0x206040000 توسط اکسپلویت رو مشاهده میکنید :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
def ml_dbgwrap_halt_cpu(): value = read_qword(0x206040000) if ((value & 0x90000000) != 0): return write_qword(0x206040000, value | 0x80000000) while (True): if ((read_qword(0x206040000) & 0x10000000) != 0): break def ml_dbgwrap_unhalt_cpu(): value = read_qword(0x206040000) value = (value & 0xFFFFFFFF2FFFFFFF) | 0x40000000 write_qword(0x206040000, value) while (True): if ((read_qword(0x206040000) & 0x10000000) == 0): break |
محقق تونسته ، تابع ml_dbgwrap_halt_cpu در کد بالارو ، با یه تابعی با همون نام در فایل dbgwrap.c در سورس کد XNU ، مطابقت بده. این فایل حاوی کد ، رجیسترهای دیباگ ARM CoreSight MMIO در CPU اصلی هستش.
سورس کد میگه که 4 ناحیه ی MMIO مرتبط با CoreSight وجود داره با نامهای : ED, CTI, PMU,UTT . هر کدومشون 0x10000 بایت فضا اشغال میکنن و در کنار هم قرار میگیرن. تابع ml_dbgwrap_halt_cpu از UTT استفاده میکنه و طبق گفته ی سورس کد، برخلاف سه تای دیگه، از ARM نمیاد و یه ویژگی اختصاصی اپل هستش که برای راحتی کار اضاقه شده.
محقق با نوشتن ARM_DBG_LOCK_ACCESS_KEY در محل مربوطه، تونسته تأیید کنه که 0x206000000–0x206050000 در واقع بلوکی از رجیسترهای دیباگینگ CoreSight MMIO برای GPU coprocessor هستن. هر هسته از CPU اصلی ، بلوک های رجیسترهای دیباگ CoreSight MMIO خودش داره اما برخلاف GPU coprocessor ، آدرسهاشون رو میشه از devicetree پیدا کرد.
نکته جالب دیگه اینکه، نویسندگان این اکسپلویت میدونستن که چطوری میتونن از ناحیه خاص Apple UTT برای از سرگیری اجرای CPU استفاده کنن. این کد بخشی از سورس کد XNU نیست اما محقق معتقده که اگه منصفانه به قضیه نگاه کنیم، میشه از رو تست و بررسی بدستش آورد.
چیزی که برای محقق مشخص نیست اینه که، مهاجم چه کاری با رجیسترهای ناشناخته ناحیه ی دوم انجام داده. محقق مطمئن نیست که چه بلوکهایی از رجیسترهای دیباگینگ MMIO ، اونجا هست و از اون مهمتر ، مهاجم چطوری متوجه اونا شده ،در صورتیکه توسط فریمور استفاده هم نمیشن.
ادامه گزارش در خصوص رجیسترهای ناشناخته بعدی هستش.
رجیسترهای 0x206140008 و 0x206140108 ، عمل فعال/غیرفعال کردن و اجرای ویژگی سخت افزاری مورد استفاده توسط اکسپلویت رو کنترل میکنن. شبه کد زیر نشون دهنده نحوه ی استفاده اکسپلویت از رجیسترهای 0x206140008 و 0x206140108 هستش:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
def dma_ctrl_1(): ctrl = 0x206140108 value = read_qword(ctrl) write_qword(ctrl, value | 0x8000000000000001) sleep(1) while ((~read_qword(ctrl) & 0x8000000000000001) != 0): sleep(1) def dma_ctrl_2(flag): ctrl = 0x206140008 value = read_qword(ctrl) if (flag): if ((value & 0x1000000000000000) == 0): value = value | 0x1000000000000000 write_qword(ctrl, value) else: if ((value & 0x1000000000000000) != 0): value = value & ~0x1000000000000000 write_qword(ctrl, value) def dma_ctrl_3(value): ctrl = 0x206140108 value = value | 0x8000000000000000 write_qword(ctrl, read_qword(ctrl) & value) while ((read_qword(ctrl) & 0x8000000000000001) != 0): sleep(1) def dma_init(original_value_0x206140108): dma_ctrl_1() dma_ctrl_2(False) dma_ctrl_3(original_value_0x206140108) def dma_done(original_value_0x206140108): dma_ctrl_1() dma_ctrl_2(True) dma_ctrl_3(original_value_0x206140108) |
رجیستر 0x206150020 ، فقط برای SoCهای Apple A15/A16 Bionic استفاده میشه. مقدارش در مرحله اولیه اجرای اکسپلویت برابر 1 هستش ، اما در مراحل آخر اجرای اکسپلویت، مقدار اصلیش رو میگیره.
رجیستر 0x206150040 برای ذخیره ی برخی فلگها و مقدار پایین (کم ارزش) آدرس فیزیکی مقصد استفاده میشه.
رجیستر 0x206150048 هم برای ذخیره ی داده هایی که باید نوشته بشن ، مقدار بالای (باارزش) آدرس فیزیکی مقصد ، هش داده و مقادیر دیگه (احتمالا یه دستور) ، استفاده میشه. این ویژگی سخت افزاری ، داده ها رو در بلوک های تراز شده ی 0x40 بایتی می نویسه ، و همه چیز باید در 9 بار نوشتن ، در رجیستر 0x206150048 نوشته بشه. در زیر شبه کدی که اکسپلویت از 0x206150040 , 0x206150048 استفاده میکنه رو مشاهده میکنید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
if (cpuid == 0x8765EDEA): # CPUFAMILY_ARM_EVEREST_SAWTOOTH (A16) i = 8 mask = 0x7FFFFFF elif (cpuid == 0xDA33D83D): # CPUFAMILY_ARM_AVALANCHE_BLIZZARD (A15) i = 8 mask = 0x3FFFFF elif (cpuid == 0x1B588BB3): # CPUFAMILY_ARM_FIRESTORM_ICESTORM (A14) i = 0x28 mask = 0x3FFFFF elif (cpuid == 0x462504D2): # CPUFAMILY_ARM_LIGHTNING_THUNDER (A13) i = 0x28 mask = 0x3FFFFF elif (cpuid == 0x07D34B9F): # CPUFAMILY_ARM_VORTEX_TEMPEST (A12) i = 0x28 mask = 0x3FFFFF dma_init(original_value_0x206140108) hash1 = calculate_hash(data) hash2 = calculate_hash(data+0x20) write_qword(0x206150040, 0x2000000 | (phys_addr & 0x3FC0)) pos = 0 while (pos < 0x40): write_qword(0x206150048, read_qword(data + pos)) pos += 8 phys_addr_upper = ((((phys_addr >> 14) & mask) << 18) & 0x3FFFFFFFFFFFF) value = phys_addr_upper | (hash1 << i) | (hash2 << 50) | 0x1F write_qword(0x206150048, value) dma_done(original_value_0x206140108) |
تا زمانیکه همه چیز به درستی انجام بشه، سخت افزار عملیات دسترسی مستقیم به حافظه (DMA) و نوشتن داده ها در مکانهای مدنظر رو باید انجام بده.
اکسپلویت از این ویژگی سخت افزاری برای دور زدن Page Protection Layer (PPL) استفاده میکنه که عمدتا برای دستکاری page table ها بکار میره. همچنین ازش برای دستکاری داده ها در سگمنت محافظت شده ی __PPLDATA هم میشه استفاده کرد. اکسپلویت از این ویژگی برای دستکاری کد کرنل استفاده نمیکنه، اما محقق ، یکبار در طول بررسیش، تونسته یه دستورالعمل رو در سگمنت __TEXT_EXEC کرنل بنویسه و خطای Undefined Kernel Instruction با آدرس و مقدار مورد انتظار رو دریافت کرده. این فقط یکبار اتفاق افتاده و در دفعات بعدی ، محقق خطای AMCC رو گرفته. محقق گفته که میدونه دفعه ی اول چیکار کرده که اجرا شده، برای همین میخواد در آینده آسیب پذیری رو عمیقتر بررسی کنه، چون فکر میکنه خیلی جالبه که آسیبپذیری که برای آسیب رسوندن به ما استفاده شده رو برداریم و از اون برای چیزای خوبی مثلا فعال کردن kernel debugging در آیفونهای جدید استفاده کنیم.
تا اینجا همه ی رجیسترهای MMIO پوشش داده شدن و تنها نکته ای که میمونه، نحوه ی محاسبه هش ها هستش. الگوریتم محاسبه ی هش ها رو در زیر میبینید :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
sbox = [ 0x007, 0x00B, 0x00D, 0x013, 0x00E, 0x015, 0x01F, 0x016, 0x019, 0x023, 0x02F, 0x037, 0x04F, 0x01A, 0x025, 0x043, 0x03B, 0x057, 0x08F, 0x01C, 0x026, 0x029, 0x03D, 0x045, 0x05B, 0x083, 0x097, 0x03E, 0x05D, 0x09B, 0x067, 0x117, 0x02A, 0x031, 0x046, 0x049, 0x085, 0x103, 0x05E, 0x09D, 0x06B, 0x0A7, 0x11B, 0x217, 0x09E, 0x06D, 0x0AB, 0x0C7, 0x127, 0x02C, 0x032, 0x04A, 0x051, 0x086, 0x089, 0x105, 0x203, 0x06E, 0x0AD, 0x12B, 0x147, 0x227, 0x034, 0x04C, 0x052, 0x076, 0x08A, 0x091, 0x0AE, 0x106, 0x109, 0x0D3, 0x12D, 0x205, 0x22B, 0x247, 0x07A, 0x0D5, 0x153, 0x22D, 0x038, 0x054, 0x08C, 0x092, 0x061, 0x10A, 0x111, 0x206, 0x209, 0x07C, 0x0BA, 0x0D6, 0x155, 0x193, 0x253, 0x28B, 0x307, 0x0BC, 0x0DA, 0x156, 0x255, 0x293, 0x30B, 0x058, 0x094, 0x062, 0x10C, 0x112, 0x0A1, 0x20A, 0x211, 0x0DC, 0x196, 0x199, 0x256, 0x165, 0x259, 0x263, 0x30D, 0x313, 0x098, 0x064, 0x114, 0x0A2, 0x15C, 0x0EA, 0x20C, 0x0C1, 0x121, 0x212, 0x166, 0x19A, 0x299, 0x265, 0x2A3, 0x315, 0x0EC, 0x1A6, 0x29A, 0x266, 0x1A9, 0x269, 0x319, 0x2C3, 0x323, 0x068, 0x0A4, 0x118, 0x0C2, 0x122, 0x214, 0x141, 0x221, 0x0F4, 0x16C, 0x1AA, 0x2A9, 0x325, 0x343, 0x0F8, 0x174, 0x1AC, 0x2AA, 0x326, 0x329, 0x345, 0x383, 0x070, 0x0A8, 0x0C4, 0x124, 0x218, 0x142, 0x222, 0x181, 0x241, 0x178, 0x2AC, 0x32A, 0x2D1, 0x0B0, 0x0C8, 0x128, 0x144, 0x1B8, 0x224, 0x1D4, 0x182, 0x242, 0x2D2, 0x32C, 0x281, 0x351, 0x389, 0x1D8, 0x2D4, 0x352, 0x38A, 0x391, 0x0D0, 0x130, 0x148, 0x228, 0x184, 0x244, 0x282, 0x301, 0x1E4, 0x2D8, 0x354, 0x38C, 0x392, 0x1E8, 0x2E4, 0x358, 0x394, 0x362, 0x3A1, 0x150, 0x230, 0x188, 0x248, 0x284, 0x302, 0x1F0, 0x2E8, 0x364, 0x398, 0x3A2, 0x0E0, 0x190, 0x250, 0x2F0, 0x288, 0x368, 0x304, 0x3A4, 0x370, 0x3A8, 0x3C4, 0x160, 0x290, 0x308, 0x3B0, 0x3C8, 0x3D0, 0x1A0, 0x260, 0x310, 0x1C0, 0x2A0, 0x3E0, 0x2C0, 0x320, 0x340, 0x380 ] def calculate_hash(buffer): acc = 0 for i in range(8): pos = i * 4 value = read_dword(buffer + pos) for j in range(32): if (((value >> j) & 1) != 0): acc ^= sbox[32 * i + j] return acc |
همونطور که میبینید، این یه الگوریتم سفارشی هستش و از جدول تعریف شده ی sbox برای تعریف هش ها استفاده میکنه. محقق اونو در باینری های مختلفی جستجو کرده، اما موردی پیدا نکرده.
احتمالا متوجه شدید که این هش چندان ایمن نیست، چون 20 بیت رو اشغال میکنه ( 10 + 10 ، دوبار محاسبه میشه) ، اما نکته ای که هست اینه که ، تا زمانیکه کسی ندونه چطوری محاسبه و استفاده میشه، کارش انجام میده. بطور خلاصه با عبارت Security By Obscurity (امنیت از طریق ابهام) ، میشه توصیفش کرد.
اما نکته جالبتر اینکه، مهاجم چطوری تونسته این ویژگی سخت افزاری رو کشف و اکسپلویت کنه، در صورتی که ازش استفاده نمیشه و هیچ دستورالعملی در فریمور در خصوص نحوه ی استفاده از اون وجود نداره.
محقق تراشه ی M1 در مک رو هم بررسی کرده و متوجه شده که این ویژگی سخت افزاری ناشناخته، در اون هم وجود داره. در ادامه محقق از ابزار m1n1 برای تست استفاده کرده. ابزار یه تابعی بنام trace_range داره که امکان رهگیری همه ی دسترسی ها به یه محدوده ی ارائه شده از رجیسترهای MMIO رو میده. محقق محدوده ی 0x206110000–0x206400000 رو داده و مشاهده کرده که هیچکدوم از این رجیسترها در macOS استفاده نمیشن.
این آسیب پذیری خیلی شبیه به آسیب پذیری بوده که محقق در 36امین دوره ی Chaos Communication Congress (36C3) در سال 2019 ارائه داده. اون ارائه که موضوعش هک درایورهای Blu-ray پلی استیشن سونی بوده ، محقق در خصوص نحوه ی دامپ فریمور و اجرای کد در درایورهای Blu-ray ، روی پلی استیشن 3 و 4 ، از طریق رجیسترهای MMIO DMA ، که از طریق دستورات SCSI در دسترس بودن، صحبت کرده.
محقق میگه اینکه من تونستم این آسیب پذیری رو کشف و اکسپلویتش کنم، برا این بوده که نسخه های قبلی فریمور از این رجیسترها برای انجام همه ی عملیات DRAM استفاده میکردن ، اما بعدش سونی استفاده از اون رو ممنوع کرد و شروع به استفاده از دسترسی مستقیم به DRAM کرد، چون همه ی DRAM به فضای آدرس CPU هم نگاشت میشدن. چون کسی از این رجیسترها استفاده نمیکرده و من نحوه ی استفاده از اون رو میدونستم، بنابراین باعث یه امتیاز شده و نیازی به دونستن الگوریتم مخفی هش نداشته.
ممکنه در این مورد هم یه همچین اتفاقی افتاده باشه؟ محقق میگه نمیدونم، اما این GPU coprocessor ها برای اولین بار در SoCهای اخیر اپل ظاهر شدن. محقق براساس مواردی که در بالا گفته، نظر شخصیش اینه که ، این ویژگی سخت افزاری روی فریمورهای خرده فروشی خاصی استفاده شده. البته این احتمال هم وجود داره که قبلا به اشتباه در برخی از فریمورهای خاص یا سورس کد XNU استفاده شده و بعدا حذف شده.
محقق امیدواره که از روی اصلاحیه ای که اپل منتشر کرده، بدونه که در ناحیه دوم ناشناخته هم چه خبره، اما محقق گفته که تونسته نحوه ی اصلاح این آسیب پذیری رو بفهمه اما اپل این اصلاح رو مبهم کرده.
اپل این آسیب پذیری رو با افزودن محدوده ی MMIO مورد استفاده ی اکسپلویت (0x206000000–0x206050000 و 0x206110000–0x206400000) به pmap-io-ranges ذخیره شده در devicetree اصلاح کرده. XNU از اطلاعاتی که اونجا ذخیره شده، تعیین میکنه که آیا نگاشت آدرس های فیزیکی خاصی مجازه یا نه. همه مواردی که اونجا ذخیره شدن، فیلدهای معناداری دارن و میشه فهمید که محدوده به چه نوع حافظه ای تعلق داره.
اینجا PCI ، مخفف Peripheral Component Interconnect Express و DART مخفف Device Address Resolution Table و DAPF مخفف Device Address Filter هستش.
عنوان تگی که برای مناطق مورد استفاده ی اکپسلویت هم گذاشته شده ، Deny هستش.