
كاشف روتكيت لينكس يعتمد على eBPF باستخدام تحليل متعدد القنوات عبر الرؤى (sched_switch, NMI, /proc) لكشف DKOM والتلاعب بنقاط التتبع وإخفاء العمليات مع التحقق من التكامل على مستوى العتاد.
تحليل سلامة العمليات النظامية ورؤية متقاطعة
"سأغني، لذا أشرق بشدة، SPiCa..."
SPiCa هو كاشف روتكيت لنظام لينكس يعتمد على eBPF ومكتوب بلغة رست. الاسم مستوحى من أغنية Hatsune Miku SPiCa والنجم الذي تشير إليه — سبيكا (ألفا العذراء)، ألمع نقطة في برج العذراء. ما يبدو كنجم واحد بالعين المجردة هو في الواقع ثنائي طيفي: نجمان في مدار متبادل، لا يمكن تمييزهما كجسمين منفصلين دون قياس أطيافهما. يطبق SPiCa نفس المبدأ على مراقبة النواة: عدة قنوات مستقلة تقيس نفس حالة النواة من آليات متميزة فيزيائيًا، والروتكيت الذي يكتم إحداها يفضح بواسطة الأخرى.
إخلاء مسؤولية: تم إنشاء أو إعادة هيكلة أجزاء كبيرة من قاعدة الشيفرات هذه بمساعدة GLM. تم تطبيق اختبارات دقيقة وتصميم تكراري، ولكن يُرجى مراجعة الشيفرة من حيث الأمان والأداء قبل الاستخدام الإنتاجي.
صُمم SPiCa لهزيمة الخصم المقيد بـ eBPF — مهاجم يتمتع بصلاحيات مرتفعة (CAP_BPF أو CAP_SYS_ADMIN) ويقوم بتحميل برنامج eBPF ذو صلاحيات في النواة. هذا الخصم أضعف جوهريًا من روتكيت LKM لأن مدقق BPF يفرض قيودًا صارمة:
مع حظر LKMs بواسطة بوابة LSM بعد الإقلاع، يبقى هذا الخصم المقيد هو التهديد الواقعي المتبقي. آليات SPiCa المضادة للتهرب معايرة لهذا التهديد — كل دفاع صريح بشأن ما يغطيه وما لا يغطيه.
init_module. SPiCa يرفع المستوى الأدنى بحجب ناقل LKM الأسهل ولكنه لا يحد من الخصم عند المستوى الأعلى.SPiCa هو طبقة الملاذ الأخير في مجموعة دفاع في العمق، وليس بديلاً عن الطبقات التي تعلوه.
يشغل SPiCa أربعة برامج eBPF مرتبطة بخطافات النواة، بالإضافة إلى محرك كشف في مساحة المستخدم يربط ناتجها عرضيًا مع رؤية النظام لنفسه (/proc).
الخاصية البنيوية الرئيسية: لا يمكن للروتكيت كتم جميع القنوات الثلاث في وقت واحد دون أن يصبح الكتم نفسه قابلاً للكشف أو مزعزعًا للاستقرار. كتم NMI يتطلب تعديل IDT (جدول واصف المقاطعات)، مما يسبب ذعرًا في معظم النوى. هذه هي "القنبلة الحية" — الطريق الوحيد للعمى الكامل للمهاجم هو طريق من المحتمل أن ينهار النظام.
sched sees it, /proc doesn't → DKOM NMI finds sched's heartbeat stopped → TAMPER sched goes globally silent, /proc != empty → SILENT
كل فئة كشف هي حكم تفاضلي: تباين بين قناتين أو أكثر. محرك الكشف هو دالة خالصة فوق سجل النظام + لقطة /proc + طوابع زمنية للقنوات — لا إدخال/إخراج، لا آثار جانبية، قابلة للاختبار بالكامل بالوحدات.
### إعادة تصميم NMI: من المراقبة إلى التكامل
في التصميم الأصلي، كانت NMI قناة مراقبة عمليات ثانية تقوم بأخذ عينات من وحدة المعالجة المركزية والإبلاغ عن المهمة الجاري تشغيلها. كان هذا زائدًا عن الحاجة: `sched_switch` تراقب بالفعل جدولة العمليات، وكانت NMI تأخذ نفس البيانات عبر آلية مختلفة. كلف هذا التكرار ما يقرب من 1000+ حدث/ثانية/CPU في الحلقة العازلة من بيانات العملية والتي تؤكد في 99.999% من الوقت "نعم، المجدول يفعل ما يفعله المجدول."
في البنية المعاد تصميمها، **تم إعادة استخدام NMI من مراقبة العمليات إلى التحقق من سلامة نقاط التتبع (tracepoint).** لم تعد تُبلغ عن العملية التي تعمل على وحدة المعالجة المركزية. بدلاً من ذلك، تتحقق من أن `sched_switch` تعمل بالفعل عن طريق قراءة إشارة نبض مشتركة في قسم `.bss`. هذا:
1. يلغي حوالي 99% من حركة مرور الحلقة العازلة الخاصة بـ NMI (أحداث شبه صفرية في الحالة المستقرة)
2. يكتشف بشكل مباشر انفصال نقاط التتبع، وقمعها، وفشل إرفاق BTF (خلل BTF الأصلي — انظر [§11](#11-the-btf-bug-incident))
3. يعمل من مقاطعة أجهزة، خارج مسار إرسال نقاط التتبع — محصن ضد `bpf_override_return`، واعتراض kprobe، والتلاعب بمصفوفة الدوال
4. يقرأ المتغيرات العامة في `.bss` عبر الوصول المباشر للذاكرة، وليس مساعدات BPF — محصن ضد `fmod_ret` على الدوال المساعدة
---
## 3. قناة مراقبة sched\_switch
برنامج eBPF ملحق بنقطة التتبع `sched_switch` يتم تشغيله في كل مرة يقوم فيها النواة بجدولة عملية على وحدة معالجة مركزية. يقرأ معرف العملية (PID) واسم الأمر (comm) الخاصين بالمهمة الواردة مباشرة من وسيطات نقطة التتبع باستخدام قراءات تقليدية (غير BTF) ذات إزاحة ثابتة:```
ctx.read_at::<u32>(56) → next_pid
ctx.read_at::<[u8;16]>(40) → next_comm
متعمد عدم استخدام BTF/CO-RE. تخطيط وسيطات نقاط التتبع ثابت عبر إصدارات النواة (فهي جزء من واجهة ABI لنقاط التتبع). استخدام الإزاحات المبرمجة يجنب هشاشة إصدارات النواة التي قد تسببها تنقل بنى struct عبر BTF. هذا اختيار تصميمي متعمد موثق في §11.
في كل استدعاء، يقوم البرنامج بما يلي:
next_pid و next_comm من سياق نقطة التتبعProcessInfo باستخدام XOR مع BASE_KEYsc_schedbpf_ktime_get_ns() إلى المتغير العام .bss SCHED_HEARTBEAT — النبضة التي يراقبها مدقق سلامة NMIيتجنب البرنامج عمداً استخدام bpf_get_current_pid_tgid() في هذا السياق. في وقت sched_switch، تكون "المهمة الحالية" هي المهمة الخارجة، وليست الواردة. توفر وسيطات نقطة التتبع هوية العملية الصحيحة (الواردة).
يستخدم محرك الكشف قاعدة زمنية أحادية رتيبة: نانوثانية منذ بدء تشغيل عملية SPiCa (Instant::now() منذ دخول run_detection()). عندما يصل حدث جدولة، يخزن معالج الحدث now المقدم من المتصل (نانوثانية محلية للعملية)، وليس قيمة bpf_ktime_get_ns() من eBPF المضمنة في الحدث. هذا يتجنب عدم تطابق القاعدة الزمنية الذي قد يحدث إذا اختلط زمن إقلاع النواة بالزمن المحلي للعملية — وهو خطأ كان موجوداً في الإصدارات السابقة وتسبب في فشل جميع مسندات البقاء بصمت.
برنامج NMI ملحق بعداد أداء عتادي (HW_CPU_CYCLES) ينطلق عند مستوى مقاطعة العتاد. لا يمكن تعطيل NMIs باستخدام cli — قمعها يتطلب إعادة برمجة PMU أو ربط IDT، وكلاهما صاخب وزعزعة للاستقرار.
آلية فحص السلامة بسيطة للغاية:``` .bss (shared within SPiCa's ELF object — all programs see the same memory): SCHED_HEARTBEAT ← written by sched_switch on every invocation NMI_LAST_HB ← NMI's record of the last heartbeat it observed NMI_FIRST_TICK ← first NMI invocation timestamp (grace period reference) NMI_LAST_EMIT ← throttle: last event emission timestamp
sched_switch runs → SCHED_HEARTBEAT = bpf_ktime_get_ns()
NMI fires (once per second, throttled): if SCHED_HEARTBEAT == NMI_LAST_HB: if past grace period (5 seconds since first NMI tick): → sched_switch stopped running → emit event_type=1 (TAMPER) else: → sched_switch is alive → emit event_type=0 (heartbeat OK) NMI_LAST_HB = SCHED_HEARTBEAT
### لماذا يكتشف هذا كل هجوم في النطاق
| الهجوم | ما يحدث | ما يراه NMI |
|---|---|---|
| تم فصل نقطة التتبع عن مصفوفة الدوال | يتوقف sched\_switch عن التنفيذ | يتجمد `SCHED_HEARTBEAT` → TAMPER |
| خلل BTF / فشل الإرفاق (صامت) | لا يتم تنفيذ sched\_switch أبدًا | يبقى `SCHED_HEARTBEAT` صفرًا → TAMPER (بعد فترة السماح) |
| `bpf_override_return` على دالة جدولة | إذا منع نقطة التتبع من الإطلاق | يتجمد `SCHED_HEARTBEAT` → TAMPER |
| تصحيح البايت كود في مكانه | يتطلب كتابة عشوائية في النواة (على مستوى LKM) | خارج نموذج تهديد eBPF |
| معالجة مؤشر المستهلك للمخزن المؤقت الحلقي | أحداث sched لا تصل إلى مساحة المستخدم | لا يزال `SCHED_HEARTBEAT` يتقدم (البرنامج يعمل) → لا TAMPER خاطئ؛ تكتشف مساحة المستخدم عبر `max(sched_last)` stale → SILENT |
### لماذا `.bss` تحديدًا
متغيرات `.bss` العامة تُخزن في قسم البيانات الداخلي لبرنامج BPF، الذي يديره المُحمل بواسطة مصفوفة خريطة داخلية. وهي:
- **غير قابلة للتثبيت بشكل منفصل** — لا تظهر كخرائط مسماة في `/sys/fs/bpf/`
- **غير قابلة للاعتراض عبر خطافات `bpf_map_update_elem`** — كتابات `.bss` هي تخزين مباشر في الذاكرة، وليست استدعاءات نظام لتحديث الخريطة. لم تعد آلية `sc_canary` القديمة (مقارنة نسخة `.bss` مع نسخة خريطة مسماة للكشف عن اعتراض `bpf_map_update_elem`) ضرورية.
- **مشتركة بين البرامج في نفس كائن ELF** — يتواصل sched\_switch و NMI عبر `.bss` بدون أي واجهة خارجية
### المناعة ضد الاعتراض القائم على BPF
مُدقق سلامة NMI محصن هيكليًا ضد هجمات تجاوز BPF بسبب خاصية أساسية: `bpf_override_return` يعترض استدعاءات **الدوال**، لكن مدقق NMI لا *يستدعي* الأشياء التي يتحقق منها — بل *يقرأ ذاكرة `.bss` مباشرة*. لا يمكنك تجاوز قيمة الإرجاع لقراءة ذاكرة لأن قراءة الذاكرة ليست استدعاء دالة.
بالإضافة إلى ذلك:
- `bpf_probe_read_kernel` (المستخدم لقراءة هياكل النواة في التصاميم البديلة) هو مساعد آمن ضد الأخطاء يقبل أي عنوان — لكن تصميم SPiCa للنبضات عبر `.bss` لا يحتاجه حتى. يقرأ المدقق متغيرات `.bss` العامة عبر تعليمات تحميل مباشرة.
- برنامج NMI يعمل في سياق NMI، حيث تكون kprobes غير موثوقة هيكليًا (تؤجلها النواة أو تمنعها). هجوم قائم على kprobe ضد تنفيذ المدقق يصطدم بالعتاد.
### دلالات أحداث NMI
المخزن المؤقت الحلقي NMI (`sc_nmi`) يحمل أحداثًا خفيفة الوزن:
| `event_type` | المعنى | إجراء مساحة المستخدم |
|---|---|---|
| 0 | نبضات — NMI حي، sched\_switch حي | تحديث طابع زمني `last_nmi_heartbeat` |
| 1 | TAMPER — NMI حي، نبضات sched\_switch مجمدة | طباعة `[TAMPER]` فورًا |
تصدر الأحداث مرة واحدة على الأكثر في الثانية (مقيدة بـ `NMI_LAST_EMIT`). إذا أصبح المخزن المؤقت الحلقي NMI صامتًا لأكثر من 5 ثوانٍ، تطلق مساحة المستخدم `[SILENT]` — قناة NMI نفسها ميتة.
---
## 5. منطق الكشف```mermaid
graph TD
subgraph RING0["Kernel Space: Four eBPF Programs"]
direction TB
SCHED_P["TracePoint, sched_switch<br/>read next_pid, next_comm<br/>write SCHED_HEARTBEAT (.bss)<br/>XOR obfuscate → sc_sched"]
NMI_P["PerfEvent hardware NMI<br/>read SCHED_HEARTBEAT (.bss)<br/>compare to NMI_LAST_HB<br/>frozen → event_type=1 (TAMPER)<br/>alive → event_type=0 (heartbeat)<br/>→ sc_nmi"]
LSM_P["BPF LSM, kernel_read_file<br/>READING_MODULE<br/>gate=0: allow + log<br/>gate=1: EPERM + log → sc_lsm"]
WATCH_P["TracePoint, sched_process_exit<br/>current == SPICA_PID (.bss)? → sc_wd flag"]
end
subgraph RING3["User Space: Differential Engine"]
ENGINE["SPiCa (Tokio async)"] -->|XOR deobfuscate| RB_S[(sc_sched RingBuf)]
ENGINE -->|event_type=0: heartbeat<br/>event_type=1: TAMPER| RB_N[(sc_nmi RingBuf)]
ENGINE -->|raw read| RB_L[(sc_lsm RingBuf)]
ENGINE -->|read_dir| PROC[" /proc"]
RB_S --> FSM{Detection FSM}
PROC --> FSM
FSM -->|scheduled, absent /proc, >2s| D1["[DKOM]"]
FSM -->|in /proc, never seen by sched, >5s| D2["[GHOST]"]
RB_N -->|event_type = 1| D3["[TAMPER]"]
FSM -->|sched channel silent, /proc ≠∅| D4["[SILENT]"]
FSM -->|raw getdents64 ≠ libc readdir| D9["[HOOK]"]
RB_S -->|same TGID, different start_time_ns| D5["[DUPE]"]
RB_L -->|allowed = 1| D7["[LKM-ALLOW]"]
RB_L -->|allowed = 0| D8["[LKM-DENY]"]
WATCH_P -.->|pin exists at startup| D6["[WATCHDOG]"]
end
classDef kernbox fill:#fdf2f8,stroke:#9333ea,stroke-width:2px,color:#581c87;
classDef userbox fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e3a8a;
classDef alertbox fill:#fff7ed,stroke:#ea580c,stroke-width:1px,color:#7c2d12;
classDef storage fill:#f8fafc,stroke:#64748b,stroke-width:1px;
class RING0 kernbox;
class RING3 userbox;
class D1,D2,D3,D4,D5,D6,D7,D8,D9 alertbox;
class RB_S,RB_N,RB_L,PROC storage;
SILENT هو حكم على مستوى القناة، وليس لكل عملية. يتم تفعيله عندما:
قناة sched ميتة: max(sched_last) عبر جميع سجلات السجل قديم بعد CHANNEL_DEAD_NANOS بينما /proc غير فارغ. الحارس غير الفارغ /proc هو ضمان النشاط: على أي نظام لينكس قيد التشغيل، يكون /proc غير فارغ (init، خيوط النواة، عمال kwork)، والمجدول ليس خاملاً أبداً (أجهزة ضبط الوقت، منتظرو الإدخال/الإخراج، ردود RCU). يشير max(sched_last) القديم على نظام غير فارغ إلى أن القناة ماتت — وليس أن النظام خامل.
قناة NMI ميتة: لم يصل حدث نبضة القلب (event_type=0) من الحلقة العازلة لـ NMI لأكثر من 5 ثوانٍ. هذا يعني أن حدث أداء NMI توقف عن العمل — إما أنه تم فصل حدث الأداء أو إعادة برمجة PMU.
كلا الفحصين له فترة تهدئة لمدة 30 ثانية لمنع إغراق التنبيهات.
[HOOK])يقرأ SPiCa /proc عبر آليتين مستقلتين في كل نبضة:
استدعاء getdents64 الخام (read_tgids()) — يستخدم Rust std::fs::read_dir هذا مباشرة عبر libc::syscall(SYS_getdents64, ...) متجاوزاً جميع ربطات دالات libc. لا تستطيع روت كيت LD_PRELOAD اعتراض هذا المسار.
readdir من libc (read_tgids_libc()) — يستدعي libc::opendir / libc::readdir عبر FFI، والذي يمر عبر الرابط الديناميكي ويمكن اعتراضه بالكامل بواسطة ربطات /etc/ld.so.preload.
إذا رأى getdents64 PIDs لا تراها readdir من libc، فإن روت كيت في مساحة المستخدم يقوم بربط readdir لإخفاء العمليات. يقوم SPiCa بتفعيل [HOOK]:```
[HOOK] 3 PID(s) hidden from libc readdir — LD_PRELOAD rootkit suspected
تحوّل هذه التقنية امتياز SPiCa على مستوى النواة إلى كشف نشط لجذور مساحة المستخدم. مسار استدعاء النظام الخام هو الحقيقة الأساسية — لا يمكن لأي خطاف في مساحة المستخدم إخفاؤه. مسار مكتبة libc هو المنظر "المتصوّر" الذي ستراه أداة عادية (مثل `ps`، `ls`). التناقض هو دليل لا لبس فيه على اعتراض المكتبة.
**الجذور التي تم اكتشافها بواسطة `[HOOK]`:**
| الجذر | آلية الإخفاء | مكتشف |
|---------|-----------------|----------|
| Symbiote | طفيلي LD_PRELOAD، يخطف `readdir` | نعم (عند الإخفاء النشط) |
| JynxKit | LD_PRELOAD، إخفاء `MAGIC_GID` عبر `readdir` | نعم |
| Azazel | LD_PRELOAD، خطافات `readdir` + `stat` | نعم |
| Medusa/OrBit | LD_PRELOAD، خطف `readdir` + سرقة بيانات الاعتماد | نعم |
**تم اختباره ضد Symbiote حقيقي:** تم نشر عينة Symbiote حية (SHA256 `f55af21f...`، MalwareBazaar) عبر `/etc/ld.so.preload` على جهاز ظاهري يعمل بنظام Ubuntu 24.04. العينة تخطف `readdir`, `readdir64`, `stat`, `fstatat`, `pam_authenticate`, `pcap_loop`, `recvmsg`, `fopen`, `read`, `execve`. عندما يخفي خطاف LD_PRELOAD بشكل نشط رقم عملية من `readdir`، يُطلق SPiCa `[HOOK]` خلال دورة علامة واحدة (<1 ثانية). عندما يتم تحميل Symbiote ولكنه سلبي (لا يخفي بنشاط)، يُنتج SPiCa صفر من النتائج الإيجابية الكاذبة.
### نافذة السماحية
نافذة سماحية مقدارها 50 مللي ثانية تمنع النتائج الإيجابية الكاذبة في العمليات المستحدثة حديثًا. عمليات التحقق من القناة على مستوى SILENT لديها فترة سماح قدرها 5 ثوانٍ (مرجع `NMI_FIRST_TICK` لبرنامج NMI) بحيث لا يؤدي زمن بدء التشغيل إلى إنشاء تنبيهات TAMPER كاذبة.
---
## 6. سرية العنوان المحدودة بواسطة المدقق
### تعريف
**سرية العنوان المحدودة بواسطة المدقق** هي خاصية أمنية حسابية تصمد تحت نموذج الخصم المقيد بـ eBPF. تنص على:
> بالنظر إلى خصم يمكنه تحميل برامج eBPF (CAP\_BPF) ولكنه مقيد بمدقق BPF (حلقات محدودة، مساعدات مقيدة، لا كتابة عشوائية في النواة)، فإن عنوان النواة لقسم بيانات `.bss` لبرنامج BPF يكون من غير الممكن حسابيًا اكتشافه.
### الآليات الأربع
الخاصية هي تركيب من أربعة حواجز مستقلة:
1. **kASLR** — عشوائية تخطيط مساحة عنوان النواة تقوم بعشوائية منطقة كومة النواة حيث يتم تخصيص ذاكرة خريطة BPF (بما في ذلك خرائط الإسناد الخلفي `.bss`). يتغير العنوان الدقيق في كل إقلاع.
2. **حد تعليمات المدقق** — يحد مدقق BPF إجمالي التعليمات لكل برنامج إلى ~1 مليون ويطلب حلقات تنتهي بشكل مؤكد. يمكن لبرنامج المسح الخاص بالخصم استجواب N ≈ 10^6 عنوان على الأكثر لكل تحميل عبر `bpf_probe_read_kernel`. بالنظر إلى مساحة بحث عشوائية بواسطة kASLR، فإن احتمال النجاح لكل برنامج لا يُذكر.
3. **بوابة الوصول إلى الخريطة عبر LSM** (راجع [§7](#7-lsm-map-access-gate)) — بدون البوابة، يمكن للخصم تعداد خرائط BPF حسب المعرف (`BPF_MAP_GET_NEXT_ID` → `BPF_MAP_GET_FD_BY_ID` → `BPF_MAP_LOOKUP_ELEM`) وقراءة محتويات `.bss` مباشرة. تزيل البوابة هذا المسار السهل، مما يُجبر الخصم على مسار فحص الذاكرة المحدود بواسطة المدقق.
4. **موضع `.bss`** — لا تظهر المتغيرات العامة `.bss` في واجهات تعداد الخرائط المسماة بأسماء مقروءة إنسانياً. خريطة الإسناد الخلفي الداخلية `.bss` تُسمى `.bss` بواسطة libbpf/aya، ولكن محتوياتها (المتغيرات العامة الفعلية) لا يمكن الوصول إليها إلا إذا كان لديك واصف ملف الخريطة (map fd). يتطلب واصف ملف الخريطة إما جدول واصفات عملية التحميل أو معرف الخريطة (المحظور بواسطة البوابة).
### هيكل الحجة الرسمي```
Adversary's goal: locate SPiCa's .bss in kernel virtual memory
Search space: kernel heap region, kASLR-randomized (~2^30 entropy)
Path A — map enumeration (blocked):
BPF_MAP_GET_NEXT_ID → BPF_MAP_GET_FD_BY_ID → BPF_MAP_LOOKUP_ELEM
→ blocked by LSM gate (§7) for non-SPiCa processes
Path B — memory scan (bounded):
bpf_probe_read_kernel(addr, buf, len) — fault-safe, accepts any addr
Per-program capacity: N ≈ 10^6 probes (instruction limit)
Success probability per load: N / |search space| ≈ 10^6 / 2^30 ≈ 10^-24
Can reload programs, but: each load is a syscall (observable), and
the target address doesn't change between loads (same boot session)
Path C — timing side channel (theoretical):
bpf_probe_read_kernel timing varies on fault vs success
Binary search over the heap could reduce scan complexity to O(log |A|)
→ O(30) probes, well within instruction budget
LIMITATION: must be acknowledged. Mitigated by rate-limiting BPF_PROG_LOAD
via the LSM gate (future work).
معظم أبحاث أمان BPF تتعامل مع المدقق (verifier) كـ سطح هجوم (أخطاء المدقق، عدم الاتساق، رش JIT). هذا العمل يعكس الإطار: قيود المدقق هي أداة دفاعية تحدد نطاق بحث الخصم. السرية هنا ليست تشفيرية (ليست AES)؛ إنها حسابية — يحدها ما يسمح به المدقق للخصم من حسابات.
bpf_probe_read_kernel يمكن ملاحظة توقيته (الخطأ مقابل النجاح يستغرق دورات مختلفة). البحث الثنائي الزمني عبر الكومة (heap) أكثر كفاءة نظريًا من المسح الخطي. حد التعليمات يقيد عمليات الفحص لكل برنامج، لكن البحث الثنائي قد يقلل عدد عمليات الفحص إلى O(log |A|) ≈ 30. هذا قيد حقيقي. التخفيف: تحديد معدل BPF_PROG_LOAD عبر بوابة LSM.المتغيرات العامة .bss مدعومة بخريطة BPF داخلية. أي عملية لديها CAP_BPF يمكنها تعداد جميع الخرائط على النظام:```
bpf(BPF_MAP_GET_NEXT_ID, …) → iterate all map IDs
bpf(BPF_MAP_GET_FD_BY_ID, id) → get fd to any map
bpf(BPF_MAP_LOOKUP_ELEM, fd, key, value) → read map contents
ضد خصم eBPF (الذي لا يمكنه استدعاء syscalls)، يتم إخفاء `.bss`. ضد جذر userspace، إنها خريطة قياسية — قابلة للقراءة بالكامل. بوابة LSM تسد هذه الفجوة.
### الدفاع
خطاف BPF LSM على استدعاء النظام `bpf` يفحص أوامر الوصول إلى الخريطة:```
hook = "bpf"
read cmd (arg 0)
if cmd == BPF_MAP_GET_FD_BY_ID:
read map_id from userspace bpf_attr (bpf_probe_read_user)
if map_id matches any of SPiCa's stored IDs (.bss):
if caller_tgid != SPICA_PID:
return -EPERM
تُكتب معرفات الخريطة إلى .bss بواسطة أداة تحميل مساحة المستخدم مباشرة بعد تحميل البرنامج، وقبل تفعيل ربط LSM (نفس نمط التوقيت الموجود في sc_gate الحالي لحجب LKM). لا حاجة لـ BTF — cmd و map_id يأتيان من وسائط استدعاء النظام، وليس من بنى kernel النواة.
جراحي: يحجب فقط الوصول إلى معرفات الخريطة المحددة لـ SPiCa. أدوات BPF الأخرى للعمليات الأخرى (tcpdump، bpftrace، bcc) تصل إلى خرائطها الخاصة ولا تتأثر.
/proc/pid/mem — يمكن لعملية جذر أخرى قراءة ذاكرة عملية SPiCa مباشرة عبر ptrace، متجاوزة استدعاء نظام BPF بالكامل. هذا قيد أساسي: لا يمكنك الحماية من عملية بنفس مستوى الصلاحية تقرأ ذاكرتك عبر /proc/pid/mem. الدفاع: إرسال السجلات إلى مضيف خارجي (إذا كان المهاجم يستطيع قراءة الذاكرة المحلية، يمكنه أيضًا كبت التنبيهات المحلية — فقط التسجيل عن بُعد يساعد).على المضيفات المزودة بـ TPM، يتم الحصول على مفتاح الإبهام XOR ذي الـ 64 بت من TPM2_GetRandom عبر crate tss-esapi (استدعاء مكتبة مباشر لـ libtss2-esys). لا يمر المفتاح عبر أي أنبوب (pipe)، ولا عبر أي وسيط سطر أوامر لعملية فرعية، ولا عبر قرص. إنه موجود فقط في عتاد TPM وفي ذاكرة kernel المتطايرة (خريطة .bss) طوال مدة عملية SPiCa.
على المضيفات التي لا تحتوي على TPM (VM بدون vTPM، حاويات، أجهزة بدون شريحة TPM)، يتراجع SPiCa إلى مفتاح وقت البناء لكل نسخة يتم إنشاؤه من /dev/urandom بواسطة سكريبت البناء. يكون التراجع صاخبًا بشكل مرئي عند بدء التشغيل مع لافتة تحذير.
.bssالقيم التالية موجودة في قسم .bss الخاص ببرنامج eBPF، وتُكتب بواسطة مساحة المستخدم عبر set_global() قبل تحميل أي برنامج:
خرائط BPF المسماة يمكن تعدادها عبر واجهة تكرار الخريطة لاستدعاء النظام bpf() (محجوبة بواسطة بوابة LSM — انظر §7)؛ يتم الوصول إلى المتغيرات العامة لـ .bss عبر نفس الخريطة الداخلية ولكنها ليست مسماة بشكل منفصل ولا قابلة للتثبيت.
يتم إجراء عملية XOR لجميع حقول ProcessInfo باستخدام BASE_KEY ذي 64 بت قبل كتابتها إلى المخازن الحلقية. يُترك حقل event_type بدون إبهام عمدًا حتى تتمكن مساحة المستخدم من قراءته كحارس قبل فك إبهام الباقي.
هذا إبهام ضد تسرب القراءة، وليس تشفيرًا ضد خصم قادر. XOR بمفتاح متكرر من 8 بايتات معرض هيكليًا للنص المعروف: قيم comm المتوقعة ("bash"، "systemd"، "kthreadd") يتم XOR لها ضد النص المشفر تستعيد بايتات المفتاح مباشرة. الدفاع مناسب لخصم eBPF (الذي لا يستطيع قراءة المخزن الحلقي بسهولة — يتطلب نفس فجوة القدرة التي تحمي .bss)، وليس لخصم لديه وصول ثنائي + اعتراض للمخزن الحلقي.
الحالة: مرحلة التصميم. لم يُنفذ بعد. يوثق هذا القسم البنية المستهدفة للورقة البحثية.
ينقل ختم TPM المرتبط بـ PCR حدود توزيع المفاتيح من طبقة البرمجيات إلى السيليكون. يُختم المفتاح في وقت التثبيت مقابل قيم PCR المتوقعة لسجلات تكوين المنصة، ولا يمكن فك ختمه إلا إذا تطابقت حالة إقلاع النظام مع القياسات المتوقعة.
أثناء الإقلاع، يقيس البرنامج الثابت، ومحمل الإقلاع، وkernel النواة المكونات الحرجة في PCRs:
ملاحظة: تخصيص PCR يعتمد على سلسلة الإقلاع. يقيس GRUB kernel إلى PCR 4؛ يقيس systemd-stub إلى PCR 4 وسطر الأوامر إلى PCR 8. يجب أن تتطابق سياسة الختم مع سلسلة الإقلاع المستهدفة.
الختم (وقت التثبيت): يُختم المفتاح ذو 64 بت مقابل قيم PCR المتوقعة باستخدام TPM2_Create مع جلسة TPM2_PolicyPCR. يُخزن الكائن المختم على القرص. إنه مشفر بمفتاح TPM الداخلي ولا يمكن فك تشفيره إلا عندما تتطابق PCRs المحددة.
فك الختم (إقلاع مبكر، مرحلة initramfs): قبل تنفيذ أي كود غير موثوق في مساحة المستخدم، يطلب خطاف initramfs الخاص بـ SPiCa تنفيذ TPM2_Unseal. إذا تطابقت قيم PCR الحالية مع سياسة الختم، يُصدر TPM المفتاح.
الحقن: يُكتب المفتاح إلى .bss عبر set_global() قبل تحميل البرامج.
المصيدة: إذا كان المهاجم قد عدّل kernel (عدم تطابق PCR 4)، أو استبدل initramfs (عدم تطابق PCR 9)، أو غيّر سياسة Secure Boot (عدم تطابق PCR 7)، فإن تجزئات PCR تتباعد. يرفض TPM فك الختم، و يفشل SPiCa بشكل آمن — يرفض البدء بدلاً من العمل بشكل أعمى بمفتاح مخترق.
للوثيقة البحثية، اعرض السياسة القوية وناقش المفاضلة المتعلقة بإعادة الختم في القيود.
الآليتان متكاملتان:
.bss حيث يوجد المفتاح.لا تكفي أي منهما بمفردها. ختم PCR لا يساعد إذا تم اختراق المفتاح في زمن التشغيل (تعداد الخريطة). سرية العناوين لا تساعد إذا تم اختراق النظام قبل بدء SPiCa (initramfs معادٍ).
spica_lsm_modblock، بوابة الوصول للخريطة) في زمن التشغيل ولا تُقاس في أي PCR. الجذور الخفية (rootkit) التي تفصلها بعد الإقلاع لا يلتقطها ختم PCR. ما يلتقط ذلك هو نبضة NMI القلبية (اكتشاف أن نظام الكشف نفسه توقف عن العمل).SPiCa هي طبقة الإنفاذ الأخيرة. إنها تكمل نظامًا مهيأً بشكل صحيح، ولا تحل محل الطبقات أعلاه.```mermaid
flowchart TD
SB["UEFI Secure Boot
─────────────────────────────
Verifies bootloader signature against
the UEFI db certificate store
Measured to PCR 7"]
MS["Kernel Module Signing
─────────────────────────────
CONFIG_MODULE_SIG_FORCE=y
Kernel rejects unsigned .ko at load time"]
IMA["IMA, Integrity Measurement Architecture
─────────────────────────────
Measures file hashes to TPM PCR10
Appraise policy blocks non-matching signatures"]
SPICA["SPiCa
─────────────────────────────
LSM gate: blocks LKM loads + map enumeration
sched_switch + NMI integrity channels
Differential detection: DKOM · GHOST · TAMPER · SILENT · DUPE
PCR-bound key sealing (design phase)"]
SB -->|"boot chain verified"| MS
MS -->|"signed modules only"| IMA
IMA -->|"measured + appraised"| SPICA
classDef firmware fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#78350f
classDef kernel fill:#fdf2f8,stroke:#9333ea,stroke-width:2px,color:#581c87
classDef spica fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e3a8a
class SB firmware
class MS,IMA kernel
class SPICA spica
SPiCa checks all four layers at startup and prints their status.
---
## 11. حادثة خطأ BTF
### ما حدث
أثناء الاختبار على Ubuntu (أحدث نواة)، تسبب عدم توافق BTF في إرفاق برنامج نقطة التتبع `sched_switch` بنجاح ولكن **لم يطلق أي حدث واحد.** أعاد استدعاء النظام `attach()` قيمة `Ok(())`، لذا استمر SPiCa بشكل طبيعي — لكن المخزن الدائري للجدولة بقي فارغًا. لم يتم إطلاق أي تنبيهات اكتشاف لأن محرك الكشف لم يحتوي على بيانات جدولة. **عمل SPiCa أعمى دون أي إشارة إلى الفشل.**
هذا هو أسوأ نمط فشل لأداة أمنية: العمى الصامت.
### لماذا لم يتم اكتشافه
كان محرك الكشف الأصلي يعمل **لكل عملية**: كل سجل عملية كان يحتوي على الطوابع الزمنية `sched_last` و `nmi_last`، وكان يتم حساب النشاط لكل سجل. عندما ماتت sched_switch عالميًا:
1. `sched_live` أصبح خطأ لكل سجل (لا توجد أحداث جدولة جديدة → جميع قيم `sched_last` تنتهي صلاحيتها)
2. الشرط `TAMPER` لكل عملية (`in_proc && nmi_live && !sched_live`) يمكن أن يشتعل، لكنه تطلب استمرار `nmi_live` *باستمرار* لمدة ثانيتين. NMI يأخذ عينات متفرقة (فترة دورة 10M)، لذلك استمر `suspect_since` في إعادة الضبط بسبب تذبذب العينات ولم ينضج أبدًا.
3. الشرط `SILENT` لكل عملية تطلب `sched_live`، والذي أصبح الآن خطأ لكل شيء — انعكس الشرط تحت الظروف التي كان من المفترض أن يكشفها بالضبط.
4. لم يكن هناك **فحص نشاط على مستوى القناة** — لا آلية "هل اشتعلت sched من قبل؟" أو "هل max(sched_last) قديم؟".
بالإضافة إلى ذلك، تم اكتشاف عدم تطابق في الأساس الزمني: قام `sched_last` بتخزين `bpf_ktime_get_ns()` (نانو ثانية بدء تشغيل النواة) بينما تقارن `evaluate()` مع `nanos_since_startup()` (نانو ثانية محلية للعملية). أنتج `wrapping_sub` لهذه الأسس الزمنية المختلفة قيمًا ضخمة، مما جعل جميع تأكيدات النشاط خاطئة ببساطة. لم يعمل منطق الكشف بشكل صحيح أبدًا في الإنتاج — خطأ BTF قام فقط بإخفائه عن طريق منع وصول الأحداث بالكامل.
### كيف يعيد التصميم إصلاحه
| المشكلة | الإصلاح |
|---|---|
| لا يوجد فحص نشاط على مستوى القناة | يقوم `evaluate()` الآن بحساب `max(sched_last)` ويطلق `[SILENT]` إذا كان قديمًا بينما `/proc` غير فارغ |
| TAMPER لكل عملية لم ينضج أبدًا (إعادة ضبط التذبذب) | أصبح TAMPER الآن إشارة مباشرة من برنامج NMI (مقارنة نبضات `.bss`)، وليس آلية FSM لكل عملية مع عتبات |
| SILENT لكل عملية انعكس عندما ماتت sched | أصبح SILENT الآن على مستوى القناة، محسوبًا من الإجماليات، وليس من تأكيدات لكل سجل |
| عدم تطابق الأساس الزمني | يقوم `sched_last` الآن بتخزين الوقت المحلي للعملية (معامل `now`)، وليس `bpf_ktime_get_ns()` |
| NMI كان ملاحظة زائدة | أصبح NMI الآن مدقق سلامة — يكتشف موت sched مباشرة عبر نبضة `.bss` |
---
## 12. القيود المعروفة وسطح الهجوم
### ضمن نموذج التهديد eBPF
| الهجوم | الحالة | ملاحظات |
|---|---|---|
| التلاعب بمؤشر المستهلك للمخزن الدائري | مكتشف (SILENT) | يصبح `max(sched_last)` قديمًا → SILENT. `SCHED_HEARTBEAT` لا يزال يتقدم (البرنامج يعمل) → لا TAMPER خاطئ. |
| تدمير struct حدث الأداء (صفر حقل `state`) | مكتشف (SILENT) | يتوقف NMI عن الإطلاق → لا أحداث نبضات → SILENT على قناة NMI |
| انتحال حقل `task_struct` (الكتابة فوق pid/tgid) | جزئي (DUPE) | إذا تطابق TGID المنتحل مع سجل موجود يحتوي على `start_time_ns` مختلف، يشتعل DUPE. إذا تم انتحال `start_time_ns` أيضًا، فإن هذا يمر دون اكتشاف. |
| فصل برنامج eBPF (إزالة من مصفوفة funcs) | مكتشف (TAMPER) | تجمد نبضة NMI → TAMPER |
| تصحيح البايت كود في مكانه | غير مكتشف | يتطلب كتابة عشوائية للنواة (مستوى LKM) — خارج نموذج تهديد eBPF |
| قناة جانبية زمنية على `bpf_probe_read_kernel` | مخاطرة نظرية | البحث الثنائي على الكومة يمكن أن يجد `.bss` في حوالي 30 استكشافًا. انظر قيود [§6](#6-verifier-bounded-address-secrecy). |
### خارج نموذج التهديد eBPF (معترف به، لم يتم حله)
| الهجوم | الحالة | ملاحظات |
|---|---|---|
| خطاف معالج IDT/NMI | القنبلة الحية | تجاوز كامل هندسيًا. ذعر نواة شبه مؤكد. |
| قمع ثنائي القناة | القنبلة الحية | قم بكبت كل من sched + NMI في وقت واحد. يرث عدم استقرار خطاف NMI. |
| استغلال المدقق | غير هدف | يهرب إلى تنفيذ كود نواة عشوائي. فئة تهديد منفصلة. |
| ptrace / `/proc/pid/mem` | قيود أساسية | قراءة الذاكرة بنفس الامتياز. فقط شحن السجلات خارج المضيف يساعد. |
| تصحيح مؤشر المستهلك + نبضة القلب | مستوى LKM | إذا كان لدى المهاجم كتابة عشوائية للنواة، يمكنه تقديم مؤشر المستهلك وكتابة نبضات مزيفة. لكن الكتابة العشوائية للنواة = مستوى LKM = خارج نموذج التهديد. |
---
## 13. البناء والتشغيل
### المتطلبات الأساسية
- نواة لينكس >= 5.15 مع `CONFIG_DEBUG_INFO_BTF=y` (لخطاف LSM فقط)
- لحظر الوحدة: `CONFIG_BPF_LSM=y` و `lsm=bpf` في سطر أوامر النواة
- رقاقة TPM 2.0 + مكتبة `tpm2-tss` (اختياري؛ يتراجع مع تحذير مرئي)
- سلسلة أدوات Rust الليلية
> **ملاحظة:** لم يعد خطوة `generate-vmlinux` **مطلوبة**. تستخدم برامج eBPF إزاحات نقاط التتبع التقليدية والعامة `.bss` — لا حاجة لتصفح بنية CO-RE/BTF. تم الاحتفاظ بأمر xtask `generate-vmlinux` لاستخدام مستقبلي ولكنه ليس جزءًا من خط البناء.
تحقق من أن BPF LSM نشط: يجب أن يحتوي `cat /sys/kernel/security/lsm` على `bpf`.
### الإعداد```shell
make install-deps # system packages + nightly Rust (pacman/apt/dnf auto-detected)
make install-tools # bpf-linker
make build # compiles eBPF + userspace (no vmlinux generation needed)
make run # sudo ./target/release/spica
### التثبيت في initramfs (حماية الإقلاع المبكر)```shell
sudo make install # spica install — auto-detects Debian (initramfs-tools) or Fedora (dracut)
sudo insmod some_module.ko # should fail with EPERM (gate locked) cat /sys/kernel/security/lsm # should contain 'bpf' ls /sys/fs/bpf/spica_watchdog # exists if previous run was killed ungracefully
### التطوير (ماك أو لينكس)
لا يمكن تشغيل برامج eBPF على macOS. تعمل `cargo check` واختبارات الوحدة لمنطق الكشف؛ أما التحقق الكامل في وقت التشغيل فيتطلب لينكس.```shell
make check # cargo check for workspace
make check-ebpf # cargo check for the eBPF crate (bpfel-unknown-none)
make test # unit tests for detection FSM, key derivation, obfuscation
GetRandom الحالي لـ TPM باستخدام جذر أجهزة كامل للثقة. انظر §9.bpf لمنع تعداد الحالة الداخلية لـ SPiCa من العمليات غير التابعة لـ SPiCa. انظر §7.BPF_PROG_LOAD — توسيع بوابة LSM للحد من معدل تحميل برامج BPF من العمليات غير التابعة لـ SPiCa، للتخفيف من مخاطر القناة الجانبية الزمنية على اكتشاف .bss. انظر §6 القيود.siphasher موجود بالفعل في الشجرة للرمز التكاملي).ترخيص محرك SPiCa: MIT OR Apache-2.0 (مساحة العمل). يصدر برنامج eBPF ترخيص GPL عبر الثابت _license — وهذا مطلب نواة لبرامج eBPF التي تستخدم مساعدات مرخصة بموجب GPL، وينطبق فقط على الرمز البايتي المحمل لـ eBPF، وليس على الثنائي في مساحة المستخدم.
نسب الشخصية: "Hatsune Miku" والأعمال الفنية المرتبطة بها هي ملكية محفوظة لحقوق الطبع لشركة Crypton Future Media, INC. (www.piapro.net). هذا المشروع هو أداة بحثية مستقلة غير تجارية، وليست تابعة لـ Crypton Future Media. تُستخدم الشخصية بموجب ترخيص شخصية Piapro (PCL).
اسم مشروع SPiCa مستوحى من الأغنية الأصلية لـ Toku-P.
| القيد | التأثير على الخصم |
|---|
| الحلقات المحدودة (~1 مليون تعليمة لكل برنامج) | لا يمكنه مسح كل ذاكرة النواة |
| سلامة المؤشرات (الإشارة المباشرة تتطلب هدفًا صحيحًا ومحدودًا) | لا يمكنه متابعة مؤشرات عشوائية |
| الوظائف المساعدة المقيدة (قائمة مسموح بها حسب نوع البرنامج) | لا يمكنه استدعاء kmalloc أو vmalloc أو أي وظيفة تخصيص نواة |
لا كتابة عشوائية للنواة (bpf_probe_write_kernel مقيد بشدة) | لا يمكنه تعديل task_struct أو مصفوفات وظائف نقاط التتبع أو شيفرة برنامج BPF |
| الوصول إلى الخرائط مقيد بالمراجع المحملة | لا يمكنه الوصول إلى خرائط تنتمي لبرامج أخرى (إلا إذا تم تعدادها بواسطة ID — انظر §7) |
| القناة | الآلية | ما يكتمها | تكلفة الكتم |
|---|
/proc | تعداد دليل procfs | DKOM (فصل العملية عن قائمة المهام) | منخفضة — تقنية روتكيت معروفة جيدًا |
sched\_switch | نقطة تتبع eBPF على المجدول | فصل البرنامج عن مصفوفة الوظائف؛ تصفية السياق | متوسطة — تتطلب كتابة نواة على مصفوفة الوظائف |
| NMI | مقاطعة عداد الأداء العتادي → حدث أداء eBPF | ربط معالج IDT/NMI | شبه مؤكد يسبب ذعر النواة — مقاطعة عتادية غير قابلة للإخفاء |
| التنبيه | الشرط | ما يكتشفه |
|---|
[DKOM] | TGID المجدول من قبل النواة غائب عن /proc لأكثر من 2 ثانية | التلاعب المباشر بكائنات النواة — عملية مخفية عن التعداد في مساحة المستخدم |
[GHOST] | TGID موجود في /proc لكن لم يتم رؤيته بواسطة sched_switch لأكثر من 5 ثوانٍ | تزوير /proc — إدخال وهمي لاجتياز فحوصات DKOM |
[TAMPER] | يكتشف NMI تجمد نبضة قلب sched_switch (event_type=1) | فصل نقطة التتبع، أو قمعها، أو فشل BTF/attach |
[SILENT] | max(sched_last) قديم عبر السجل بأكمله بينما /proc غير فارغ؛ أو غياب نبضة قلب NMI لأكثر من 5 ثوانٍ | فقدان الرصد على مستوى القناة — قناة sched أو NMI ميتة |
[DUPE] | نفس TGID مع start_time_ns مختلفة عبر الأحداث | تزوير حقل task_struct — يقوم الروت كيت بتصحيح tgid لانتحال هوية عملية شرعية |
[HOOK] | PIDs مرئية عبر getdents64 الخام ولكنها غائبة عن readdir الخاص بالمكتبة libc | روت كيت LD_PRELOAD — اعتراض مكتبات مساحة المستخدم يخفي العمليات عن ps، ls، والأدوات الأخرى (Symbiote، JynxKit، Azazel، Medusa/OrBit) |
[WATCHDOG] | وجود pin /sys/fs/bpf/spica_watchdog عند بدء التشغيل | تم إنهاء المثيل السابق بشكل غير نظيف (SIGKILL، OOM، تعطل) |
[LKM-ALLOW] | اعتراض READING_MODULE أثناء فتح البوابة (نافذة الإقلاع) | سجل التدقيق: تم تحميل الوحدة قبل قفل البوابة |
[LKM-DENY] | اعتراض READING_MODULE أثناء قفل البوابة | منع insmod/modprobe بعد التهيئة |
| المتغير العام | الغرض | يُكتب بواسطة |
|---|
BASE_KEY | مفتاح إبهام XOR | مساحة المستخدم عند التحميل |
SPICA_PID | TGID الخاص بـ SPiCa (مراقب) | مساحة المستخدم عند التحميل |
SCHED_HEARTBEAT | طابع زمني لحيوية sched_switch | برنامج sched_switch عند كل استدعاء |
NMI_LAST_HB | سجل NMI لآخر نبضة حيوية لـ sched | برنامج NMI عند كل فحص |
NMI_FIRST_TICK | أول ktime لاستدعاء NMI (فترة سماح) | برنامج NMI عند أول استدعاء |
NMI_LAST_EMIT | خنق: آخر ktime لإصدار حدث | برنامج NMI عند كل إصدار |
| PCR | ما يقيسه | الاستقرار |
|---|
| PCR 4 | كود محمل الإقلاع + صورة kernel (يقيس GRUB كليهما) | يتغير عند تحديث kernel |
| PCR 5 | جدول أقسام GPT/MBR، تكوين الإقلاع | مستقر عبر التحديثات |
| PCR 7 | سياسة Secure Boot (SI policy، MOK، db/dbx) | مستقر عبر تحديثات kernel |
| PCR 8 | سطر أوامر kernel (قياسات systemd-stub) | مستقر ما لم يتغير سطر الأوامر |
| PCR 9 | Initramfs (GRUB يقيس initrd هنا) | يتغير عند تحديث initramfs |
| PCR 10 | قائمة قياس IMA (Integrity Measurement Architecture) | يتغير مع قياس الملفات القابلة للتنفيذ |
| السياسة | مختم مقابل | القوة | التكلفة التشغيلية |
|---|
| قوية | PCR 4 + 7 + 9 + 10 | يلتقط تغييرات kernel و initramfs و Secure Boot و IMA | إعادة الختم بعد كل تحديث kernel/initramfs |
| متوازنة | PCR 7 + 10 | يلتقط تغييرات Secure Boot وتقييم IMA؛ مستقر عبر تحديثات kernel | إعادة الختم فقط عند تغيير سياسة Secure Boot أو سياسة IMA |
| دنيا | PCR 7 فقط | يلتقط تغييرات حالة Secure Boot فقط | مستقر جدًا؛ أضعف ربط |
| المصطلح | التعريف |
|---|
| BPF | مرشح حزم بيركلي — محرك تنفيذ داخل النواة للبرامج المعزولة. يمتد BPF الحديث (eBPF) إلى ما بعد الحزم ليشمل التتبع والأمان والشبكات. |
| BTF | تنسيق نوع BPF — معلومات تصحيح النواة التي تسمح للبرامج من نوع CO-RE (تجميع مرة، تشغيل في كل مكان) بالتنقل عبر بنى النواة بشكل محمول. |
| CO-RE | تجميع مرة، تشغيل في كل مكان — تقنية BPF تستخدم BTF لكتابة برامج محمولة تتكيف مع إصدارات النواة المختلفة. |
| DKOM | معالجة مباشرة لكائنات النواة — تقنية الجذر الخفي لإزالة عملية من القائمة المرتبطة للنواة لإخفائها عن /proc. |
| fmod_ret | نوع برنامج BPF يعدل قيمة الإرجاع لدالة نواة عبر دعامة BPF. |
| freplace | امتداد برنامج BPF — يلتصق بدالة (فرعية) محددة لبرنامج BPF آخر، معترضًا تنفيذها. |
| مصفوفة الدوال | مصفوفة مؤشرات الدوال في بنية نقطة تتبع النواة التي تحمل دوال الاستدعاء (بما في ذلك برامج BPF) لاستدعائها عند إطلاق نقطة التتبع. |
| IDT | جدول واصف المقاطعة — بنية وحدة المعالجة المركزية التي تربط متجهات المقاطعة بدوال المعالجة. يتطلب ربط مدخل NMI تعديل IDT. |
| kASLR | توزيع عشوائي لمساحة عنوان النواة — يعشو عناوين رمز/بيانات النواة عند كل إقلاع لإعاقة الاستغلال. |
| NMI | مقاطعة غير قابلة للإخفاء — مقاطعة أجهزة لا يمكن تعطيلها بواسطة البرنامج (cli). تستخدم بواسطة عدادات الأداء للمراقبة على مستوى الأجهزة. |
| PCR | سجل تكوين المنصة — سجل TPM يجمع قياسات (تجزئات) لمكونات الإقلاع. لا يمكن إعادة تعيينه (باستثناء إعادة التشغيل)، فقط يتم توسيعه. |
| PMU | وحدة مراقبة الأداء — عدادات أجهزة في وحدة المعالجة المركزية تحسب الأحداث (دورات، أخطاء ذاكرة مؤقتة، إلخ) ويمكنها تشغيل المقاطعات (NMIs) عند عتبات معينة. |
| TPM | وحدة المنصة الموثوقة — معالج تشفير يوفر تخزين مفاتيح موثوق بالأجهزة، وتوليد أرقام عشوائية، وإثبات القياسات. |
| المُدقق | مُدقق BPF — مكون النواة الذي يحلل برامج BPF بشكل ثابت قبل التحميل لضمان إنهائها وعدم وصولها إلى ذاكرة غير آمنة. |