پرش به محتوای اصلی
پرش به محتوای مقاله

دست‌کاری کنترل‌کننده حافظه؛ راهی برای عبور از حصارهای امنیتی CPUهای AMD

·۲۲ مرداد ۱۴۰۵۲۸ دقیقه مطالعه۱ بازدید
رمزگشایی کامل پردازنده با استفاده از درهم‌سازی DRAM
رمزگشایی کامل پردازنده با استفاده از درهم‌سازی DRAM
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

نخستین اثبات عملی از دور زدن حصارهای امنیتی CPU از طریق دست‌کاری لایه MCT/DCT در کنترل‌کننده حافظه؛ جایی که آدرس فیزیکی به مختصات خام DRAM تبدیل می‌شود.

تصور کنید تنها با تغییر یک بیت در کنترل‌کننده حافظه، تمام دیوارهای امنیتی یک پردازنده مدرن فرو بریزد. کریستوفر دوماس (Christopher Domas) با شناسه‌ی @xoreaxeaxeax ثابت کرد که با بازنویسی ترجمه آدرس‌های فیزیکی DRAM، می‌توان به مناطقی از حافظه دسترسی پیدا کرد که حتی برای هسته سیستم‌عامل (Kernel) نیز نامرئی هستند. این فرآیند که او آن را «اسپاگتی کردن DRAM» (spaghettifying DRAM) نامیده است، به مهاجم اجازه می‌دهد اسرار حیاتی پلتفرم را استخراج کند؛ از جمله بخش‌های تخصصی حافظه (carveouts) که برای سیستم‌عامل کاملاً پنهان‌اند.

بسیاری از سیستم‌های امنیتی CPU بر این فرض استوارند که آدرس‌های فیزیکی، لنگرهایی تغییرناپذیر و ثابت هستند. ما تصور می‌کنیم پردازنده امنیتی پلتفرم (PSP) یا حالت مدیریت سیستم (SMM) کاملاً ایزوله هستند، چون حصارهای سخت‌افزاری از آدرس‌های فیزیکی اختصاص‌یافته به آن‌ها محافظت می‌کنند. اما نکته کلیدی اینجاست که این حصارها در لایه‌ای بالاتر از کنترل‌کننده حافظه قرار دارند. اگر نحوه نگاشت آدرس‌ها به خازن‌های واقعی DRAM را تغییر دهید، حصارها در جای خود می‌مانند اما داده‌هایی که محافظت می‌کردند به جای دیگری منتقل می‌شوند. در این وضعیت، آدرس فیزیکی x دیگر برابر با x نیست (&x != &x).

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

مکانیسم اسپاگتی کردن

