歡迎來到興華永恒!加入收藏設為首頁
您當前所在位置:首頁 > 技術專欄 > 專業發布
技術專欄

針對CVE-2015-2545漏洞研究分析(中篇)


3.5.6 字典對象處理流程

關鍵的函數為forall在處理dict的過程,我們在第三個語句塊首部分下斷點<`EPSIMP32!RegisterPercentCallback+0x4664`>,觀察斷點,入棧了3個參數,調用一函數,那么我們需要思考下這三個參數是什么,通過查詢<<PLRM2.PDF>>,我們得到關鍵性的資料,[`圖2`]上面說如果第一個操作是字典類型,那么它會入棧一個`key`和一個`數據`,這里類似哈希表的形式,通過一個key可以迅速得到對應的數值;為什么`圖1`我寫`pNext`,通過`圖3`我們可以判斷其內容是否為null,則`lea eax, [ebp-14]`eax取出來的是個指針,所以這里這個名字主要是方便識別其為指針所定。

1491893143694777.png

圖1

1491893171474704.png

圖2

1491893193459016.png

圖3

3.5.7 對象結構解析

關于第一個CALL所做的事情,大致可以分為3個方面,給PNEXT附值,給KEY賦值,給VALUE賦值,這里說的簡單,里面的功能CALL需要自己手動調試下做好記錄更加方便理解是如何賦值的過程,這里直接說下是如何得到的這些數值,首先看下`ECX`所對應的內容`圖1`所示,其中`+0X8`偏移的位置是循環遍歷的次數,相當于一個`INDEX`也可以說是個`界限值`,里面的CALL循環條件的范圍就是 `400`, 其中`+0XC`的位置`8`表示`KEY`的個數,為什么,如`圖2`所示,那么關于`+0X0`偏移的位置則是個`基址`的意思,所有的結果都是通過[基址+偏移*X]的形式得到相應的數據,`圖3`表示第一個`KEY1`中的內容,同時`2B4`則為下標,通過基址+下標*4即可獲取第一個KEY1對應內容的地址,這0x28個字節就是個結構體,大致內容如下所示,正好可以跟我們的數據一一對應,不過這里還是需要`多跟幾遍`才會更加明白`結構`的情況,當跑完第一個CALL之后的內存情況如圖4所示。

2017-03-27_163447.png

圖1

1491893295712524.png

圖2

2017-03-27_164236.png

圖3

     

 struct {    
      dword * pNext; //指向下個結構體
      dword dwIndex; //下標
      ps_obj key;   //key
      ps_obj value;  //數據
      }kv_pair_element;
     
      struct PostScript object {
      dword type;//類型
      dword attr; //屬性
      dword value1; //數據
      dword value2; //數據
      }ps_obj;

2017-03-27_165635.png

圖4

00030000[類型] 00000000[屬性] 000001ff[數據]  04f32ea4[數據]
00000300[類型] 00000000[屬性] 04f69db0[數據]  04f32ea4[數據]
04f8fd98[pNext]

3.5.8 釋放空間函數分析

第二call,第三call,為同一call,在對key與value進行操作,copy到其他位置,之后的`PROC`則為重點call,此call則執行`forall`的所有的操作,我們只需要在copy函數的位置下斷點即可得到出發漏洞的位置<copy:`EPSIMP32!RegisterPercentCallback+0x15582`>,然后我們單步跟蹤即可,這里可以先用ida觀察下copy的大致流程,然后通過動態的方式更好的去跟蹤我們想要的數據,由于copy的函數塊比較大,動態調試起來也不是特別容易,我這里跟的時候是每個call都跟進去了,很費時間,但肯定可以找到想要的函數數據的,這里我直接給下偏移<`EPSIMP32!RegisterPercentCallback+0x12e8e`>,如`圖1`所示為釋放過程的函數<`EPSIMP32+0x1a0e8`>,這個釋放的過程可以仔細觀察下,還記得開始的時候的this指針所指向的內容嗎?[[this]],記得第一個call的時候,我們獲取KEY1-KEY8都是存在以[[this]]為基址,然后加上一個偏移得到這些數據,第一次的循環delete也是從[[this]]為基址開始遍歷,判斷是否為null,不是空則delete,那么這正片空間都被delete了,這個的范圍也是我們剛剛進入第一個call的時候的一個下標`400`,循環結束之后,delete this,并且清空`+0x0`, `+0x8`,就是清空key的個數。

1491893589730477.png

圖1

1491893613379181.png

圖2(釋放:dict1 copy dict2—>釋放dict2過程)

3.5.9 copy字典對象

之后會進行拷貝的操作,要把dict1–>copy到dict2中,則會new一段空間,而這段空間剛剛好為之前所釋放的[[this]],這里new的是`0x1000`大小,并且通過`memset`清空剛剛申請的空間中的內容`圖1,2`所示,之后會繼續new0x28空間大小,為什么?因為`dect1–>copy–>dect2`中,diect1只有`1個key`,則在0x1000中所填充的數據也就是1個4字節地址,所以需要new 0x28大小來保存數據圖3所示,copy完數據`圖4`所示。

1491893712750396.png

圖1

1491893741462057.png

圖2(新new空間與釋放的dict2一致)

1491893794695892.png

圖3

2017-03-27_184239.png

圖4(new0x28大小空間:內容pNext,index, 類型,屬性,數據,數據,類型,屬性,數據,數據)

3.5.10 填充構造數據

之后則為putinterval操作的過程,這個就會填充我們的pNext指針所指向的數據空間,斷點位置<`EPSIMP32!RegisterPercentCallback+0x160da`>,然后會進行`memcpy`的操作,把我們數據正好填充到我們之前的pNext所指向的空間中,這樣會whlile循環會再次跑一邊,而這次的 key,vale則是我們自己所構造的指定數據,結構如下所示。

1491893888518643.png

圖1

00000000[pNext]    000003ff[index]    00000003[類型]    00000000[屬性]
00000000[key.valu1]    44444444[key.value2]    00000500[類型]    00000000[屬性] 
00000000[value.1]    0462e0b0[value.2]//這里是原來數據,并非復制過來的數據
在線咨詢 周一至周五
09:00-18:00
老师让我脱她乳罩摸她乳视频