
The first analysis framework for CPU microcode
Custom Processing Unit هي أول إطار عمل للتحليل الديناميكي قادر على ربط (hook) وتصحيح وتتبّع المايكروكود الخاص بالمعالج على مستوى البرمجيات.
يعمل من خلال الاستفادة من تعليمات غير موثقة في معالجات Intel تتيح الوصول إلى CRBUS. باستخدام مفكّك مايكروكود الخاص بنا، قمنا بهندسة عكسية لكيفية استخدام المعالج لـ CRBUS، ومن خلال محاكاة هذه التفاعلات نتحكم بالكامل في المعالج.
ستجد إطار التحليل الثابت كشجرة فرعية في مجلد هذا، أو على https://github.com/pietroborrello/ghidra-atom-microcode.
اطّلع على الشرائح التي تصف هذا العمل هنا.
ملاحظة: يتطلب Custom Processing Unit معالجًا مفتوح القفل الأحمر (Red-Unlocked): حاليًا، فقط معالجات Goldmont (GLM) لديها فك قفل أحمر عام. اختبرنا Gigabyte GB-BPCE-3350C مع خطوة معالج (stepping) 0x9 و0xa (cpuid 0x000506C9 و0x000506CA).
يتكون Custom Processing Unit من تطبيق UEFI وعدد قليل من المكتبات. يتفاعل تطبيق UEFI مع معالج GLM، بينما توفر المكتبات أدوات مساعدة مختلفة لتجميع المايكروكود في تطبيق UEFI وتحليل مخرجاته.
GNU_EFI_DIR=<path_to_gnu_efi> make
سيؤدي هذا إلى بناء ملفات المايكروكود المصدرية وتطبيق UEFI في cpu.efi.
انسخ cpu.efi إلى مجلد \EFI\ في مفتاح USB، وأدخله في GLM ثم أقلع إلى EFI shell.
نفّذ map -r في EFI shell لتحديد جهاز مفتاح USB و <deviceid>: لتركيبه.
شغّل ./cpu.efi لطباعة المساعدة:
Usage:
patch: <tool> p
patch & exec: <tool> x
perf: <tool> f
zero out m&p: <tool> z
hook: <tool> h [m&p idx] [uop addr] [patch addr]
template: <tool> m
dump imms: <tool> di
dump rom: <tool> dr
dump msrs: <tool> dm
dump SMM: <tool> ds [address] [size]
cpuid: <tool> c [rax] [rcx]
rdmsr: <tool> rm [msr]
wrmsr: <tool> wm [msr]
read: <tool> r [cmd] [addr]
write: <tool> w [cmd] [addr] [value]
invoke: <tool> i [addr]
update ucode: <tool> u [size]
ldat read: <tool> lr [port] [array] [bank] [idx] [addr] [optional size]
ldat write: <tool> lw [port] [array] [bank] [idx] [addr] [value]
يوفر cpu أدوات مساعدة لتشغيل تعليمات بسيطة من سطر الأوامر:
يوفر cpu واجهات لروتينات معقدة في المعالج من المثير تنفيذها لدراسة سلوك المعالج:
u: تحديث مايكروكود المعالج باستخدام التصحيح الموقّع المقدمf: جمع عدادات الأداء أثناء تشغيل المايكروكوديوفر cpu واجهات خام للتعليمات غير الموثقة udbrd و udbgwr.
أكثر الأوامر إثارة للاهتمام التي توفرها هي:
يعرض cpu روتينات الوصول إلى LDAT للقراءة والكتابة. حدّد المعاملات [port] [array] [bank] [idx] [addr] للقراءة أو الكتابة هناك.
المنافذ المثيرة للاهتمام هي:
يرجى ملاحظة أن الوصول إلى بعض هذه المكونات الداخلية قد يتسبب في تجمّد المعالج.
يوفر cpu وظائف لتثبيت التصحيحات في المايكروكود.
bios/ucode_patches/ucode_patch.u (انظر إلى التصحيحات الأخرى للحصول على أمثلة)cpu.efi p لتثبيت التصحيح على العنوان المحدد في .org.لاحظ أنه في المايكروكود، فقط العناوين بين 0x7c00 و 0x7e00 قابلة للكتابة وذات معنى للتصحيح.
عند تشغيل cpu.efi x، سيتم أيضًا تنفيذ المايكروكود المصدَّر وطباعة السجلات rax, rbx, rcx, rdx كنتيجة.
لتنفيذ المايكروكود تلقائيًا عند أحداث معينة في المعالج أو نقاط معينة في المايكروكود، يستخدم cpu خاصية المطابقة والتصحيح (Match and Patch).
إنها تحدّد عنوان مايكروكود للربط (hook) وعنوان المايكروكود الذي سيتم القفز إليه عند تفعيل الربط.
z: يعيد تعيين جميع إعدادات المطابقة والتصحيح.h: يثبّت خطافًا (hook)، مع إعطاء فهرس (0-0x20)، وعنوان للربط (0-0x7c00)، وعنوان هدف للتنفيذ (0x7c00-0x7e00).من خلال تثبيت خطافات متعددة وتنفيذ تعليمة بشكل مستمر، يستطيع cpu تتبع العمليات الدقيقة (microoperations) التي تنفذها تلك التعليمة وتفريغها. للتتبع:
// [TRACED INSTRUCTION HERE] في get_trace_clock_at().cpu.efi m.
سيؤدي ذلك إلى إنشاء ملف trace.txt يحتوي على جميع العناوين التي تم الوصول إليها.uasm-lib/uasm.py -t trace.txt > parsed_trace.txt.
سيولّد تتبعًا كاملاً للمايكروكود الذي تم تنفيذه أثناء التعليمة.لاحظ أن uasm.py سيستخدم ملفات ms_arrayX.txt الموجودة في مجلده لإنشاء تفكيك (disassembly) للتعليمات الدقيقة المنفذة. هذه الملفات مخصصة لمعالجات GLM ذات الخطوة (stepping) 0x9 (cpuid 0x000506C9). يرجى توليد المصفوفات المناسبة إذا كان لديك خطوة مختلفة.
يمكنك استخدام وظائف تفريغ LDAT لهذا الغرض.
يحتوي المعالج على مخازن مختلفة غير قابلة للوصول من المعمارية، ونحن نوفر روتينات لتفريغها:
smm: SMROM (أو أي عنوان آخر مع تعطيل حماية SMM)rom: ROM الداخليةimms: القيم المباشرة المثبتة في المعالج (hardcoded immediates)msrs: إعدادات MSRs الداخليةنوفر مُجمِّعًا (assembler) يولّد ملفات رأس (header files) ليتم تجميعها في تطبيق UEFI cpu.efi.
انظر إلى التصحيحات المرفقة في bios/ucode_patches للتعرف على بناء الجملة (syntax).
وهو يدعم العمليات البسيطة والوسوم (labels).
جمّع تصحيح مايكروكود باستخدام uasm.py -i ucode_patch.u -o ucode_patch.h.
سيتم تجميع cpu.efi وسيتضمن تلقائيًا تصحيح المايكروكود الذي تريد تطبيقه.
الملف: code_patch.u
.org 0x7c00
rax:= ZEROEXT_DSZ32(0x00001337)
rbx:= ZEROEXT_DSZ32(0x00001337)
rcx:= ZEROEXT_DSZ32(0x00001337)
rdx:= ZEROEXT_DSZ32(0x00001337)
أعد التجميع، ثم شغّل في GLM:
cpu.efi z # zero out match & patch
cpu.efi p # apply the patch
cpu.efi h 0 0x0428 0x7c00 # rdrand entry point
الآن في كل مرة يتم فيها تنفيذ rdrand، سيعيد القيمة 0x1337 في السجلات.
نُشر عملنا في ورقة بحثية في مؤتمر WOOT 2023:
@inproceedings{Borrello2023CustomProcessingUnit,
title = {{CustomProcessingUnit}: Reverse Engineering and Customization of Intel Microcode},
author = {Borrello, Pietro and Easdon, Catherine and Schwarzl, Martin and Czerny, Roland and Schwarz, Michael},
booktitle = {IEEE Workshop on Offensive Technologies (WOOT 23)},
year = {2023},
}
يمكن تشغيل التجارب الموصوفة في الورقة باستخدام:
cpu.efi e [exp_idx]
مع [exp_idx]: