کشف آسیبپذیری در UEFI با شبیهسازی دیکودر PNG
خلاصهٔ کاملتر
محققان امنیتی NetSPI یک ماژول BIOS به نام PngDecoderDxe.bin رو بررسی میکردن تا ببینن آیا در برابر آسیبپذیری LogoFail محافظت شده یا نه. LogoFail یه باگ شناختهشدهست که با دستکاری هدر فایل تصویری، هنگام تخصیص حافظه برای دیکد، سرریز بافر (buffer overflow) ایجاد میکنه. بررسی کد نشون داد که این دیکودر در برابر LogoFail محافظت داره — اما یه مشکل جداگانه داره: هیچ چک محدودیتی برای عملیات خواندن از بافر وجود نداره.
مشکل اینجاست که طول chunk IDAT (بخشی از فایل PNG که دادههای فشردهی پیکسل رو نگه میداره) توسط دیکودر بدون تأیید با اندازه واقعی دادهها پذیرفته میشه. اگه این طول جعل بشه، دیکودر بیشتر از اون چیزی که واقعاً در فایل هست میخونه و به حافظههای مجاور سرک میکشه. این نوع باگ رو buffer over-read میگن — نه نوشتن خارج از محدوده، بلکه خواندن از جاهایی که نباید.
برای اثبات این موضوع، از Qiling استفاده شده — یه فریمورک پایتونی که میتونه باینریهای مختلف از جمله ماژولهای UEFI رو بدون نیاز به سختافزار واقعی شبیهسازی کنه. چون ماژول UEFI به سرویسهای خاص فریمور نیاز داره، محققان با استفاده از hook کردن توابعی مثل AllocatePool و FreePool، این سرویسها رو با کد پایتون شبیهسازی کردن تا بتونن کنترل کاملی روی چیدمان حافظه داشته باشن.
def hook_allocpool(ql):
global next_heap_addr
size = ql.arch.regs.rcx
if size >= 0x300800:
print("[!] NETSPI: Large allocation detected. Spacing out heap.")
next_heap_addr += 0x10000000
alloc_addr = next_heap_addr
ql.mem.map(alloc_addr, (size + 0xfff) & ~0xfff)
ql.arch.regs.rax = alloc_addr
next_heap_addr += (size + 0xfff) & ~0xfff
return Trueیه فایل PNG مسموم هم ساخته شد: طول chunk IDAT از مقدار واقعی 0xe7542 به 0x90000000 تغییر داده شد. این مقدار از حد مجاز 0x7fffffff کمتره پس چک LogoFail رو رد میکنه، ولی خیلی بزرگتر از دادهی واقعی موجوده. نتیجه؟ دیکودر تلاش میکنه بیشتر از اون چیزی که توی فایل هست بخونه و به ناحیههای خارج از بافر میرسه:
CRITICAL SYSTEM ABORT: UNMAPPED MEMORY ACCESS
Instruction RIP: 0x104106
Illegal Read Address: 0x9076000 (The image data ended at 0x9073B07)
این آسیبپذیری از این جهت مهمه که UEFI قبل از بارگذاری سیستمعامل اجرا میشه. هر ضعفی در این لایه میتونه به نشت اطلاعات حساس در زمان بوت یا حتی تهدید "ریشه اعتماد" (Root of Trust) سیستم منجر بشه — چیزی که سیستمعامل هیچ کنترلی روش نداره.
نکات کلیدی:
- آسیبپذیری LogoFail در این باینری وصله شده بود، اما یه buffer over-read جداگانه پیدا شد
- با جعل طول IDAT در فایل PNG، دیکودر UEFI بدون محدودیت از حافظه میخونه
- Qiling برای شبیهسازی محیط UEFI و hook کردن توابع مدیریت حافظه استفاده شد
- این باگ میتونه در زمان بوت باعث نشت دادههای حساس از حافظه سیستم بشه
- UEFI قبل از سیستمعامل اجرا میشه، پس آسیبپذیریهایش خارج از کنترل OS هستن




