
فتح _كل شيء_ على وحدة المعالجة المركزية باستخدام تشويش DRAM
فتح كل شيء على وحدة المعالجة المركزية عبر تشويش DRAM — PSP، وC6، والمايكروكود، وSMM، وأي شيء آخر أغفلته المواصفات.
&x == &x.
عادةً.

اضغط على متحكم DRAM ويمكن جعل العنوان يهبط حيثما تشاء في
الذاكرة. يعدّل skitter-creek-bath-salts الطبقات السفلى من تسلسل
الذاكرة لإعادة توصيل ترجمات عناوين DRAM الفيزيائية. يؤدي هذا إلى تشويش
ذاكرة المنصة، مما يكشف مناطق محمية من DRAM — مناطق معزولة غير مرئية حتى
للنواة. وعندما تنكسر ترجمات العناوين، تنكسر معها البدائيات
الأمنية المبنية عليها، ونفتح كل شيء.
طُوِّر واختُبِر على معالجات AMD Family 16h، آخر جيل توثّق أوراق بياناته
سجلات الترجمة الخاصة بمتحكم DRAM — وتُظهر أنها لا يمكن قفلها. أما 17h وما بعده
فببساطة يحجبون هذه المعلومات. إن
ملحمة *p متشابهة عبر الأجيال
والمعماريات، والتحويلات الأساسية تمتد حتى إلى ARM وRISC-V
وما هو أبعد؛ يُظهر لنا skitter-creek-bath-salts فقط كيف نبدأ.
*pإنه طريق طويل نحو الأسفل.
الذاكرة مبنية على طبقات من التجريد عميقة لدرجة تصبح شبه عبثية. عندما
يشير كودك إلى *p، يبدو أنه يصل إلى DRAM عند p. لكنه لا يفعل ذلك —
فـ p عنوان افتراضي، وقبل أن تُلمس ولو بتة واحدة من DRAM، يجب
أن ينجو من العقبات أدناه:```
── CPU core / MMU ─────────────────────────────────────────────────
┌─ VA ← 64-bit virtual address from load/store
│
└> canonical-form check ──────────────────────┐ ← bits [63:48] sign-extend from bit 47
┌─ segment base add <─────────────────────────┘ ← FS.base / GS.base (MSR_FS_BASE, MSR_GS_BASE)
│
└> TLB probe ─────────────────────────────────┐ ← tagged by PCID (host) / VPID (guest)
hit → physical address k │
miss → engage hardware page walker │
┌─ page walk (from CR3) <─────────────────────┘ ← walked only on TLB miss
│ PML5[VA 56:48] ← only if CR4.LA57
│ PML4[VA 47:39]
│ PDPT[VA 38:30] ← 1 GiB leaf possible
│ PD [VA 29:21] ← 2 MiB leaf possible
│ PT [VA 20:12]
│ PTE ← R/W · U/S · NX · A/D · PAT · PCD · PWT · G
│
└> per-level checks ──────────────────────────┐ ← evaluated at every level of the walk
privilege (U/S) │ ← CPL vs PTE.U/S
write (R/W) │ ← + CR0.WP
execute (NX) │ ← EFER.NXE
SMEP / SMAP │ ← CR4.SMEP · CR4.SMAP · EFLAGS.AC
protection keys │ ← PKRU (user) · IA32_PKRS (supervisor)
┌─ A/D bit update <───────────────────────────┘ ← locked RMW on PTE
│
└> if guest: EPT / NPT re-walk ───────────────┐ ← each guest-PA above re-walked
EPT-PML4 → EPT-PDPT → EPT-PD → EPT-PT │ ← + EPT memory-type override
⇒ ~5× walks per single guest walk │
┌─ TLB shootdown IPIs <───────────────────────┘ ← invlpg broadcast to peer vCPUs
│
│ ── IOMMU (chipset / I/O fabric) ──────────────────────────────────
│
└> if device-initiated, IOMMU page walk ──────┐ ← VT-d / AMD-Vi: device-ID → domain → tables
│
┌── physical address k <─────────────────┘
│
│ ── CPU core / MMU — memory-type resolution ────────────────────────
│
└> MTRR range match ──────────────────────────┐ ← IA32_MTRR_DEF_TYPE + fixed/variable MTRRs
┌─ PAT entry select <─────────────────────────┘ ← IA32_PAT[ PTE.PAT:PCD:PWT ]
│
└> effective memory type ─────────────────────┐ ← { WB, WT, WC, WP, UC-, UC }
│
── CPU uncore — caches & coherence ────────────────────────────────
│
┌─ L1-D probe <───────────────────────────────┘ ← VIPT, per-core
│
└> L2 probe ──────────────────────────────────┐ ← per-core / per-CCX
┌─ LLC probe + directory consult <────────────┘ ← shared, sliced
│
└> snoop / coherence ─────────────────────────┐ ← MESI / MOESI broadcast
intra-socket │ ← broadcast to peer cores
inter-socket │ ← QPI · UPI · Infinity Fabric · CXL.cache
home-node directory response │ ← data | intervention | abort
│
── system data fabric / interconnect ──────────────────────────────
│
┌─ if MMIO range or sub-4 GiB MMIO hole <─────┘ ← uncore/data fabric posted/non-posted txn
│ → device BAR; done
│
└> else DRAM-bound: data fabric / mesh ───────┐ ← AMD DF · Intel mesh-or-ring uncore
│
┏━━ ── MCT / IMC (memory controller) ────────────────────────────────
W ┃ ┌─ DRAM hole remap <──────────────────────────┘ ← high-memory remap above TOM
E ┃ │
┃ └> memory-region exclusion remap ─────────────┐ ← reserved / protected ranges
┃ ┌─ channel interleave hash <──────────────────┘ ← XOR of selected PA bits → channel
A ┃ │
R ┃ └> rank interleave hash ──────────────────────┐ ← XOR of selected PA bits → rank
E ┃ ┌─ bank interleave hash <─────────────────────┘ ← XOR of selected PA bits → bank
┃ │
┃ └> bank swizzle / XOR scramble ───────────────┐ ← vendor- and BIOS-configurable
H ┃ ┌─ chip-select normalize (DCT) <──────────────┘ ← per-rank CS line
E ┃ │ rank → CS map
R ┃ │
E ┃ └> sub-channel select ────────────────────────┐ ← DDR5 / LPDDR5 only
┗━━ │
│
DRAM coordinates <─────────────────────────┘ ← bank group · bank · row (RAS) · column (CAS)
يعمل هذا المشروع على أعمق مستويات مسار `*p`، طبقة MCT/DCT
— حيث يدخل عنوان فيزيائي من نسيج البيانات/الربط البيني إلى وحدة التحكم
بالذاكرة ويُعاد كتابته للمرة الأخيرة إلى إحداثيات DRAM الخام التي
تُرسل إلى DIMM.
---
## تحويل DRAM إلى سباغيتي
> العناوين الفيزيائية هي في الحقيقة أقرب إلى اقتراح.```nasm
xor dword [0xf80c2094], 0x00400000
هذا هو الاستغلال. كله.
انقلاب بت واحد في متحكم DRAM يعيد توصيل الجزء السفلي من مسار *p،
والبيانات التي كانت في &x أصبحت الآن في مكان آخر أثناء التنفيذ. فجأة &x != &x.
كل آلية تستخدمها وحدة المعالجة المركزية، والبرنامج الثابت، وuncore، ومجموعة الشرائح لعزل
الذاكرة المحمية تقع فوق متحكم الذاكرة، ولا شيء منها يرى ما يحدث في الأسفل.
الحواجز تحمي العناوين الفيزيائية، وليس إحداثيات DRAM؛ أعد ترتيب
الإحداثيات ولن تلاحظ الحواجز الموجودة في الأعلى أبداً.
لكن إعادة توصيل DRAM أمر سهل. البت المذكور أعلاه هو وضع bank-swizzle في DCT، وهو مجرد واحد من العشرات التي تتحكم في إعادة تعيين العناوين في الطبقة النهائية — كل ما عليك فعله هو العبث بها لإسقاط كل ما بُني فوقها. الجزء الأصعب بعد ذلك هو الحفاظ على استقرار المنصة بينما تكون ذاكرة النظام بأكملها مشوشة تحتها.