CVE-2018-5996 7zip學(xué)習(xí)筆記
前置知識(shí)
Range encoding
顧名思義,就是把一個(gè)字符串流根據(jù)字符出現(xiàn)的頻率,轉(zhuǎn)化成一個(gè)范圍(閾值)
https://en.wikipedia.org/wiki/Range_encoding
簡(jiǎn)介
原文
https://landave.io/2018/01/7-zip-multiple-memory-corruptions-via-rar-and-zip/#fn:2
可觸發(fā)堆溢出和棧溢出
PPMd是壓縮算法RAR3壓縮算法的實(shí)現(xiàn)
bug
對(duì)于每個(gè)RAR版本,最多創(chuàng)建一個(gè)coder。如果同一個(gè)版本有多個(gè)實(shí)例,就使用同一個(gè)coder。
調(diào)用code可能返回失敗S_FALSE,而且被創(chuàng)建的coder下次仍然會(huì)使用。我們找到一個(gè)能讓它返回
S_FALSE的函數(shù)。
CInBufferException,當(dāng)從輸入流中讀入時(shí),這個(gè)異??赡軙?huì)被拋出,我們可以用一個(gè)RAR3實(shí)例
來觸發(fā)這個(gè)異常,拋出S_FALSE
一旦RAR3在PPMd更新時(shí)拋出異常,會(huì)讓PPMd模型處于不穩(wěn)定狀態(tài),同樣的coder會(huì)被用作下個(gè)實(shí)例,
即使在CInBufferException已經(jīng)拋出S_FALSE的異常碼
RAR3解碼器維持PPMd模型的狀態(tài),PPMd模型只有在一個(gè)item顯示要求時(shí)才會(huì)重新初始化,
這意味著我們可以這樣做:
- 當(dāng)PPMd模型在更新時(shí),構(gòu)造一個(gè)RAR3實(shí)例來觸發(fā)ClnBufferException,
- 之后的item沒有重置,因此PPMd會(huì)處于不穩(wěn)定狀態(tài)
PPMd Preliminaries
PPMd壓縮算法是建立有限階D的馬爾科夫模型,模型狀態(tài)實(shí)質(zhì)是一個(gè)256元的上下文樹,最大深度為D。
從根到上下文節(jié)點(diǎn)的路徑將被解釋為字節(jié)符號(hào)序列,父關(guān)系將被理解為后綴關(guān)系。除此之外,每一個(gè)
上下文結(jié)點(diǎn)保存與后繼節(jié)點(diǎn)相關(guān)的后繼符號(hào)的統(tǒng)計(jì)頻率。
使用以下名為CPpmd7_Context的結(jié)構(gòu)體來表示一個(gè)上下文結(jié)點(diǎn)
typedef struct CPpmd7_Context_ {
UInt16 NumStats; //Stats array中元素個(gè)數(shù)
UInt16 SummFreq;
CPpmd_State_Ref Stats;
CPpmd7_Context_Ref Suffix;
} CPpmd7_Context;
typedef struct {
Byte Symbol;
Byte Freq;
UInt16 SuccessorLow;
UInt16 SuccessorHigh;
} CPpmd_State;
- 第一個(gè)RAR3實(shí)例創(chuàng)建的同時(shí),一些上下文節(jié)點(diǎn)也同時(shí)被創(chuàng)建,Ppmd7_DecodeSymbol將p->MinContext
向上移動(dòng)一次,知道找到相應(yīng)的符號(hào)為止。解碼器方法會(huì)因?yàn)镃InBufferException失敗。 - 由于下一個(gè)RAR3實(shí)例并沒有重置位,我們會(huì)繼續(xù)使用之前創(chuàng)建的PPMd模型。
- Ppmd7_DecodeSymbol使用一個(gè)新的范圍解碼器,并且
p->MinContext!=p->maxContext。
它在p->MinContext中尋找對(duì)應(yīng)的符號(hào),但這個(gè)符號(hào)事實(shí)上已經(jīng)在p->MaxContext和p->MinContext之間
的上下文,當(dāng)UpdateModel函數(shù)被調(diào)用,這個(gè)符號(hào)就會(huì)被重復(fù)添加到State數(shù)組
棧溢出和堆溢出
state指針數(shù)組固定大小且存放在棧中,并且在向其中添加新state指針時(shí)不會(huì)檢查長(zhǎng)度,故能構(gòu)建棧溢出
state內(nèi)容存放在堆中,溢出原理和上述相同