<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/papers/11032

            Ke Sun([email protected])

            原文:http://en.wooyun.io/2015/12/08/33.html

            0x00 摘要


            混淆是一種能增加二進制分析和逆向工程難度與成本的常用技術。主流的混淆技術都是著眼于使用與目標CPU相同的機器代碼,在相同的處理器模式下,隱藏代碼并進行控制。本文中引入了一種新的混淆方法,這一方法利用了64Windows系統中的32位/64位交叉模式編碼。針對靜態和動態分析工具的案例研究證明了這種混淆技術雖然簡單,但是十分有效。

            0x01 64位Windows中的模式轉換


            所有的64位Windows操作系統都能向下兼容未修改過的 32位應用,這是通過WoW64(64位Windows上的32位Windows)子系統實現的。WoW64使用了3個動態鏈接庫(Wow64.dll,Wow64win.dll 和 Wow64cpu.dll),提供了一個兼容層,用作64位內核與32位應用{1}之間的接口,借此,處理器模式就可以在32位和64位之間動態地切換。

            在任何時間中,處理器模式都是由當前代碼段(CS)描述符中的控制位決定的。圖1就是一個段描述符的示意圖。L位(21位)是“64位代碼段”控制標記:“值為1則說明這個代碼段中的指令會在64位模式下執行,值為0則說明在這個代碼段中的指令會在兼容(32位)模式下執行。” {2}

            p1

            圖1-段描述符的示意圖 {2}

            64位Windows下的任何應用,無論是32位還是64位,在載入到內存中時,都至少有兩個代碼段。這兩個代碼段的32位地址空間映射是完全重合的,但是段選擇器是不同的:其中一個的選擇器是0x23,L標記為0(32位代碼段);另一個的選擇器是0x33,L標記為1(64位代碼段)。 在一個應用的PE(可移植可執行)標頭中,“Machine”字段的標簽是32位還是64位PE決定了這個應用的默認代碼段。

            當遠分支指令把控制流從一個代碼段上轉移到另一個有著不同L標記的代碼段上時,處理器模式交換就會被觸發。例如,如果一個32位應用在64位Windows中執行,默認的CS選擇器就會是0x23,處理器會是32位模式。如果,使用了遠轉移來跳轉到一個選擇器是0x33的代碼段上,那么在執行完這條指令后,處理器模式就會切換到64位,在從32位向64位切換時也是一樣的。

            有很多遠分支指令都可以用于觸發模式轉換,包括(1)遠轉移(2)遠調用(3)遠返回和(4)中斷返回。這些指令就像是不同維度的平行世界之間的傳送門,在需要時可以通過這些門穿梭于不同的世界。因為這種方便的可控模式交換,混淆技術才有了機會來使用交叉模式編碼,這種方法既可以用在32位應用中,也可以用在64位應用上。

            唯一需要注意的是64位應用,在64位模式中使用的內存地址需要限制在低于2G的內存空間中,否則,在切換到32位模式時,會出現內存地址沖突。

            0x02 交叉模式混淆的概念


            所有的IA指令都可以分為兩類:兼容交叉模式的指令和不兼容交叉模式的指令。兼容交叉模式指的是指令的機器代碼在32位和64位模式下都是有效的,并且含義也都是完全相同的,否則指令就會被視作不兼容交叉模式。

            英特爾的軟件開發人員手冊中列出了每條指令及其可應用模式的詳細信息。在這個指令表中,“64-bit Mode”字段和“Compat/Leg Mode”(32位)字段都顯示是“有效的”(類似于圖2中的“MOV r32, imm32”),這就是一條兼容指令。如果其中任何一個字段不是“有效的”,那么這就是一條不兼容指令。這兩類指令都可以用于交叉模式混淆。

            p2

            圖2-兼容與不兼容指令示例

            2.1兼容指令

            雖然兼容指令的執行在32位和64位模式下都是相同的,但是,考慮到兩種模式的差異,得到的結果也有可能是不同的。圖3中就是一個簡單的例子。從圖中可以看到,無論是在32位還是64位模式下,在運行時反匯編同一組指令會得到完全相同的結果。

            p3

            圖3-兼容指令在不同模式下的執行示例

            “call”只是簡單地調用了下一條指令“mov ebx, esp”,并且這個代碼塊僅僅會檢查棧指針在“call”指令的執行前后,修改了多少字節。由于棧框架大小的區別,在32位模式下,eax中的結果是4;在64位模式下,eax中的結果是8。這就證明了,同一組指令的結果要取決于模式,也就是說可以利用混淆數據或控制流來對抗某種單一模式的分析工具。

            2.2不兼容指令

            利用不兼容指令進行混淆更加直接,因為,這類指令只在一種模式下是有效的。一條64位的不兼容指令要么會被視作有效指令,要么就在32位模式下解釋成完全不同的指令,反之亦然(如圖4),不支持處理動態模式轉換的分析工具在這時就會遇到問題。

            p4

            圖4-不兼容指令在不同模式下的執行示例

            0x03 案例研究交叉模式混淆


            一個很簡單的例子就能證明交叉模式混淆的有效性。圖5是交叉模式代碼的示意圖,這些代碼首先會作為32位原生指令來執行。然后,通過使用遠轉移,跳轉到CS 0x33,把處理器轉換成64位模式,并繼續執行64位原生指令(在32位模式中不兼容)。64位代碼在執行后會解碼另一組32位原生指令,在通過遠返回把處理器切換回32位模式后,接著這些32位指令就會運行。最終,這一部分的32位代碼會解密出秘鑰。

            p5

            圖5-使用了交叉模式編碼的示例程序示意圖

            圖6中是這個交叉模式代碼在命令行中執行的結果。在十六進制中打印出的代碼段選擇器證實了,處理器確實從32位轉換到了64位,又從64位轉換成了32位。

            p6

            圖6-交叉模式代碼示例在命令行中的執行

            3.1靜態分析工具

            當使用32位的IDA Pro來分析上面的交叉模式代碼時,很明顯,在通過遠轉移進行模式交換后,IDA仍然會把64位的原生代碼反匯編成32位的指令,導致反匯編結果與實際的64位指令出現偏差。(圖7)

            p7

            圖7-對比IDA Pro的運行時反匯編與靜態反匯編

            如果使用64位版本的IDA Pro,IDA仍然會在32位模式下分析這一交叉模式代碼,因為IDA會自動把這些代碼識別成一個32位應用。此時,再通過遠轉移來轉換模式,反匯編就會出錯,并把控制流帶到錯誤的地址(圖8)。

            p8

            圖8-64位IDA Pro的靜態反匯編顯示了錯誤的遠轉移地址

            除了廣泛使用的IDA,我們還使用了另一個靜態分析工具-Radare2來測試我們的交叉模式代碼。Radare2是一個開源的命令行框架,支持多個平臺上的逆向工程。類似于IDA,Radare2在32位模式下無法正確地反匯編64位原生代碼,而在64位下,無法正確地除了32位原生代碼。

            3.2動態分析工具

            在運行時代碼分析中,動態二進制插樁(DBI)是一種廣泛應用的技術。在這次研究中,我們選擇了兩個常用的二進制翻譯工具- DynamoRio 和 Pin來運行測試程序。

            這兩個工具都無法處理從32位到64位的運行時模式轉換,并且在通過遠轉移進行模式轉換時會崩潰。圖9顯示,DynamoRio 和 Pin都無法在64位模式下,打印出代碼段選擇器的值。

            p9

            (a)

            p10

            (b)

            p11

            (c)

            圖9-(a)命令行(b)DynamoRio(c)Pin執行交叉模式代碼的情況

            由于需要切換到32位模式,DynamoRio在執行64位應用時也遇到了類似的崩潰問題,而Pin直接停止運行,顯示錯誤信息“不支持通過遠返回來轉換不同的代碼段”。

            有趣的是,在僅僅使用兼容指令時,有時候DBI工具可能會在運行了用于切換模式的遠轉移后,繼續運行,但是,實際上模式并沒有切換。圖10中顯示,DynamoRio使用兼容指令運行了代碼,與2.1中討論的例子一樣。可以看到,程序運行到了模式交換點之后,但是,沒能真正的轉換到代碼段 0x33,而是停留在了CS 0x23。eax中的返回值是4而不是8,這與直接執行時的結果不同,從而為DBI環境監測創造了機會。

            p12

            (a)

            p13

            (b)

            圖9-(a)命令行(b)DynamoRio執行兼容交叉模式的代碼

            3.3調試工具

            我們還發現,在調試包含運行時模式切換的代碼時,交叉模式代碼還會給OllyDbg和WinDbg這樣的常用調試工具造成問題。32位的OllyDbg(目前64位不可用)在從32位切換到6位模式后,無法繼續調試。而64位的WinDbg可以正確的運行交叉模式代碼,但是在交叉模式條件下,修改過的代碼會出現單步執行問題。

            0x04 總結


            利用64位Windows系統向下兼容32位程序的優勢,交叉模式編碼可以作為一種非常有效的混淆技術。目前,大多數靜態分析工具、DBI工具和調試工具都是基于單一的處理器模式,這些工具在處理包含運行時模式交換的代碼時就會遇到問題。而且,只要在設計時稍加注意,交叉模式代碼還可以用于檢測DBI環境。

            從理論上說,只要讓這些分析工具能適應動態模式交換,那么交叉模式問題就會迎刃而解,只不過需要大量的工程努力。

            0x05 致謝


            感謝李曉寧,亞歐對此次研究和審閱做出的貢獻。

            0x06 參考


            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线