دسترسی به حافظه یک خط لوله عمیق از انتزاع‌ها است. وقتی کد یک اشاره‌گر را فراخوانی می‌کند (*p)، به نظر می‌رسد که مستقیماً به DRAM در آدرس p دسترسی دارد، اما در واقع باید از یک مسیر سخت‌گیرانه عبور کند:

  • هسته CPU و MMU: آدرس مجازی ۶۴ بیتی (VA) ابتدا تحت بررسی فرمت کانونی (canonical-form) قرار می‌گیرد (بیت‌های [63:48] از بیت ۴۷ گسترش علامت می‌یابند). سپس پایه سگمنت (FS.base / GS.base از طریق MSR_FS_BASE و MSR_GS_BASE) به آن اضافه می‌شود.
  • TLB و Page Walk: سیستم ابتدا TLB (که با PCID/VPID برچسب‌گذاری شده) را بررسی می‌کند. در صورت عدم یافتن (miss)، یک پیمایشگر سخت‌افزاری صفحه از CR3 فعال شده و از PML5 (اگر CR4.LA57 فعال باشد)، PML4، PDPT (برگ ۱ گیگابایتی)، PD (برگ ۲ مگابایتی) و در نهایت PT عبور می‌کند تا به ورودی جدول صفحه (PTE) برسد.
  • بررسی سطح دسترسی: در هر سطح از این پیمایش، سطح دسترسی (U/S)، مجوزهای نوشتن (R/W + CR0.WP) و مجوز اجرای کد (NX + EFER.NXE) ارزیابی می‌شود. همچنین بررسی‌های SMEP/SMAP (از طریق CR4.SMEP/SMAP) و کلیدهای حفاظتی (PKRU/IA32_PKRS) انجام می‌گیرد.
  • ترجمه مهمان (Guest Translation): اگر سیستم در محیط ماشین مجازی باشد، یک پیمایش مجدد EPT/NPT رخ می‌دهد که می‌تواند منجر به ۵ برابر پیمایش بیشتر برای هر پیمایش واحد مهمان شود. این شامل مسیر EPT-PML4 $\rightarrow$ EPT-PDPT $\rightarrow$ EPT-PD $\rightarrow$ EPT-PT و بازنویسی‌های نوع حافظه EPT است.
  • نگهداری TLB: سیستم وقفه‌های IPI برای تخلیه TLB را از طریق پخش invlpg به vCPUهای همتا مدیریت می‌کند.
  • IOMMU: برای درخواست‌های آغاز شده توسط دستگاه‌ها، یک پیمایش صفحه IOMMU (مانند VT-d یا AMD-Vi) رخ می‌دهد که شناسه‌ی دستگاه $\rightarrow$ دامنه $\rightarrow$ جداول را برای رسیدن به آدرس فیزیکی k نگاشت می‌کند.
  • تعیین نوع حافظه: سیستم نوع موثر حافظه (WB, WT, WC, WP, UC-, UC) را با استفاده از تطبیق محدوده‌های MTRR (از طریق IA32_MTRR_DEF_TYPE و MTRRهای ثابت/متغیر) و ورودی‌های PAT (از طریق IA32_PAT[ PTE.PAT:PCD:PWT ]) تعیین می‌کند.
  • بافت سیستم (Uncore & Fabric): درخواست ابتدا کش‌های L1-D (VIPT، هر هسته)، L2 (هر هسته/CCX) و سپس LLC مشترک (بخش‌بندی شده) را بررسی می‌کند. در نهایت وارد بافت داده‌های سیستم (AMD DF یا Intel mesh/ring) می‌شود تا از طریق پخش‌های MESI/MOESI در Infinity Fabric، QPI، UPI یا CXL.cache همگامی (coherence) برقرار شود.

باز کردن همه چیز در پردازنده با درهم‌سازی DRAM

لایه MCT/DCT؛ نقطه حمله

پروژه skitter-creek-bath-salts روی مرحله نهایی تمرکز دارد: کنترل‌کننده حافظه (MCT) و لایه تبدیل کش داده (DCT). اینجا جایی است که آدرس فیزیکی دریافتی از بافت داده‌ها برای آخرین بار به مختصات خام DRAM تبدیل شده و به DIMM ارسال می‌شود. این تبدیل نهایی شامل چندین مرحله پیچیده است:

  • بازنگاشت حفره‌های DRAM: بازنگاشت‌های حافظه بالا (High-memory remaps) بالای سقف حافظه (TOM).
  • بازنگاشت استثنائی: مدیریت محدوده‌های رزرو شده یا حفاظت شده.
  • هش‌های اینترلیو (Interleave Hashes): عملیات XOR روی بیت‌های منتخب آدرس فیزیکی برای تعیین کانال، رنک و بانک.
  • جابه‌جایی بانک‌ها (Bank Swizzle): یک سیستم رمزنگاری XOR که توسط سازنده و BIOS قابل پیکربندی است.
  • نرمال‌سازی انتخاب تراشه (DCT): نگاشت خط CS برای هر رنک.
  • انتخاب زیر-کانال: مخصوص معماری‌های DDR5 و LPDDR5.
  • مختصات نهایی: خروجی نهایی شامل گروه بانک، بانک، ردیف (RAS) و ستون (CAS) است.

به نقل از مستندات این پژوهش، با تغییر یک رجیستر پیکربندی خاص — برای مثال دستور xor dword [0xf80c2094], 0x00400000 در CPUهای خانواده 16h شرکت AMD — می‌توان حالت «Bank-swizzle» را فعال کرد. این کار عملاً نقشه حافظه را به‌هم می‌ریزد. ناگهان، آدرس فیزیکی که قبلاً توسط یک حصار امنیتی مسدود شده بود، اکنون به مکان دیگری در DRAM اشاره می‌کند، در حالی که یک آدرس مجاز ممکن است اکنون به یک راز حفاظت‌شده اشاره (alias) کند.

باز کردن قفل همه چیز در پردازنده با استفاده از درهم‌سازی حافظه DRAM

اجرا و پایداری سیستم

