تصور کنید تنها با تغییر یک بیت در کنترلکننده حافظه، تمام دیوارهای امنیتی یک پردازنده مدرن فرو بریزد. کریستوفر دوماس (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) برقرار شود.

لایه 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 در لحظه انتقال است. دوماس از یک توالی اسمبلی خاص برای حفظ پایداری پلتفرم استفاده میکند:
۱. آمادهسازی: غیرفعال کردن پردازندههای کمکی (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 ممکن است بدون ترتیب باشد.

برای حل این معما، دوماس از حلکننده 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_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 مراجعه کنید.




گفتگو