Win10安全特性之執行流保護

wyzsk發表於2020-08-19
作者: 騰訊電腦管家 · 2015/02/04 15:07

0x00 背景


微軟在2015年1月22日公佈了windows10技術預覽版,Build號:9926。電腦管家反病毒實驗室第一時間對其引入的新安全特性進行了深入分析。

眾所周知,漏洞利用過程中攻擊者若要執行惡意程式碼,需要破壞程式原有指令的的正常執行。執行流保護的作用就是在程式執行的過程中檢測指令流的正常性,當發生不符合預期的情況時,及時進行異常處理。業界針對執行流保護已經有一些相對成熟的技術方案,在微軟釋出的windows10最新版本中,我們看到了這一防護思想的廣泛使用。

0x01 CFI


CFI即控制流完整性Control-Flow Integrity,主要是透過對二進位制可執行檔案的動態改寫,以此為其增加額外的安全性保障。

enter image description here

這是Mihai Budiu介紹CFI技術時使用的例子。這裡透過對二進位制可執行檔案的改寫,對jmp的目的地址前插入一個在改寫時約定好的校驗ID,在jmp的時候看目的地址前的資料是不是我們約定好的校驗ID,如果不是則進入錯誤處理流程。

同理在call 和 ret的時候也可以進行改寫:

enter image description here

左半部分就是一個對call的改寫,右半部分是對ret的一個改寫,在call的目的地址和ret的返回地址之前插入校驗ID,然後改寫的call 和ret中增加了對校驗ID的檢查,如果不符合預期,進入錯誤處理流程,這個思路和上邊對jmp的處理是完全一樣的。

0x02 CFG


實現CFI需要在jmp、call 一個暫存器(或者使用暫存器間接定址)的時候,目的地址有時必須透過動態獲得,且改寫的開銷又很大,這些都給CFI的實際應用造成了一定的困難。

微軟在最新的作業系統win10當中,對基於執行流防護的實際應用中採用了CFG技術。CFG是Control Flow Guard的縮寫,就是控制流保護,它是一種編譯器和作業系統相結合的防護手段,目的在於防止不可信的間接呼叫。

漏洞攻擊過程中,常見的利用手法是透過溢位覆蓋或者直接篡改某個暫存器的值,篡改間接呼叫的地址,進而控制了程式的執行流程。CFG透過在編譯和連結期間,記錄下所有的間接呼叫資訊,並把他們記錄在最終的可執行檔案中,並且在所有的間接呼叫之前插入額外的校驗,當間接呼叫的地址被篡改時,會觸發一個異常,作業系統介入處理。

以win10 preview 9926中IE11的Spartan html解析模組為例,看一下CFG的具體情況:

enter image description here

這裡就是被編譯器插入的CFG校驗函式

enter image description here

但是靜態情況下預設的檢測函式是一個直接return的空函式,是微軟在和我們開玩笑嗎?

enter image description here

透過動態除錯看一下

enter image description here

從上圖我們可以看出,實際執行時的地址和我們透過IDA靜態看到的地址是不一樣的,這裡就涉及到CFG和作業系統相關的那部分。支援CFG版本的作業系統載入器在載入支援CFG的模組時,會把這個地址替換成ntdll中的一個函式地址。不支援CFG版本的作業系統不用理會這個檢測,程式執行時直接retn。

這是ntdll中的檢測函式

enter image description here

原理是在進入檢測函式之前,把即將call的暫存器值(或者是帶偏移的暫存器間接定址)賦值給ecx,在檢測函式中透過編譯期間記錄的資料,來校驗這個值是否有效。

檢測過程如下:

首先從LdrSystemDllInitBlock+0x60處讀取一個點陣圖(bitmap),這個點陣圖表明瞭哪些函式地址是有效的,透過間接呼叫的函式地址的高3個位元組作為一個索引,獲取該函式地址所在的點陣圖的一個DWORD值,一共32位,證明1位代表了8個位元組,但一般來說間接呼叫的函式地址都是0x10對齊的,因此一般奇數位是不使用的。

透過函式地址的高3個位元組作為索引拿到了一個所在的點陣圖的DWORD值,然後檢查低1位元組的0-3位是否為0,如果為0,證明函式是0x10對齊的,則用3-7bit共5個bit就作為這個DWORD值的索引,這樣透過一個函式地址就能找到點陣圖中所對應的位了。如果置位了,表明函式地址有效,反之則會觸發異常。