برای جلوگیری از کرش کردن سیستم در حین این جابه‌جایی، عملیات باید بسیار جراحی‌گونه و دقیق باشد. ترفند اصلی، سرعت بالا و عدم دسترسی به DRAM در لحظه انتقال است. دوماس از یک توالی اسمبلی خاص برای حفظ پایداری پلتفرم استفاده می‌کند:

۱. آماده‌سازی: غیرفعال کردن پردازنده‌های کمکی (APs) و وقفه‌ها (cli).
۲. پرایمینگ (Priming): آماده‌سازی TLBها برای جلوگیری از پیمایش صفحات در لحظه تغییر (مثلاً mov eax, [0xf80c2094] برای MMIO و mov eax, [0x6f800000] برای هدف).
۳. تخلیه (Eviction): گرم کردن کش و تخلیه هدف (clflush [0x6f800000]) برای اجبار سیستم به خواندن مستقیم از DRAM.
۴. سریال‌سازی: استفاده از موانع حافظه (mfence و lfence) برای تضمین اینکه هیچ دسترسی همگامی باقی نمانده و خواندن‌های بعدی در نمای اسپاگتی‌شده بازآرایی شوند.
۵. تغییر (The Flip): اجرای دستور xor dword [0xf80c2094], 1<<22 برای تغییر وضعیت DCT و اسپاگتی کردن DRAM.
۶. استخراج: واکشی داده‌های هدف از منطقه حفاظت‌شده از طریق یک آدرس جایگزین (mov ebx, [0x6f800000]).
۷. بازگردانی: بازگرداندن فوری نگاشت اصلی با یک XOR دیگر، سریال‌سازی مجدد و فعال‌سازی دوباره APها.

حل رمز اسپاگتی با جبر خطی

از آنجا که تبدیل کنترل‌کننده حافظه یک نگاشت خطی در میدان GF(2) است، این به‌هم‌ریختگی تصادفی نیست، بلکه ریاضی است. چالش اینجاست که دیتاشیت‌های سازندگان اغلب ناقص هستند؛ برای مثال، نقشه‌های XOR ممکن است اشتباه باشند و مرحله تفریق MMIO ممکن است بدون ترتیب باشد.

باز کردن همه چیز در پردازنده با درهم‌سازی حافظه DRAM

برای حل این معما، دوماس از حل‌کننده SMT به نام z3 استفاده می‌کند. این ابزار یک مقدار شناسه‌دار (مانند 0xdeadc0de) را در آدرسی شناخته‌شده در نمای همگام قرار می‌دهد، سپس به نمای اسپاگتی سوئیچ کرده و حافظه را می‌گردد تا ببیند این مقدار در کجا ظاهر شده است. این کار یک جفت «هدف و جایگزین» (target, alias) ایجاد می‌کند — یک نقطه داده عینی که نشان می‌دهد دو آدرس فیزیکی مختلف به یک سلول یکسان در DRAM اشاره می‌کنند.

با جمع‌آوری چندین جفت از این دست، z3 می‌تواند ماتریس ترجمه را بازسازی کند. این ماتریس مانند یک «سنگ رشید» عمل می‌کند و به مهاجم اجازه می‌دهد برای هر راز حفاظت‌شده، آدرس جایگزین دقیق آن را محاسبه کند و تمام قفل‌ها را دور بزند. این تبدیل حل‌شده به مهاجم اجازه می‌دهد هر آدرس هدف در نمای عادی را گرفته و معادل آن را در نمای اسپاگتی پیدا کند، بدون اینکه هیچ حصار یا قفلی مانع او شود.

باز کردن عمیق‌ترین اسرار CPU

با حل ماتریس ترجمه، ابزار دوماس دسترسی نامحدود به چندین هدف با ارزش بالا پیدا می‌کند:

پردازنده امنیتی پلتفرم (PSP):

  • ابزار می‌تواند حافظه خصوصی carveout مربوط به fTPM را استخراج کند (مثلاً آدرس 0x7f800000 با اندازه 0x800000 در سیستم‌های تست).
  • دوماس با موفقیت روتین crAmd_ModExp را بازیابی کرد — موتور توان‌رسانی پیمانه‌ای RSA که برای امضاهای fTPM و تست‌های میلر-رابین برای ضرب سکه کلیدها استفاده می‌شود.
  • کد بازیابی شده، منطق داخلی fTPM را فاش می‌کند، از جمله استفاده از عملوندهای ۱۰۲۴ بیتی و رشته‌های ثبت خطای خاص مانند "crAmd_ModExp aA failed, status = 0x%x" و "crAmd_ModExp aB failed status = 0x%x".
  • تحلیل کد (disassembly) نشان می‌دهد که این روتین رجیسترهای {r4, r5, r6, r7, lr} را push کرده، ۴۰۴ بایت روی استک تخصیص می‌دهد و توابع داخلی را برای وارد کردن پایه و توان قبل از اجرای modexp فراخوانی می‌کند.
  • این حافظه قرار است منحصراً در اختیار هسته ARM در PSP باشد و حتی برای سطح Ring-0 نامرئی باشد.

