לדלג לתוכן

אמון אתחול ובידוד חומרה

נניח שכתבנו driver תקין, אבל במחשב אחד הוא נטען ובמחשב אחר הוא נדחה. ההבדל יכול להופיע עוד לפני שDriverEntry שלנו קיבל הזדמנות לרוץ. כדי לחקור את המצב הזה צריך לצאת לרגע מהתהליך שלנו ולהבין מי בכלל מרשה לקוד להתחיל.

עד עכשיו בדקנו הרשאות של משתמשים, הגנות של דפים וחתימות של קבצים. כל בדיקה כזאת נשענת על קוד שמבצע אותה. אם מישהו החליף את הקוד של הבודק, התשובה שלו כבר אינה ראיה טובה. מכאן מגיע הצורך בשרשרת אמון שמתחילה לפני מערכת ההפעלה.

מי בודק את מי

המנגנון של Secure Boot מפעיל מדיניות אמון של הfirmware על רכיבי האתחול. המשך השרשרת בתוך Windows מכונה Trusted Boot וכולל בדיקות של רכיבי מערכת נוספים. חתימה תקפה אומרת שהקובץ מתאים לזהות ולמדיניות שנבדקו; היא אינה הוכחה שהקוד נטול באגים. את תפקידי השלבים אפשר לראות בתיעוד האתחול המאובטח.

המדידה של Measured Boot מוסיפה ראיות לגבי מה שנטען. החיבור לTPM מאפשר להשתמש בראיות בתהליך attestation, כאשר הצד המאמת בודק גם טריות וגם מדיניות. המדידה עצמה אינה בהכרח הפעולה שחוסמת רכיב. לכן השאלות ״מה הותר לטעון״ ו״מה נמדד״ מובילות למסלולי חקירה שונים. אפשר לעקוב אחר ההבחנה בתיאור שרשרת האתחול והמדידה.

נחשוב על שני קבצים חתומים מאותו ספק. באחד התגלתה חולשה. הבדיקה הקריפטוגרפית של החתימה יכולה להצליח בשניהם, ובכל זאת מדיניות עדכנית יכולה לדחות אחד מהם. מכאן שגרסת המדיניות והrevocation הן חלק מהניסוי, בדיוק כמו גרסת הקובץ.

מה מוסיף בידוד בעזרת hypervisor

הגבול בין user mode לקרנל כבר מוכר לנו. המנגנון של VBS מוסיף שימוש בווירטואליזציה כדי לבודד חלק מפעולות האבטחה מסביבת הקרנל הרגילה. השירות HVCI, שמופיע גם בשם Memory Integrity, משתמש בסביבה הזאת לאכיפת כללי code integrity בקרנל. הדרייבר צריך להתאים להגנות הפעילות, ולא רק לעבור קומפילציה. התצורה, דרישות החומרה והאפשרות לבדוק מה באמת רץ מתוארות בתיעוד Memory Integrity.

ההפרדה הזאת אינה מתקנת double completion בdriver שלנו. היא גם אינה מעניקה אישור להשתמש בpointer אחרי ששוחרר. כאן כדאי לעצור ולשאול איזה תוקף או איזה כשל כל מנגנון אמור לעצור. הגנה על טעינת קוד והוכחת תקינות של state machine הן עבודות שונות, ושתיהן נחוצות.

בודקים את המחשב לפני שמסבירים אותו

הסקריפט הבא קורא מצב ואינו משנה הגדרות. מריצים בPowerShell עם ההרשאות שהשאילתות דורשות. שגיאת גישה או חומרה שאינה נתמכת נשמרת כמידע חסר, ולא מומרת אוטומטית לערך ״כבוי״.

$ErrorActionPreference = 'Stop'
$report = [ordered]@{
    timeUtc = [DateTime]::UtcNow.ToString('o')
    os = $null
    secureBoot = $null
    secureBootError = $null
    deviceGuard = $null
    deviceGuardError = $null
}
$osInfo = Get-CimInstance Win32_OperatingSystem
$report.os = [ordered]@{
    caption = $osInfo.Caption
    version = $osInfo.Version
    build = $osInfo.BuildNumber
}
try { $report.secureBoot = Confirm-SecureBootUEFI }
catch { $report.secureBootError = $_.Exception.Message }
try {
    $guardInfo = Get-CimInstance -Namespace root\Microsoft\Windows\DeviceGuard `
        -ClassName Win32_DeviceGuard
    $report.deviceGuard = [ordered]@{
        vbsStatus = $guardInfo.VirtualizationBasedSecurityStatus
        configured = @($guardInfo.SecurityServicesConfigured)
        running = @($guardInfo.SecurityServicesRunning)
        available = @($guardInfo.AvailableSecurityProperties)
    }
} catch { $report.deviceGuardError = $_.Exception.Message }
$report | ConvertTo-Json -Depth 5

המספרים במערכים הם קודים של הספק. לדוגמה, נוכחות הערך 2 ברשימת השירותים שרצים מציינת Memory Integrity לפי החוזה המתועד. לא מחפשים מחרוזת מקרית בפלט ולא מניחים שconfigured וrunning חייבים להיות זהים.

נשמור את הדוח לצד תוצאות טעינת הdriver מפרק 13. כאשר יש כשל, נצרף את שגיאת הטעינה ואת אירועי Code Integrity המתאימים בזמן. ההשוואה מתחילה מהבדל שנצפה. היא אינה מתחילה מכיבוי הגנות עד שהdriver מצליח לעלות.

איך מתכננים ניסוי שאפשר לפרש

הניסוי נערך בVM של המעבדה עם snapshot ועם תצורה מתועדת. משנים גורם אחד, מבצעים reboot אם השינוי דורש זאת וקוראים שוב את המצב בפועל. במכונה וירטואלית יכולת nested virtualization והגדרות הhost משפיעות על מה שהguest מסוגל להפעיל.

הבדיקה של driver במצב test signing והבדיקה שלו תחת מדיניות הפצה אמיתית הן שתי תחנות שונות. ההצלחה בתחנה הראשונה אינה ראיה להצלחה בשנייה. גם kernel debugging יכול להשפיע על תצורת האבטחה והמדידה, ולכן מתעדים אותו כגורם בניסוי.

נרצה לסיים את השיעור עם תרשים קצר: מי טוען את הרכיב, מי מאמת אותו, איפה נשמרת המדיניות ואיזה מידע קיבלנו כאשר נדחה. ברגע שאפשר לענות על ארבע השאלות האלה, הודעת ״הdriver לא נטען״ הופכת להתחלה של חקירה מסודרת.