這裡有個有趣的東西,雖然使用test cl,0Fh檢測是否0x10對齊,如果對齊的話實際上用3-7位作為索引,也就是說第3位一定是0。但如果函式地址不是0x10對齊的話,則會對3-7位 or 1,然後再作為索引。這樣就有一個弊端,如果一個有效的間接呼叫的函式地址是8位元組對齊的,那麼其實是允許一個8位元組的一個錯位呼叫的,這樣可能導致的結果就是可能造成雖然透過了校驗,但是實際呼叫的地址並不是原始記錄的函式地址。

還有一點,如果這時候漏洞觸發成功,間接呼叫的暫存器值已經被攻擊者修改了,這時候從bitmap中取值的時候可能造成記憶體訪問無效。請看LdrpValidateUserCallTargetBitMapCheck符

號處的這條指令:mov edx,dword ptr [edx+eax*4] edx是bitmap地址,eax是索引,但如果eax不可信了,這個很有可能,則會導致記憶體訪問異常,並且這個函式並沒有異常處理。這是因為微軟為了效率考慮(畢竟這個校驗函式的呼叫十分頻繁,一個開啟CFG的模組可能會有上萬個呼叫處),微軟在ntdll! RtlDispatchException中對該地址發生的異常做了一個處理:

enter image description here

如果異常發生的地址命中LdrpValidateUserCallTargetBitMapCheck,則進行一個單獨處理,RtlpHandleInvalidUserCallTarget會校驗當前程式的DEP狀態和要間接呼叫的地址(ecx)的記憶體屬性,如果當前程式關閉了DEP並且要間接呼叫的地址有可執行屬性,則觸發CFG異常,否則透過修改pContext把EIP修正到ret返回處,並且表明異常已被處理。

最後再說下這個原始的bitmap,在系統初始化的時候,記憶體管理器初始化中會建立一個Section(MiCfgBitMapSection32),這個Section在Win8.1上的大小是透過MmSystemRangeStart(32位下是0x80000000)計算的,前面提到過bitmap裡面1位代表8位元組,計算完後正好是32MB

enter image description here

而在Win10上MiCfgBitMapSection32的大小有了變化,直接寫死成了0x3000000(48MB)

enter image description here

Section建立完成後在每個程式啟動的時候會對映進去

(NtCreateUserProcess-> PspAllocateProcess-> MmInitializeProcessAddressSpace-> MiMapProcessExecutable-> MiCfgInitializeProcess)

對映的時候作為shared view,除非某一個程式修改了這片記憶體。

在一個CFG模組對映進來的時候,重定位過程中會重新解析PE檔案LOADCONFIG中的Guard Function Table以重新計算該模組對應的bitmap(MiParseImageCfgBits),最後更新到MiCfgBitMapSection32中去(MiUpdateCfgSystemWideBitmap)。

0x03 電腦管家XP防護的執行流保護


早些年的漏洞攻擊程式碼可以直接在棧空間或堆空間執行指令,但近幾年,微軟作業系統在安全性方面逐漸加強,DEP、ASLR等防護手段的應用,使得攻擊者必須藉助ROP等繞過手段來實現漏洞利用。在ROP利用中,棧交換指令Stack pivot必不可少。

針對ROP攻擊的防禦長久以來是漏洞防禦的一個難題,因為ROP指令在靜態層面分析與程式的正常指令流毫無差別,且執行時也是在合法模組內執行,因此極難防禦。

管家漏洞防禦團隊針對ROP利用的特點,從整個程式的執行流層面進行分析,研究出在動態執行時區分是合法指令流還是異常指令流的方法,其思想與CFI不謀而合。

下邊就是一個由於錯位彙編形成的比較常用的棧交換指令

enter image description here

而實際正常的執行流程是這樣的

enter image description here

以上是沒有開啟XP防護的情況

開啟電腦管家XP防護之後:

enter image description here

enter image description here

此時如果攻擊者依靠靜態分析時得到棧交換指令位置來執行ROP攻擊的話,會被執行流保護邏輯發現異常,後續攻擊則無法實現。

0x04 尾聲


CFG防護方法需要在編譯連結階段來完成準備工作,同時需要作業系統的支援。CFI無需編譯時的幫助,且不僅能夠防禦call呼叫,能夠對全部執行流進行保護。但CFI需要插入大量的檢測點,並且在執行過程中檢測的頻率極高,難免對程式執行效率帶來影響。

電腦管家XP版的防禦方法相比於前兩者,對效能的影響更小,但這種方法是針對舊版作業系統的緩解方案,通用性會打折扣。所以建議廣大windows使用者儘量升級到最新作業系統,享受全面的安全保護。而由於某些原因無法升級的使用者也不必擔心,管家XP版會繼續提供最高的安全防護能力。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章