حالت مدیریت سیستم (SMM):

  • با خواندن SMBASE از MSR 0xc0010111 ابزار می‌تواند بردار ورودی SMI handler (واقع در SMBASE + 0x8000) را استخراج کند.
  • این کار کدی را فاش می‌کند که در سطح Ring -2 اجرا می‌شود، یعنی привиلیژ‌ترین محیط در CPU.
  • استخراج داده‌ها، استاب (stub) ورودی SMI را نشان می‌دهد که GDT را از SMBASE+0x8148 بارگذاری کرده، هسته را از طریق CR0.PE | CR0.MP به حالت protected mode می‌برد و با استفاده از یک فریم far-return به ورودی هندلر ۳۲ بیتی در SMBASE+0x803a می‌پرد.
  • این استاب به‌طور خاص سقف استک SMM را روی 0x6efe2ff8 تنظیم کرده و برای ورود به هندلر اصلی از far-return استفاده می‌کند.

ذخیره وضعیت C6 (Idle-State Stash):

  • وقتی هسته‌ها برای کاهش مصرف انرژی به حالت C6 می‌روند، تمام وضعیت معماری x86 آن‌ها در DRAM ذخیره می‌شود (مثلاً در 0x7f000000 با اندازه 0x800000).
  • وضعیت هر هسته در یک ناحیه ذخیره‌سازی ۱۶ کیلوبایتی قرار دارد. ابزار می‌تواند این‌ها را بخواند تا رجیسترهای داخلی CPU را بیابد:
    • +0x8b0: پایه GS / per-cpu (مثلاً 0xffff9be4e3600000)
    • +0x9a0: ریشه جدول صفحه CR3 (مثلاً 0x0fd46000)
    • +0x9b8: پایه IA32_APIC_BASE (مثلاً 0xfee00900 برای BSP و 0xfee00800 برای APها)
    • +0xa38: MTRR متغیر (پایه/ماسک، مثلاً 0x6f000000)
    • +0xb10: مقدار ذخیره شده RIP (مثلاً 0xffffffff8f3a0029)

میکروکد CPU:

  • ذخیره C6 همچنین حاوی کپی از وصله میکروکد SRAM فرار در آدرس +0x1800 در هر ناحیه ذخیره‌سازی است که برای مقداردهی مجدد هسته هنگام بیدار شدن استفاده می‌شود.
  • ابزار می‌تواند این وصله (مثلاً 0x5f0 بایت) را استخراج کرده و آن را با فریم‌ورهای شناخته شده (مانند microcode_amd_fam16h.bin) تطبیق دهد.
  • داده‌های استخراج شده، uops متمایز در ابتدا و پدینگ‌های NOP تکرار شونده در ادامه را نشان می‌دهند.
  • با استفاده از dram_poke مهاجم می‌تواند در این کپی بنویسد و احتمالاً میکروکدی را که هسته هنگام بیدار شدن بارگذاری می‌کند، تغییر دهد.

رمزگشایی کامل پردازنده با استفاده از درهم‌سازی DRAM

ابزارها و پیاده‌سازی

این پروژه یک زنجیره ابزار کامل برای خودکارسازی این حملات ارائه می‌دهد:

  • dram_read: خواندن ساده از یک آدرس حفاظت‌شده با اعمال تغییرات --do-swizzle یا --do-bankswap در کنترل‌کننده DRAM، خواندن یک dword و بازگرداندن بیت‌های DCT.
  • dram_dump: استخراج محدوده حافظه حفاظت‌شده با استفاده از نقشه‌های حل‌شده اسپاگتی. این ابزار از شبه-معکوس GF(2) برای بازیابی جایگزین‌ها برای هر dword در محدوده استفاده می‌کند و از پرچم‌هایی مانند --dangerously-skip-calibration و --fenced-range پشتیبانی می‌کند.
  • dram_poke: نوشتن در حافظه حفاظت‌شده. این ابزار از چندین نقشه برای گسترش پوشش استفاده می‌کند، زیرا اسپاگتی‌های مختلف حفره‌های رنک-ناقص متفاوتی ایجاد می‌کنند. این ابزار می‌تواند برای تغییر ذخیره میکروکد C6 به کار رود.
  • خط لوله تحلیل: اسکریپت gather_aliases.py جفت‌های (هدف، جایگزین) را جمع‌آوری می‌کند و unspaghettify.py از این‌ها برای ساخت نقشه‌های نهایی استفاده می‌کند.

