Windows Virtualization Internals (חלק 2) — זיכרון שאפילו ה-kernel לא רואה: VBS, HVCI ו-Credential Guard
· עודכן בתאריך: · Go Komura · Windows, virtualization, אבטחה, VBS, HVCI, Credential Guard
היסטוריית עדכונים (גרסה ראשונה, פורסמה בתאריך 22 Aug 2026)
- פרסום ראשון
לצטט את המאמר הזה(DOI (ארכיון רשום): 10.5281/zenodo.22176873)
מזהי ה־DOI שלהלן מפנים לגרסאות שנשמרו בעבר בארכיון, ועשויים שלא להתאים לטקסט הנוכחי. להפניה לטקסט הנוכחי, השתמשו בכתובת של דף זה.
Go Komura (2026). Windows Virtualization Internals (חלק 2) — זיכרון שאפילו ה-kernel לא רואה: VBS, HVCI ו-Credential Guard. KomuraSoft LLC. https://comcomponent.com/he/blog/windows-virtualization-internals-vbs-hvci-credential-guard/
- DOI (ארכיון רשום)
- 10.5281/zenodo.22176873
- DOI (הגרסה האחרונה שנרשמה)
- 10.5281/zenodo.22176874
איפה Windows שומר סודות שלא administrator ולא ה-kernel יכולים לקרוא? חלק 2 מתחיל מהשאלה הזו ועוקב אחרי איך VBS, HVCI ו-Credential Guard עובדים.
ב-Windows המסורתי, תוקף שטען kernel driver כ-administrator והריק את הזיכרון של process LSASS יכול היה לגנוב password hashes ו-Kerberos tickets ולהשתמש בהם ל-lateral movement למחשבים אחרים.
ב-Windows 11 עם Credential Guard רץ, ה-hashes של domain credentials מוגנים אינם נשמרים בשום מקום שה-kernel הרגיל יכול לחפש. במכשירים שעומדים בדרישות הרישיון (Enterprise, Education וכדומה) ובדרישות החומרה, ההגנה הזו מופעלת כברירת מחדל מ-22H2 ואילך.1 הדרישות ומצב הריצה בפועל הם שני דברים שונים, ולכן הסכנה לא נעלמה במקומות שבהם זה לא רץ.
חלק 1 הראה את המבנה שבו Windows המארח רץ ב-root partition מעל ה-hypervisor. מה שהמאמר הזה עוקב אחריו הוא עוד קו גבול אחד, שמצויר בתוך אותו partition.
“Windows Virtualization Internals” — כל 3 החלקים
מסתכלים על אותו Windows hypervisor בסדר יסוד → בידוד אבטחה → יישום ל-VMs קלות.
| חלק | השאלה המרכזית |
|---|---|
| חלק 1: ה-hypervisor ו-partitions | איפה Windows המארח רץ? |
| חלק 2: VBS, HVCI ו-Credential Guard (המאמר הזה) | איפה שומרים סודות שאפילו ה-kernel לא יכול לקרוא? |
| חלק 3: WSL2, Windows Sandbox ו-containers | למה אפשר להקל בלי לוותר על בידוד? |
מה המאמר הזה מניח
| פריט | פירוט |
|---|---|
| קהל יעד | מפתחים ומפעילים שרוצים להבין מה Core isolation, Memory integrity ו-Credential Guard באמת הם |
| סביבה | Windows 10/11 x64 או Windows Server עדכני. דיון ה-rings ו-SLAT מניח x64; Arm64 משתמש במנגנונים אחרים כמו exception levels |
| ידע רקע | מושגי partitions ו-SLAT מחלק 1 |
| קושי והיקף | בינוני. זה אינו מדריך תצורה; הוא מסביר את מבנה יכולות האבטחה |
איך לקרוא את המאמר הזה
| מה רוצים לדעת | סעיפים לקרוא |
|---|---|
| למה צריך בידוד חזק מה-kernel, ואיך משיגים אותו | גבולות המודל המסורתי בסעיף 2 → VSM, VTLs ו-SLAT בסעיף 3 |
| מה HVCI ו-Credential Guard כל אחד מגן | code integrity בסעיף 4 → credentials והיקף הגנה בסעיף 5 |
| איך להבדיל את מסך ההגדרות ממצב הריצה בפועל | איך בודקים בסעיף 6 → קריאות שגויות בסעיף 7 |
1. קודם המסקנה
Windows הוסיף ציר הרשאה שנקרא VTL (Virtual Trust Level) ושם את הסודות ב-VTL1. ה-kernel הרגיל שרץ ב-VTL0 אינו יכול לקרוא זיכרון VTL1. מה ששומר על הגבול אינו ה-kernel עצמו אלא ה-hypervisor, שמחזיק את טבלאות התרגום של SLAT.
זה השלד של virtualization-based security (VBS). VBS משתמש ב-hypervisor כדי ליצור סביבה מבודדת ומשכן שם יכולות אבטחה. הוא מתוכנן בהנחה שהסביבה המבודדת נשארת מוגנת גם אם ה-kernel נפגע.2
flowchart TB
accTitle: שני העולמות ש-VBS יוצר
accDescr: VTL0 ו-VTL1 יושבים בתוך אותו partition; VTL0 מחזיק את ה-kernel הרגיל ואת האפליקציות, VTL1 מחזיק את Secure Kernel ואת יכולות האבטחה המבודדות, וה-hypervisor שומר על הגבול
subgraph vtl0 ["VTL0 (העולם הרגיל)"]
apps["אפליקציות (ring 3)"]
ntk["NT kernel ו-drivers (ring 0)"]
end
subgraph vtl1 ["VTL1 (העולם המבודד)"]
ium["יכולות אבטחה מבודדות"]
sk["Secure Kernel"]
end
hv["hypervisor (אוכף את הגבול דרך SLAT)"] --- vtl0
hv --- vtl1
ntk -.->|לא יכול לקרוא| ium
איור 1: יש שני עולמות בתוך Windows אחד, ו-kernel של VTL0 אינו יכול לגשת לזיכרון VTL1.
הנקודה החשובה היא שזה אינו “להעמיד VM נוסף”. VTL0 ו-VTL1 נמצאים בתוך אותו partition, בתוך אותו Windows. מסתכלים בתור על איך הפיצול הזה מושג.
ב-diagram, solid line מציינת relation שתמיד מתקיים ו-dashed line מציינת relation מותנה (התנאים מופיעים בהסבר של כל relation ב-detail page). הרשימה המלאה של ה-relations (סה”כ 22, כולל evidence ו-certainty) וההגדרות של ה-concepts המרכזיים נמצאות ב-detail page של ה-knowledge map (ביפנית). Data: JSON-LD / Turtle
2. גבולות מודל ה-rings — השומר והשמור עומדים באותו גובה
אבטחת Windows המסורתית נבנתה על סולם rings (רמות הרשאה). user mode (ring 3) נשמר על ידי kernel mode (ring 0). אז מי שומר על ring 0? אף אחד לא יכול. ring 0 הוא ההרשאה הגבוהה ביותר.
למבנה הזה יש שתי חולשות מבניות.
- ה-kernel אינו מונולית. ב-ring 0 רצים לא רק Windows עצמו אלא מספר גדול של drivers של צד שלישי. אם לאחד מהם יש פגיעות, התוקף מקבל הרצת קוד ב-ring 0.
- מ-ring 0 הכול נראה. לא משנה כמה process ב-user mode כמו LSASS מגן על עצמו, תוקף שלקח את ה-kernel יכול לקרוא את הזיכרון שלו בחופשיות. גם תכונות הגנה וגם טבלאות דפים מנוהלות על ידי ה-kernel עצמו.
flowchart TB
accTitle: נתיב גניבת credentials במודל ה-rings המסורתי
accDescr: תוקף שלוקח את ring 0 דרך driver פגיע יכול לקרוא זיכרון process של LSASS בסמכות המלאה של ה-kernel ולהשיג password hashes
mal["קוד התוקף"] -->|מנצל driver פגיע| r0["לוקח את ring 0"]
r0 --> readall["יכול לקרוא את כל הזיכרון הפיזי"]
readall --> lsass["משיג hashes מזיכרון LSASS"]
lsass --> lateral["מנוצל ל-lateral movement למחשבים אחרים"]
איור 2: כי השומר (ה-kernel) והשמור (הסודות) עומדים באותו גובה, החולשה היסודית היא שאם ring 0 נופל, הכול נופל.
מה שנדרש, אם כן, הוא “מקום גבוה מ-ring 0”. המקום הזה כבר הופיע בחלק 1. ה-hypervisor רץ בהרשאה גבוהה מה-kernel ולוקח שליטה בלעדית בהרשאות הגישה לזיכרון של ה-CPU (SLAT) מוקדם. אזור מבודד ששמור על ידי ה-hypervisor מוגן גם מפני גישה מתוכנת OS ב-ring 0 (supervisor mode).3
3. VSM ו-VTLs — מוסיפים עוד ציר הרשאה אחד
הסעיף הזה מתקדם בסדר קבוצת היכולות שמספקת את הבידוד (VSM) → רמות הבידוד (VTLs) → המנגנון שאוכף את הגבול (SLAT) → הקוד שרץ בפנים. השמות נראים דומים, אבל הם אינם אותו דבר.
3.1. Virtual Trust Levels (VTLs)
קבוצת יכולות ה-hypervisor שמספקת את הבידוד הזה נקראת VSM (Virtual Secure Mode). VSM הוא היסוד ל-Device Guard, Credential Guard, virtual TPM וכדומה.3
המושג המרכזי של VSM הוא VTL (Virtual Trust Level). הנקודות העיקריות הן אלה.3
- VTLs היררכיים, ו-ככל שהמספר גבוה יותר, ההרשאה גבוהה יותר. VTL0 הוא הנמוך ביותר; VTL1 מועדף יותר מ-VTL0.
- ארכיטקטונית מוגדרות עד 16 רמות, אבל מה שממומש כרגע הוא שתיים: VTL0 ו-VTL1.
- לכל VTL יש הגנות גישה לזיכרון עצמאיות. ה-hypervisor מנהל את ההגנות האלה מעל מרחב הכתובות הפיזי של ה-partition, כך שתוכנת מערכת בתוך ה-partition אינה יכולה לשנות אותן.
- ל-virtual processor יש מצב רגיסטרים ומנגנון interrupt נפרדים לכל VTL, ו-VTL נמוך יותר אינו יכול להציץ למצב של VTL גבוה יותר.
flowchart TB
accTitle: שלושת החלקים העצמאיים שמרכיבים בידוד VTL
accDescr: הגנות גישה לזיכרון, מצב רגיסטרים של virtual processor ומנגנון interrupt עצמאיים לכל VTL, ו-VTL נמוך יותר אינו יכול לגעת באף אחד מהם ב-VTL גבוה יותר
vtl["מה שעצמאי לכל VTL"] --> m1["הגנות גישה לזיכרון"]
vtl --> m2["מצב רגיסטרים של virtual processor"]
vtl --> m3["מנגנון interrupt"]
m1 -.-> rule["VTL נמוך יותר אינו יכול לגעת ב-VTL גבוה יותר"]
m2 -.-> rule
m3 -.-> rule
איור 3: להפוך לא רק זיכרון אלא גם מצב CPU ו-interrupts לעולם נפרד הוא הסט התלת-חלקי שלא משאיר חור הצצה.
אם rings (0 ו-3) הם הציר שמפריד “OS ואפליקציות”, VTLs הם ציר שני שמפריד “העולם הרגיל והעולם המבודד”. שני הצירים אורתוגונליים, ובתוך VTL1 יש גם kernel mode וגם user mode.
flowchart TB
accTitle: ארבעת האזורים שנוצרים משני צירי rings ו-VTLs
accDescr: ציר ה-rings מפריד kernel mode מ-user mode, ציר ה-VTL מפריד את העולם הרגיל מהעולם המבודד, והשילוב מייצר ארבעה אזורים: אפליקציות רגילות, NT kernel, IUM trustlets ו-Secure Kernel
subgraph ax0 ["VTL0 (עולם רגיל)"]
a0["Ring 3: אפליקציות רגילות"]
k0["Ring 0: NT kernel ו-drivers"]
end
subgraph ax1 ["VTL1 (עולם מבודד)"]
a1["Ring 3: IUM (trustlets)"]
k1["Ring 0: Secure Kernel"]
end
a0 --- k0
a1 --- k1
k0 ~~~ a1
איור 4: עכשיו יש שני צירי הרשאה, ו”האם זה ה-kernel?” ו”האם זה העולם המבודד?” הפכו לשאלות נפרדות.
3.2. מהות הגבול היא SLAT
חלק 1 אמר שטבלאות התרגום ברמה השנייה שממפות guest physical addresses (GPAs) על RAM בפועל (SPAs), כלומר SLAT, מוחזקות על ידי ה-hypervisor. VSM משתמש בדיוק בתכונה הזו. בידוד VTL נבנה באמצעות Hyper-V hypervisor ו-SLAT.4
כש-VTL1 מכריז “הזיכרון הזה לא יוצג ל-VTL0”, ה-hypervisor מסיר את הרשאת הגישה לדף הזה מטבלאות התרגום של VTL0. מכאן ואילך, גם אם kernel של VTL0 מנסה לגעת בכתובת הזו, הוא נדחה בשלב תרגום הכתובות של ה-CPU. לא משנה איך ה-kernel משכתב את טבלאות הדפים שלו.
טבלאות הדפים (GVA→GPA) עשויות להיות שייכות ל-kernel, אבל התרגום שמעבר להן (GPA→SPA) והרשאת הגישה הסופית שייכים ל-hypervisor.
flowchart TB
accTitle: איך גישה מ-VTL0 לזיכרון VTL1 נדחית
accDescr: כש-kernel של VTL0 מנסה לקרוא זיכרון VTL1, הוא יכול לעבור את טבלאות הדפים שלו אבל נדחה על ידי הגנת הגישה של SLAT, והשליטה עוברת ל-hypervisor
try["kernel של VTL0 מנסה לקרוא דף VTL1"] --> pt["עובר את טבלאות הדפים של ה-kernel עצמו"]
pt --> slat{"האם הגנת הגישה של SLAT מתירה?"}
slat -->|לא מותר| deny["ה-hypervisor מתערב ודוחה את הגישה"]
slat -->|מותר| ok["גישת זיכרון רגילה"]
deny -.-> point["מוגן בשכבה שה-kernel אינו יכול לשנות"]
איור 5: המחסום יושב מחוץ ל-kernel, והגנת SLAT אינה ניתנת לשינוי על ידי תוכנה בתוך ה-partition.
חלק 1 של סדרת הזיכרון אמר ש”ה-VAD, ה-PTE ותכונות ההגנה מחליטים אם גישה מותרת”. בסביבת VBS התמונה הופכת: אחרי שכל אלה עברו, עדיין מחכה checkpoint של SLAT.
3.3. Secure Kernel ו-IUM
מה שרץ בתוך VTL1 אינו NT kernel הרגיל אלא kernel קטן שנקרא Secure Kernel. user mode ב-VTL1 נקרא IUM (Isolated User Mode), והתוכניות שרצות שם נקראות trustlets (processes מהימנים).4
trustlet אינו יכול לעשות כל מה שהוא רוצה כמו process רגיל. רוב ה-system calls שלו מ-marshal ל-NT kernel בצד VTL0, שמבקשים ממנו לעשות את העבודה.4 VTL1 אינו “עולם עליון שיכול הכול”; הוא נבנה במכוון קטן, כ-כספת שמחזיקה סודות. ככל שפחות קוד אפשר להכניס לכספת, כך משטח התקיפה קטן יותר.
flowchart TB
accTitle: זרימת system calls של trustlet
accDescr: trustlet ב-VTL1 אינו מטפל ברוב ה-system calls בעצמו; הוא עושה marshal שלהם ל-NT kernel ב-VTL0 ומקבל רק את התוצאה, וזה שומר את VTL1 קטן
tl["trustlet (IUM ב-VTL1)"] --> sc{"נדרש system call"}
sc -->|ברוב המקרים| mar["מבקש מ-NT kernel ב-VTL0"]
mar --> res["מקבל רק את התוצאה"]
res -.-> small["VTL1 נשאר קטן ומשטח התקיפה מצטמצם"]
איור 6: לכספת אין מתקנים משלה; היא שולחת את המטלות החוצה וממשיכה לשמור רק על הסודות.
4. HVCI — מאמתים code integrity של kernel בכספת
שני הדברים לתפוס על HVCI הם איפה מתבצע האימות ו-מה מותר על הזיכרון אחרי האימות. מסתכלים קודם על ההגנה הזו, ואז על השפעתה על תאימות drivers.
4.1. מה מאומת
היכולת הנציגה הראשונה שיושבת על VBS היא Memory integrity, כלומר HVCI (hypervisor-protected code integrity). ל-Windows יש מנגנון code integrity שבודק kernel-mode drivers ו-binaries לפני שהם מתחילים ומסרב לטעון כאלה שאינם חתומים או אינם מהימנים. HVCI מבצע את האימות הזה בתוך הסביבה המבודדת של VBS.2
הסיבה להעביר את לוגיקת האימות עצמה ל-VTL1 היא בדיוק החולשה בסעיף 2. אם קוד האימות יושב בתוך kernel של VTL0, תוקף שלקח את ה-kernel יכול להחליף את האימות. אם הוא ב-VTL1, היד המחליפה אינה יכולה להגיע אליו.
flowchart TB
accTitle: ההבדל שנעשה לפי איפה חי קוד האימות
accDescr: אם קוד האימות יושב בתוך kernel של VTL0 הוא מנוטרל ברגע שה-kernel נלקח, אבל אם הוא ב-VTL1 גם תוקף שלקח את ה-kernel אינו יכול להגיע אליו והאימות נשאר מוגן
atk["תוקף שלקח את ה-kernel"] --> q{"איפה חי אימות code integrity?"}
q -->|"בתוך kernel של VTL0 (מסורתי)"| bad["אפשר להחליף את לוגיקת האימות"]
q -->|"סביבה מבודדת ב-VTL1 (HVCI)"| good["ההחלפה מחוץ להישג יד"]
bad --> res1["קוד לא חתום יכול לרוץ ב-kernel"]
good --> res2["האימות ממשיך לעבוד אחרי שה-kernel נפגע"]
איור 7: אל תשימו את ה-checkpoint בתוך הצד שעשוי להיפרץ; העברת לוגיקת האימות הזו היא מהות HVCI.
4.2. הכללים לדפים ברי-ביצוע
אפקט HVCI אינו מוגבל ל”בדיקה ב-startup”. הוא גם מגביל הקצאת זיכרון kernel.5
- דף kernel הופך בר-ביצוע רק אחרי שעבר אימות code integrity.
- דף בר-ביצוע לעולם אינו הופך לבר-כתיבה (מה שנקרא W^X).
עם שני אלה במקום, גם אם פגיעות כמו buffer overflow מאפשרת לשכתב זיכרון kernel, אי אפשר לגרום לתוכן המשוכתב לרוץ. דפים ברי-ביצוע אינם ניתנים לשכתוב, ודפים שניתן לשכתב אינם ניתנים לביצוע.5 הגיבוי הסופי להרשאת execute הוא זכות ה-execute בצד SLAT, ש-kernel של VTL0 אינו יכול לתפעל.
flowchart TB
accTitle: עד שדף kernel הופך בר-ביצוע בסביבת HVCI
accDescr: בקשת טעינת driver מקבלת אימות code integrity בסביבה המבודדת של VBS; אם היא עוברת היא מותרת כדף בר-ביצוע שאינו בר-כתיבה, ואם היא נכשלת היא נחסמת ונרשמת ביומן CodeIntegrity
load["בקשה לטעון ולהריץ קוד kernel"] --> verify{"אימות code integrity בסביבה המבודדת"}
verify -->|עובר| exec["מותר כדף בר-ביצוע (כתיבות אסורות)"]
verify -->|נכשל| block["הטעינה נחסמת"]
block --> log["נרשם ביומן CodeIntegrity Operational (event ID 3087)"]
exec -.-> wx["דפים ברי-כתיבה נשארים לא ברי-ביצוע"]
איור 8: הכלל שלעולם אינו נותן ל-execute ול-write לדור יחד מאומת בצד VTL1, ו-kernel של VTL0 אינו יכול להפוך אותו.
מעקב אחרי זה מנקודת המבט של התוקף מראה בבירור איך הכלל נכנס לתוקף.
flowchart TB
accTitle: איך הזרקת קוד נכשלת בסביבת HVCI
accDescr: גם אם פגיעות מאפשרת לשכתב זיכרון kernel, דף שאפשר לכתוב אליו אינו בר-ביצוע, ודף בר-ביצוע אינו ניתן לשכתוב מלכתחילה, כך שהקוד המוזרק לעולם אינו יכול לרוץ
inj["ניסיון לשבש זיכרון kernel דרך פגיעות"] --> which{"איזה דף הוא היעד?"}
which -->|דף בר-כתיבה| wok["השכתוב מצליח"]
which -->|דף בר-ביצוע| xfail["השכתוב עצמו בלתי אפשרי"]
wok --> nx["אבל הדף הזה אינו בר-ביצוע"]
nx --> dead["הקוד המוזרק אינו יכול לרוץ"]
xfail --> dead
איור 9: באיזה כניסה שלא תיקחו, מגיעים למבוי סתום; זו הנקודה שלעולם לא לתת לדפים ברי-כתיבה ולדפים ברי-הרצה לחפוף.
4.3. המחיר: תאימות drivers
הכלל הזה מתנגש עם drivers בעיצוב ישן. drivers שמשכתבים את הקוד שלהם בזמן ריצה, בלי חתימה, או שדורשים זיכרון שהוא גם בר-ביצוע וגם בר-כתיבה, אינם יכולים להיטען בסביבת HVCI.
את עובדת החסימה אפשר לאשר ב-Event Viewer תחת Applications and Services Logs\Microsoft\Windows\CodeIntegrity\Operational (event ID 3087 הוא הנציג).6
במקרים רבים, זה מה שבאמת מאחורי התלונה “אחרי שהפעלתי Memory integrity, ציוד היקפי הפסיק לעבוד”. התיקון הנכון הוא לעדכן לגרסה תואמת HVCI של ה-driver; כיבוי Memory integrity צריך להיחשב כמוצא אחרון שמוותר על ההגנה במלואה.
אם אתם מעורבים באימות הזה מצד פיתוח drivers, ראו גם את מאמר ה-filter driver (“מעמקי ה-I/O ב-Windows (פרק 6, אחרון) — filter drivers ו-minifilter”).
flowchart TB
accTitle: מיון כשציוד היקפי מפסיק לעבוד תחת Memory integrity
accDescr: מזהים את ה-driver שנחסם ביומן CodeIntegrity Operational; התיקון הנכון הוא לעדכן לגרסה תואמת HVCI, לבקש מהספק אם אין כזו, ולטפל בכיבוי כמוצא אחרון שלעולם אינו הופך להגדרה קבועה
sym["device מפסיק לעבוד אחרי הפעלת Memory integrity"] --> log2["לזהות את ה-driver שנחסם ביומן CodeIntegrity"]
log2 --> upd{"יש driver תואם HVCI?"}
upd -->|כן| fix2["לעדכן ולפתור תוך השארת HVCI דולק"]
upd -->|לא| ask2["לבקש מהספק גרסה תואמת"]
ask2 -.-> temp["כיבוי הוא מוצא אחרון, לעולם לא הגדרה קבועה"]
איור 10: הדבר הראשון להסתכל עליו אינו מסך ההגדרות אלא הלוג, ו-event ID 3087 יודע איזה driver נחסם.
5. Credential Guard — ה-hashes נמצאים בתוך LSAIso
במקום שבו HVCI שומר על code integrity של ה-kernel, Credential Guard שומר על credentials. חושבים על דלפק הקבלה שמקבל authentication ועל המקום שבו הסודות שמורים כשני דברים נפרדים, והמבנה והיקף ההגנה נופלים למקום.
5.1. LSASS ו-LSAIso
היכולת הנציגה השנייה שיושבת על VBS היא התשובה לתעלומה בפתיחה: Credential Guard.
Windows המסורתי שמר NTLM hashes ו-Kerberos tickets בזיכרון של process LSA (lsass.exe). כש-Credential Guard מופעל, אחסון הסודות המוגנים מביניהם, כמו NTLM hashes של domain credentials ו-TGTs של Kerberos (Ticket Granting Tickets), עובר ל-LSAIso.exe, trustlet שרץ ב-IUM ב-VTL1.7
- lsass.exe (VTL0) ממשיך לרוץ כדלפק הקבלה לעיבוד authentication, כמו קודם.
- הסודות בפועל מוחזקים על ידי LSAIso.exe (VTL1) ואינם נגישים מ-VTL0.
- השניים מתקשרים דרך RPC (Remote Procedure Call).
- LSAIso אינו מארח device drivers כלל ומשכן רק את הסט המינימלי של binaries חתומים. החתימות מאומתות מול תעודה ש-VBS סומך עליה.7
flowchart TB
accTitle: איפה יושבים credentials כש-Credential Guard מופעל
accDescr: lsass ב-VTL0, כדלפק authentication, מתקשר עם LSAIso ב-VTL1 דרך RPC; ה-hashes וה-TGTs בפועל של domain credentials מוגנים מוחזקים על ידי LSAIso, כך שתוקף שמשיג הרשאות administrator ב-VTL0 ומריק את lsass עדיין אינו מקבל את הסודות המוגנים עצמם
subgraph v0 ["VTL0"]
lsassP["lsass.exe (דלפק authentication)"]
att["תוקף (הרשאות administrator)"]
end
subgraph v1 ["VTL1"]
iso["LSAIso.exe (כספת הסודות)"]
end
lsassP <-->|RPC| iso
att -->|memory dump| lsassP
att -.->|לא יכול להגיע| iso
איור 11: כי דלפק הקבלה והכספת הופרדו, הריקת lsass כבר אינה מניבה את ה-hashes בפועל של ה-domain credentials המוגנים.
תנאים להפעלה כברירת מחדל
מ-Windows 11 גרסה 22H2 ואילך, VBS ו-Credential Guard מופעלים כברירת מחדל במכשירים שעומדים בדרישות הרישיון (Enterprise E3/E5, Education A3/A5) ובדרישות החומרה. במהדורות כמו Pro, Credential Guard אינו מופעל אוטומטית (יש חריגים, כמו מכונה שהופעלה תחת רישיון מתאים בעבר ואחר כך הורדה).1
הגנת ה-credentials הזו אינה עניין של מוצר תוספת מיוחד; היא המצב הסטנדרטי של Windows הנוכחי במהדורות המתאימות.
flowchart TB
accTitle: זרימת credentials מ-sign-in עד authentication
accDescr: אחרי sign-in הסודות בפועל נשמרים ב-LSAIso ב-VTL1; בכל פעם שנדרש authentication, lsass ב-VTL0 מבקש את החישוב דרך RPC, ורק תוצאת עיבוד ה-authentication חוזרת ל-VTL0 בלי שהסודות ארוכי-הטווח המוגנים עצמם יוחזרו אי פעם
signin["המשתמש נכנס"] --> front["lsass מטפל כדלפק"]
front --> store["הסודות בפועל נשמרים ב-LSAIso"]
auth["בקשות authentication מאוחרות יותר"] --> front
front -->|מבקש את החישוב דרך RPC| store
store -->|"מחזיר את התוצאה (לעולם לא את הסוד)"| front
איור 12: הסודות ארוכי-הטווח המוגנים עצמם לעולם אינם יוצאים מהכספת; מה שחוזר ל-VTL0 הוא תוצאת עיבוד ה-authentication, כמו ticket.
5.2. לדעת במדויק מה אינו מוגן
credentials שמוגנים
Credential Guard אינו מגן כל-תכליתי. מה שהוא מגן הוא NTLM hashes של domain credentials, TGTs של Kerberos (Ticket Granting Tickets), וכל מה שנשמר כ-domain credentials.
מחוץ להיקף
הבאים מחוץ להיקף.8
- service tickets של Kerberos (TGTs מוגנים)
- credentials של חשבונות מקומיים ושל חשבונות Microsoft
- גניבת קלט על ידי keylogger, ותקיפות פיזיות
- credentials בנתיבים שמשתמשים ב-NTLMv1, MS-CHAPv2, Digest או CredSSP
- הפנים של תוכנת צד שלישי שמנהלת credentials בעצמה
בנפרד מהיקף ההגנה, לבדוק גם תאימות authentication
גם, כש-Credential Guard מופעל, NTLMv1, unconstrained Kerberos delegation וכדומה כבר אינם ניתנים לשימוש, כך שמערכות עסקיות שתלויות ב-authentication ישן צריכות בדיקת תאימות.8 זה אינו “מפעילים וגמרנו”; מבינים מה בפנים ומה בחוץ של היקף ההגנה וממלאים את השאר בבקרות אחרות. זו הדרך הנכונה להשתמש בזה בפועל.
flowchart TB
accTitle: היקף ההגנה של Credential Guard
accDescr: NTLM hashes ו-TGTs של domain ו-domain credentials שמורים מוגנים, בעוד service tickets, חשבונות מקומיים, keyloggers, תקיפות פיזיות ו-credentials שאפליקציה שומרת בעצמה מחוץ להיקף
scope{"באיזה צד של היקף ההגנה הסוד הזה?"} --> inA["NTLM hashes ו-TGTs של domain"]
scope --> outA["service tickets וחשבונות מקומיים"]
inA --> prot["מוגן ב-LSAIso"]
outA --> unprot["לא מוגן (נדרשות בקרות אחרות)"]
unprot -.-> outB["הקשות, תקיפות פיזיות ומחסנים פרטיים לאפליקציה גם הם מחוץ להיקף"]
איור 13: היקף ההגנה מצויר בקו ברור, ומחוץ לקו ממלאים ב-multi-factor authentication ובתכנון בצד האפליקציה.
6. ראו זאת בעצמכם
אפשר לבדוק את מצב הריצה של VBS ושל כל יכולת במכונה שלכם. קוראים את מצב VBS, היסוד, בנפרד ממצב ה-services שרצים מעליו.
6.1. לבדוק VBS ואת ה-services הרצים ב-PowerShell
Get-CimInstance -Namespace root/Microsoft/Windows/DeviceGuard `
-ClassName Win32_DeviceGuard |
Select-Object VirtualizationBasedSecurityStatus,
SecurityServicesConfigured,
SecurityServicesRunning
קוראים את הפלט כך.9
- אם
VirtualizationBasedSecurityStatusהוא 2, VBS מופעל ורץ. - אם
SecurityServicesRunningמכיל 1, Credential Guard רץ; אם הוא מכיל 2, Memory integrity (HVCI) רץ.
6.2. לקרוא msinfo32 ומסך ההגדרות אחרת
כדי לבדוק מצב ריצה ב-GUI, מסתכלים על השדה “Virtualization-based security” ב-msinfo32 (ה-services הרצים רשומים שם, כמו “Hypervisor enforced Code Integrity”).
מתג “Memory integrity” תחת “Device security > Core isolation” ביישום האבטחה של Windows הוא מסך שמשקף את ההגדרה. הוא יכול להיראות דולק גם בזמן ש-HVCI אינו רץ בפועל, למשל בזמן שממתינים ל-reboot מיד אחרי הפעלה או כשיש בעיית תאימות ב-startup, לכן שופטים אם זה רץ מ-msinfo32 או מ-SecurityServicesRunning ב-Win32_DeviceGuard.6
6.3. לא לשפוט “רץ” מנוכחות process לבדה
יש גם עקבות בלשונית Details של Task Manager. במכונה שבה VBS רץ תראו process בשם “Secure System”. LsaIso.exe הוא ה-process שמופיע כש-Isolated LSA service מתארח ב-VTL1, והוא בדרך כלל אינו מופיע בתצורה שבה רק HVCI מופעל.
נוכחות או היעדר process הם רק עקבות, עם זאת, לכן שופטים אם Credential Guard רץ מ-SecurityServicesRunning (אם הוא מכיל 1), כפי שתואר למעלה. שניהם חלונות, הנראים מ-VTL0, אל העולם בצד VTL1.
flowchart TB
accTitle: ההליך לבדיקה שיכולות הקשורות ל-VBS רצות
accDescr: מאשרים ש-VBS רץ בשאילתה ל-Win32_DeviceGuard, שופטים אם Credential Guard ו-HVCI רצים מערכי SecurityServicesRunning, ומסתכלים ביומן CodeIntegrity לבעיות drivers
q0["שאילתה ל-Win32_DeviceGuard"] --> q1{"האם מצב VBS הוא 2?"}
q1 -->|לא| off["VBS לא רץ (לבדוק דרישות והגדרות)"]
q1 -->|כן| q2{"מה SecurityServicesRunning מכיל?"}
q2 -->|מכיל 1| cg["Credential Guard רץ"]
q2 -->|מכיל 2| hvciR["Memory integrity (HVCI) רץ"]
hvciR -.-> ev["לבעיות drivers, לבדוק את יומן CodeIntegrity (3087)"]
איור 14: בדיקת מצב מתקדמת בשלושה שלבים: VBS עצמו, כל service מעליו, והלוג כשמתרחשת בעיה.
7. שלוש קריאות שגויות להימנע מהן בפועל
7.1. “להגן על הרשאות administrator מספיק. VBS הוא סיפור לצד השרת”
מה ש-Credential Guard מונע הוא התפשטות הנזק אחרי שלקחו הרשאות administrator (הוצאת hashes ו-lateral movement). כלומר VBS הוא שכבת הגנה לעומק שמניחה פגיעה, וזה במחשבי לקוח שהוא משתלם. ב-Windows 11 שעומד בדרישות, מופעל כברירת מחדל הוא הנורמה, לכן היציבה הנכונה אינה “לזה אין קשר אלינו” אלא “לנהל תאימות בהנחה שזה כבר רץ”.
flowchart TB
accTitle: שלבי הפגיעה ואיפה VBS נכנס לתוקף
accDescr: גישה ראשונית מכוסה בבקרות אחרות כמו multi-factor authentication והדרכה; HVCI חוסם את הזרקת הקוד ל-kernel שאחרי העלאת הרשאות; Credential Guard חוסם גניבת סודות domain מוגנים ו-lateral movement, אבל אינו מגיע לסודות מחוץ להיקף
s1["גישה ראשונית (phishing וכדומה)"] --> s2["העלאת הרשאות"]
s2 --> s3["הזרקת קוד ל-kernel"]
s3 --> s4["גניבת סודות domain מוגנים ו-lateral movement"]
s1 -.-> d1["MFA, הדרכה ו-EDR מכסים את זה"]
s3 -.-> d2["HVCI חוסם את השלב הזה"]
s4 -.-> d3["Credential Guard חוסם את זה (סודות מוגנים בלבד)"]
איור 15: VBS אינו טכנולוגיית “להשאיר אותם בחוץ”; הוא טכנולוגיית “לא לתת להם לנצח ברגע שהם בפנים”, והשלב שהוא שומר שונה.
7.2. “אם Memory integrity גורם לבעיה, פשוט מכבים”
כיבוי יגרום לדברים לעבוד לרגע, אבל הוא מסיר את המחסום מפני הזרקת קוד ל-kernel במלואה. התיקון הנכון הוא קודם לזהות את ה-driver שנחסם ביומן CodeIntegrity ואז להחיל את הגרסה המעודכנת של הספק. גם כשמכבים זמנית לאימות, ממליצים על נוהג תפעול שלעולם אינו הופך את זה להגדרה קבועה.
7.3. “עם Credential Guard, אי אפשר לגנוב סיסמאות”
זו ביטחון-יתר שנולד מבלבול היקף ההגנה. service tickets, חשבונות מקומיים, ההקשות עצמן, ו-credentials שאפליקציה שומרת בעצמה מחוץ להיקף.8 phishing ו-keyloggers צריכים בקרות אחרות (multi-factor authentication, Windows Hello, וסקירה של איך האפליקציה עצמה מנהלת credentials).
8. סיכום
- VBS משתמש ב-hypervisor כדי ליצור סביבה מבודדת ומגן על יכולות אבטחה בהנחה שה-kernel ייפגע.2
- יחידת הבידוד היא VTL; כרגע ממומשות שתי רמות, VTL0 (העולם הרגיל) ו-VTL1 (Secure Kernel ו-IUM).3
- מהות הגבול היא הגנת הגישה לזיכרון של SLAT, שתוכנה בתוך ה-partition, כולל ה-kernel, אינה יכולה לשנות.3
- HVCI מבצע אימות code integrity בסביבה המבודדת ואוכף “לא בר-ביצוע עד שהאימות עובר” ו”דפים ברי-ביצוע אינם ברי-כתיבה”.5 המחיר הוא שצריך לנהל תאימות drivers.6
- Credential Guard מבודד את NTLM hashes ו-TGTs של domain credentials ב-LSAIso ב-VTL1. מ-Windows 11 22H2 ואילך הוא מופעל כברירת מחדל במכשירים שעומדים בדרישות הרישיון (Enterprise, Education) ובדרישות החומרה (להשתמש בזה יחד עם בדיקת מצב הריצה).71
- מצב הריצה אפשר לבדוק מ-SecurityServicesRunning ב-
Win32_DeviceGuard(1 = Credential Guard, 2 = HVCI).9
ההמשך בחלק 3, “VMs שעולות בשניות — WSL2, Windows Sandbox ו-containers”.
עד כאן הסתכלנו על וירטואליזציה מצד “חוזק הבידוד”. הפרק האחרון מסתכל מהצד ההפוך, “קלות”, ועוקב אחרי איפה ה-VMs הקלות שמשילות את המשקל של VM מלא מקצרות.
מאמרים קשורים
- Windows Virtualization Internals (חלק 1) — איפה Windows שלכם באמת רץ: hypervisor ו-partitions
- Page Fault ב-Windows (חלק 1): מתי כתובת וירטואלית מקבלת RAM פיזי
- מעמקי ה-I/O ב-Windows (פרק 6, אחרון) — filter drivers ו-minifilter
- פענוח קודי שגיאה ב-Windows — שלוש השכבות Win32, HRESULT ו-NTSTATUS
תחומי ייעוץ קשורים
KomuraSoft LLC מטפלת בחקירות תאימות בין אפליקציות Windows ליכולות אבטחה, בניתוח כשלים שנגרמים מ-drivers, ובאימות טכני של סביבות מחשבים פנימיות.
קישורים
-
Microsoft Learn, Credential Guard overview. על כך ש-Credential Guard מופעל כברירת מחדל מ-Windows 11 גרסה 22H2 ואילך במכשירים שעומדים בדרישות הרישיון, החומרה והתוכנה ולא כובו במפורש; על כך שהמהדורות/רישיונות המתאימים הם Enterprise (E3/E5) ו-Education (A3/A5), עם Pro מחוץ להיקף; ועל כך שמכונת Pro שהופעלה בעבר תחת רישיון מתאים נשארת זכאית להפעלה כברירת מחדל אחרי הורדה. ↩ ↩2 ↩3
-
Microsoft Learn, Virtualization-based Security (VBS). על כך ש-VBS משתמש בווירטואליזציה בחומרה וב-Windows hypervisor כדי ליצור סביבה מבודדת והופך אותה ל-root of trust של ה-OS בהנחה שה-kernel עלול להיפגע; על כך ש-Memory integrity מריץ אימות code integrity ב-kernel mode בתוך הסביבה המבודדת הזו; ועל כך ש-SLAT הוא דרישה חובה ל-VBS. ↩ ↩2 ↩3
-
Microsoft Learn, Virtual Secure Mode. על כך ש-VSM הוא היסוד ל-Device Guard, Credential Guard, virtual TPM וכדומה; על כך שגישה לאזורים מבודדים נשלטת רק דרך ה-hypervisor ומוגנת גם מתוכנת OS ב-ring 0; על כך ש-VTLs היררכיים עם 2 מתוך מקסימום 16 רמות ממומשות; ועל כך שהגנות גישה לזיכרון לפי VTL אינן ניתנות לשינוי על ידי תוכנת מערכת בתוך ה-partition. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Isolated User Mode (IUM) Processes. על כך ש-VSM יוצר VTLs באמצעות Hyper-V hypervisor ו-SLAT; על כך ש-Secure Kernel ו-IUM רצים ב-VTL1; על כך ש-trustlets עושים marshal של system calls ל-kernel ב-VTL0; ועל כך ש-LSAIso רץ ב-VTL1 ומתקשר עם lsass דרך RPC. ↩ ↩2 ↩3
-
Microsoft Learn, Memory integrity and virtualization-based security. על כך ש-Memory integrity (HVCI) מבצע אימות code integrity בסביבה מבודדת, ועל כך שדפי זיכרון kernel הופכים ברי-ביצוע רק אחרי שעברו אימות ודפים ברי-ביצוע לעולם אינם הופכים ברי-כתיבה. ↩ ↩2 ↩3
-
Microsoft Learn, Memory integrity and VBS enablement. על כך ש-Memory integrity מופעל כברירת מחדל בהתקנה נקייה של Windows 11 כשהחומרה תואמת; על בדיקת המצב ב-msinfo32 וביישום האבטחה של Windows; ועל אישור driver שנחסם דרך event ID 3087 ביומן CodeIntegrity Operational. ↩ ↩2 ↩3
-
Microsoft Learn, How Credential Guard works. על כך שה-LSA מתקשר עם process LSA המבודד (LSAIso.exe) כדי לשמור סודות כש-Credential Guard מופעל; על כך שהנתונים השמורים מוגנים על ידי VBS ואינם נגישים משאר ה-OS; ועל כך ש-process LSA המבודד אינו מארח device drivers ומשכן רק סט מינימלי של binaries מאומתי-חתימה. ↩ ↩2 ↩3
-
Microsoft Learn, Credential Guard protection limits. על כך ש-service tickets, חשבונות מקומיים, keyloggers, תקיפות פיזיות וכדומה מחוץ להיקף ההגנה של Credential Guard; על כך ש-TGTs מוגנים בעוד service tickets אינם; ועל כך ש-NTLMv1 ו-unconstrained delegation הופכים לבלתי ניתנים לשימוש כשזה מופעל. ↩ ↩2 ↩3
-
Microsoft Learn, Enable virtualization-based protection of code integrity. על איך לבדוק את מצב VBS ו-Memory integrity דרך מחלקה Win32_DeviceGuard, ועל משמעות ערכי SecurityServicesRunning (1 הוא Credential Guard, 2 הוא Memory integrity). ↩ ↩2
מאמרים קשורים
מאמרים עדכניים עם אותן תגיות, להעמקה בנושאים קרובים.
האם כיבוי Memory integrity (HVCI) מאיץ את Windows? — מה זה אומר, איך עושים, ואיך מחליטים
האם כיבוי Memory integrity (HVCI) באמת מאיץ מחשב Windows? מתי זה יכול לעזור, מתי לא, איך מכבים ומחזירים, ואיך מחליטים.
Windows Virtualization Internals (חלק 3) — VMs שעולות בשניות: WSL2, Windows Sandbox ו-containers
למה WSL2 ו-Windows Sandbox עולים בשניות ונשארים קלים? המאמר מסביר את המנגנונים, מ-dynamic base image ו-direct map דרך הקצאת זיכרון דינמית...
Windows Virtualization Internals (חלק 1) — איפה Windows שלכם באמת רץ: hypervisor ו-partitions
כשמפעילים Hyper-V, Windows המארח עצמו רץ מעל ה-hypervisor כ-root partition. המאמר מסביר את יסודות הווירטואליזציה דרך התפקידים של VT-x, SL...
Named Pipes בפועל — ה-IPC הסטנדרטי של Windows, מתכנון עד אבטחה
מדריך מעשי ל-Named Pipes, ה-IPC הסטנדרטי ב-Windows. המאמר מסדר לפי מקורות ראשוניים את הבחירה בין byte mode ל-message mode, תכנון server ל...
חשבונות שירות ב-Windows: LocalSystem, virtual accounts ו-gMSA
עדיין מריצים Windows services כ-LocalSystem? המאמר משווה הרשאות וזהות רשת של LocalService, NetworkService, virtual accounts, domain users...
נושאים קשורים
העמודים האלה ממקמים את הנושא בהקשר רחב יותר של שירותים והחלטות.
נושאים טכניים ב-Windows
שער לנושאי פיתוח Windows, חקירת תקלות וניצול נכסים קיימים.
שירותים הקשורים לנושא הזה
המאמר קשור ישירות לשירותים הבאים.
פיתוח יישומי Windows
יישומים עסקיים, חיבור התקנים וכלי תקשורת, מהגדרת הדרישות ועד הפיתוח.
שאלות נפוצות
שאלות נפוצות בפניות בנושא המאמר.
- האם VBS (Virtualization-based security) ו-Core isolation הם אותו דבר?
- במובן הצר, הם שונים. VBS היא טכנולוגיית היסוד שיוצרת סביבה מבודדת עם ה-hypervisor, ו-Core isolation ביישום האבטחה של Windows הוא שם של מסך שמקבץ כמה הגנות הבנויות על VBS. הנציגה היא Memory integrity, שמתייחסת ל-HVCI (hypervisor-protected code integrity). אשרו את מצב הריצה של כל שירות בשאילתה ל-Win32_DeviceGuard, לא מתצוגת המסך.
- האם באמת אי אפשר לקרוא זיכרון VTL1, גם עם הרשאות Administrator או מ-kernel driver?
- אי אפשר. הגנות גישה לזיכרון לפי VTL מנוהלות על ידי ה-hypervisor מול מרחב הכתובות הפיזי של ה-partition, ותוכנה שרצה בתוך ה-partition לא יכולה לשנות אותן. גם קוד שרץ ב-kernel (ring 0) אינו מורשה לגשת לזיכרון VTL1 מ-VTL0.
- למה הפעלת Memory integrity (HVCI) יכולה לעצור driver מלעבוד?
- בסביבת HVCI, דף kernel הופך לבר-ביצוע רק אחרי שעבר integrity verification, וכתיבות לדפים ברי-ביצוע אינן מותרות. driver לא חתום, או driver בעיצוב ישן שמשכתב זיכרון בר-ביצוע, לא יכול לעמוד באילוץ הזה והטעינה שלו נחסמת. אפשר לאשר את החסימה ביומן CodeIntegrity Operational (Event ID 3087 וכדומה).
- מה Credential Guard מגן, ומה הוא לא מגן?
- הוא מגן על NTLM password hashes של domain credentials, על TGT של Kerberos, ועל דברים שאפליקציה שמרה כ-domain credentials, בסביבה מבודדת. service tickets של Kerberos, credentials של חשבונות מקומיים וחשבונות Microsoft, גניבת קלט על ידי keylogger, ותקיפות פיזיות הם מחוץ להיקף.
- היכן אפשר לבדוק אם VBS רץ?
- הסתכלו על השדה Virtualization-based security ב-msinfo32, או בצעו שאילתה למחלקה Win32_DeviceGuard במרחב השמות root/Microsoft/Windows/DeviceGuard מ-PowerShell. אם SecurityServicesRunning מכיל 1, Credential Guard רץ; אם הוא מכיל 2, Memory integrity (HVCI) רץ.