Dela via


Kontrollera Flow Guard för plattformssäkerhet

Vad är Control Flow Guard?

Control Flow Guard (CFG) är en högoptimerad plattformssäkerhetsfunktion som skapades för att bekämpa sårbarheter för minnesskada. Genom att införa strikta begränsningar för var ett program kan köra kod från gör det det mycket svårare för sårbarheter att köra godtycklig kod via sårbarheter som buffertspill. CFG utökar tidigare tekniker för sårbarhetsreducering, till exempel /GS (buffertsäkerhetskontroll), Data Execution Prevention (DEP)och Address Space Layout Randomization (ASLR).

Att använda CFG kan vara till hjälp för att:

  • Förhindra minnesskada och utpressningstrojanattacker.
  • Begränsa serverns funktioner till endast det som behövs vid en viss tidpunkt för att minska attackytan.
  • Gör det svårare att utnyttja godtycklig kod genom sårbarheter som buffertöversvämningar.

Den här funktionen är tillgänglig i Microsoft Visual Studio och körs på CFG-Aware versioner av Windows. Windows 10 och Windows 11 på klienten och Windows Server 2019 och senare på serversidan.

Utvecklare uppmanas starkt att aktivera CFG för sina program. Du behöver inte aktivera CFG för varje del av koden eftersom en blandning av CFG-aktiverad och icke-CFG-aktiverad kod fungerar bra. Om cfg inte aktiveras för all kod kan det dock öppna luckor i skyddet. Dessutom fungerar CFG-aktiverad kod bra på CFG-Unaware versioner av Windows och är därför helt kompatibel med dem.

Hur kan jag aktivera CFG?

I de flesta fall behöver du inte ändra källkoden. Allt du behöver göra är att lägga till ett alternativ i ditt Visual Studio-projekt, så aktiverar kompilatorn och länkaren CFG.

Den enklaste metoden är att navigera till Project | Egenskaper | Konfigurationsegenskaper | C/C++ | Kodgenerering och välj Ja (/guard:cf) för Control Flow Guard.

En skärmbild av egenskapen Control Flow Guard i build-konfiguration för kodgenerering i Visual Studio.

Du kan också lägga till /guard:cf i Project | Egenskaper | Konfigurationsegenskaper | C/C++ | Kommandorad | Ytterligare alternativ (för kompilatorn) och /guard:cf till Project | Egenskaper | Konfigurationsegenskaper | Linker | Kommandorad | Ytterligare alternativ (för länkaren).

En skärmbild av C/C++-kommandoradskonfigurationen för ytterligare alternativ i Visual Studio med egenskapen inställd på /guard:cf

En skärmbild av konfigurationen av ytterligare alternativ för kommandoradslänkare i Visual Studio där egenskapen är inställd på /guard:cf

Mer information finns i /guard (Aktivera Control Flow Guard).

Om du skapar projektet från kommandoraden kan du lägga till samma alternativ. Om du till exempel kompilerar ett projekt med namnet test.cpp använder du cl /guard:cf test.cpp /link /guard:cf.

Du kan också välja att dynamiskt styra uppsättningen med icall-måladresser som anses giltiga av CFG med hjälp av SetProcessValidCallTargets från API:et för minneshantering. Samma API kan användas för att ange om sidor är ogiltiga eller giltiga mål för CFG. Funktionerna VirtualProtect och VirtualAlloc behandlar som standard en angiven region med körbara och bekräftade sidor som giltiga indirekta anropsmål. Du kan åsidosätta det här beteendet, till exempel när du implementerar en just-in-time-kompilator, genom att ange PAGE_TARGETS_INVALID när du anropar VirtualAlloc eller PAGE_TARGETS_NO_UPDATE när du anropar VirtualProtect enligt Minnesskyddskonstanter.

Hur kan jag veta om en binär fil är under kontrollflödesvakt?

Kör dumpbin-verktyget (ingår i Visual Studio-installationen) från Visual Studio-kommandotolken med alternativen /headers och /loadconfig: dumpbin /headers /loadconfig test.exe. Utdata för en binär fil under CFG bör visa att rubrikvärdena innehåller "Guard" och att belastningskonfigurationsvärdena inkluderar "CF Instrumented" och "FID table present".

En skärmbild av utdata från dumpbin /headers

En skärmbild av utdata från dumpbin/loadconfig

Hur fungerar CFG verkligen?

Programvarusårbarheter utnyttjas ofta genom att tillhandahålla osannolika, ovanliga eller extrema data till ett program som körs. En angripare kan till exempel utnyttja en sårbarhet för buffertspill genom att ge mer indata till ett program än förväntat och därmed köra över det område som reserverats av programmet för att hålla ett svar. Detta kan skada intilliggande minne som kan innehålla en funktionspekare. När programmet anropar via den här funktionen kan det sedan gå till en oavsiktlig plats som anges av angriparen.

En kraftfull kombination av kompilerings- och körningsstöd från CFG implementerar emellertid kontrollflödesintegritet som noggrant begränsar var indirekta anropsinstruktioner kan exekvera.

Kompilatorn gör följande:

  1. Lägger till enkla säkerhetskontroller i den kompilerade koden.
  2. Identifierar den uppsättning funktioner i programmet som är giltiga mål för indirekta anrop.

Körmiljöstöd som tillhandahålls av Windows-kärnan:

  1. Upprätthåller effektivt ett system som identifierar giltiga indirekta anropsmål.
  2. Implementerar logiken som verifierar att ett indirekt anropsmål är giltigt.

Så här illustrerar du:

Ett diagram som illustrerar CFG-kontrollerna som infogas av kompilatorn.

När en CFG-kontroll misslyckas vid körning avslutar Windows omedelbart programmet, vilket förhindrar alla exploateringar som försöker anropa en ogiltig adress indirekt.

/guard (Aktivera kontrollflödesvakt)

/GUARD (Aktivera skyddskontroller)