ریسک معماری گسترده‌تر

اگرچه این اکسپلویت خاص برای خانواده 16h شرکت AMD توسعه یافته است — که آخرین نسلی بود که رجیسترهای ترجمه قابل باز کردن و مستند شده داشت (نسل 17h و بعد از آن این اطلاعات را حذف کرده‌اند) — اما آسیب‌پذیری زیربنایی، معماری است. هر کنترل‌کننده حافظه مدرنی، چه از Intel، ARM یا RISC-V باشد، از نسخه‌ای از اینترلیوینگ کانال، رنک و بانک، و همچنین Bank Swizzling و نرمال‌سازی Chip-Select استفاده می‌کند.

تکنولوژی‌های امنیتی مانند AMD SEV، Intel SGX، Intel TDX، ARM TrustZone، CCA realms، pKVM، CoVE، SEP و Intel ME همگی دیوارهای خود را بر این فرض بنا کرده‌اند که خط لوله آدرس فیزیکی یک ثابت قابل اعتماد است. اگر مرحله نهایی این خط لوله (MCT/DCT) قابل دست‌کاری باشد، تمام پشته امنیتی بالای آن بی‌اثر می‌شود. قفل‌ها هنوز سر جایشان هستند، اما در را جابه‌جا کرده‌اند.

این پژوهش فرضیات این حوزه را تغییر می‌دهد و ثابت می‌کند که ایزوله‌سازی حافظه تنها یک مشکل نرم‌افزاری یا فریم‌ور نیست، بلکه یک مسئله نگاشت فیزیکی است. این نشان می‌دهد که «حصارها» در سطح سخت‌افزار تنها به اندازه آخرین لایه ترجمه که با DIMM در تماس است، قدرت دارند.

گام بعدی شما

  • اگر توسعه‌دهنده سیستم‌های سطح پایین یا پژوهشگر امنیت هستید، مخزن skitter-creek-bath-salts را برای درک نحوه تعامل با رجیسترهای MCT بررسی کنید.
  • در به‌روزرسانی‌های BIOS سیستم‌های قدیمی AMD، بررسی کنید آیا محدودیت‌های جدیدی برای دسترسی به رجیسترهای پیکربندی حافظه اعمال شده است یا خیر.

اما داستان سخت‌افزاری این تحول حتی شگفت‌انگیزتر است — به تحلیل ما درباره معماری جدید تراشه‌های Blackwell مراجعه کنید.

چرا این موضوع مهم است؟

این کشف بر اساس تخصص در مهندسی معکوس سخت‌افزار، نشان می‌دهد که حصارهای امنیتی CPUها را می‌توان با دور زدن لایه فیزیکی بی‌اثر کرد. این موضوع اعتبار تمام سیستم‌های ایزوله‌سازی حافظه در پردازنده‌های مدرن را زیر سؤال می‌برد.

تأثیر برای ایران

این خبر بیشتر برای پژوهشگران امنیت سخت‌افزار و مهندسان سیستم در ایران اهمیت دارد و اثر مستقیمی بر کاربران عادی یا توسعه‌دهندگان اپلیکیشن ندارد.

·نگاه ما
تحریریه دات‌هوش

این پژوهش ثابت می‌کند که «اعتماد به سخت‌افزار» یک توهم خطرناک است؛ وقتی لایه فیزیکی ترجمه آدرس قابل تغییر باشد، تمام مفاهیم انتزاعی امنیت (مانند Ring-0 یا TrustZone) فرو می‌ریزند. در واقع، امنیت در لایه‌های بالا تنها به شرط صلب بودن لایه‌های پایین معنا می‌یابد. این یافته می‌تواند منجر به بازنگری در طراحی کنترل‌کننده‌های حافظه در نسل‌های آینده شود تا از تغییرات پویا در زمان اجرا جلوگیری شود.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

موضوع‌ها

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.