這個漏洞是乙個ie瀏覽器裡,vbs方面的漏洞,yuange首先放出了這個漏洞的完整dve的利用,接下來各個安全團隊都出了比較好的分析報告。這個漏洞本身的原理算是比較傳統,但是利用技術非常巧妙。置位safemode後,shellcode相當於用指令碼語言直接編寫,通用性穩定性極強。閒暇之餘,也忍不住除錯一下。
除錯環境win7+ie8,參考了瀚海源的精簡版yuange poc,因為裡面有加入了通過vbs在偵錯程式裡打日誌的方法,就直接用了,感謝分享。
typedef struct farstruct tagsafearray safearray;
typedef struct tagsafearraybound safearraybound, *lpsafearraybound;
漏洞出在oleaut32!safearrayredim函式中,當新的陣列長度大於0x8000000時,無符號數被當作有符號數判斷,使記憶體分配失敗,直接返回,導致陣列元素個數已經被修改,即可以越界讀寫其它位址。除錯過程如下。
safearrayredim有兩個引數,乙個是safearray,另乙個是safearraybound。safearray是要修改陣列長度,safearrarybound裡面存放新陣列的長度,和起始索引值。
首先呼叫safearraysize計算陣列長度,如上圖,返回0x1f0。陣列元素大小為0x10,個數為0x1f。
從safearraybound裡取出新陣列元素個數,修改safearray的元素個數為0x800001f。
計算新陣列長度,為0x800001f0。
兩個長度相減,結果為0x80000000,經過jge有符號判斷,認為該值小於0。進入記憶體分配流程。
需要的記憶體為0x800001f0,記憶體分配失敗,後面再走就返回了。但是剛才陣列元素個數0x0800001f依然留在safearray物件的記憶體中,後面就可以越界讀寫了。
這個漏洞在記憶體分配失敗後,沒有將原來的陣列元素個數還原,致使可以在後面的vbs呼叫中,越界讀寫記憶體中的其它資料。到這裡,其實利用方法應該比較成熟了,記憶體布局後,型別混淆,位址洩露之類的一系列操作。下面感受一下dve的精彩之處。
由於aa() 可以越界讀寫,因此需要在aa()後面布置乙個陣列ab()。但是由於堆記憶體分配的隨機性,在aa()陣列後,未必能緊隨ab()陣列,因此在利用**中,迴圈嘗試分配陣列。直到出現aa ab陣列緊鄰。exp中**如下所示。
for i = 0 to 400
if over()=true then
isempty("over() success!!!")
document.write(i)
create=true
exit for
end if
next
function over()
on error resume next
isempty("over() running...")
dim type1,type2,type3
over=false
a0=a0+a3
a1=a0+2
a2=a0+&h8000000
redim preserve aa(a0)
redim ab(a0)
redim preserve aa(a2)
type1=1
ab(0)=1.123456789012345678901234567890 //666f74d3adf9f13f
aa(a0)=10
// type=9 indicate object
if(isobject(aa(a1-1)) = false) then
if(vartype(aa(a1-1))<>0) then
if(isobject(aa(a1)) = false ) then
type1=vartype(aa(a1))
end if
end if
end if
if(type1=&h2f66) then
isempty("cve-2014-6332: array ab and array aa cross!!!")
isempty("array ab:")
isempty(ab(0))
over=true
end if
redim preserve aa(a0)
end function
上面**判斷了aa ab是否緊鄰。 如果aa ab陣列想鄰,aa(a1-1)為ab所在堆塊起始部分,即8位元組的堆頭+ab(0)的前8位元組。ab 和 aa的關係如下圖所示。
首先判斷isboject(aa(a1-1))是否為false,因為aa(a1-1)屬性部分為heap header,當然返回false。其次 ,vartype(aa(a1-1)),vartype去取aa(a1-1)的第乙個word,這裡是0x2468,顯然也不等於0。接下來,注意到**中有一句:ab(0)=1.123456789012345678901234567890 //666f74d3adf9f13f,就是通過ab(0),改寫aa(a1)的屬性;當然isobject(aa(a1))==false。且vartype(aa(a1))==0x2f66;為什麼記憶體中是6f66,而取得的值是2f66,原因是vartype的處理流程。
可以看到,取得的word後,and 0xffffbfff。因此,這裡是2f66。這樣就判斷了aa ab是否緊鄰。
接著,通過這種aa ab交錯的修改方式,在aa(a1)處布置了testaaaaa函式位址,並且修改屬性為0x003,即vt_i4 。在aa(a1+2)布置mydata位址,並且修改aa(a1+2)屬性為0x200c,為safearray陣列型別。
上圖0x00515634為mydata資料。mydata資料偽造了乙個safearray結構,元素個數被設定成0x7fff0000,這樣通過這個safearray,可以索引到記憶體任意位址。注意到safearray中,celements為1,即陣列元素大小為1,而且pvdata為0,所以aa(a1+2)(i+&h11c+k)能直接索引到想要的位址上。
最後通過readmemo 函式,經過物件記憶體的讀取,讀取到colescript物件位址,然後搜尋safemode標誌,修改。在yuange的利用中,從偏移0x120開始搜尋,找到0xe,然後向這個地方寫入0,完成對safemode的改寫。還有一點就是,改的時候,yuange提前了4個位元組,比如在0x120處找到,則需要向0x11c處賦值,就是因為按照乙個varienttype來賦值的,不過因為ab(4)整個記憶體空間為0,所以0x120、0x11c、0x118、0x114都可以。readmemo的實現後面會分析。
0x020b7cf8為函式物件位址,通過幾次偏移,找到了colescript物件的起始位址。
下面分析一下readmemo ,即任意位址讀的實現。
ab(0)=0
aa(a1)=add+4
ab(0)=1.69759663316747e-313 // 0800000008000000
readmemo=lenb(aa(a1))
add為要讀的記憶體位址。先將add+4放到陣列元素aa(a1)內,接著通過ab(0)修改元素型別為vt_bstr。由於bstr長度存放在字串資料的起始的前4個位元組,這樣,呼叫lenb相當於從字串其實位址開始,減去4個位元組,讀取其記憶體的值。因此add需要加4,這樣lenb(aa(a1))才能返回add中的資料。
上圖中,0x00192688為aa(a1)起始位址,0x00192680為ab(0)起始位址,可以看出ab(0),已經將aa(a1)中的屬性修改為vt_bstr了。0x0046f874=add+4。
該漏洞的分析基本上到這裡了,還有一些細節方面的東西沒有寫進來。雖然一些技術點如型別混淆,記憶體布局,位址洩露到現在來說也算是比較傳統,但把這些都串聯起來,然後開啟notsafemode,確實需要相當的功底。可見yuange對於vb的理解之深。感覺自己還是水啊,以後還得多除錯學習。不過只能業餘搞了。
CVE 2010 0188除錯報告
一 tiff檔案格式介紹 1 影象檔案頭 image file header 簡稱ifh ifh資料結構包含 3個成員共計 8個位元組,byte order 成員可能是 mm 0x4d4d 或 ii 0x4949 0x4d4d 表示該tiff 圖是motoral整數格式 0x4949 表示該圖是 i...
CVE 2020 7720漏洞分析
nodejs的乙個軟體包node forge在0.10.0版本以前,其中有乙個util.setpath 函式,存在原型鏈汙染漏洞,攻擊者可以通過構造相應的引數對應用程式執行原型汙染攻擊。官方給出的poc如下 const nodeforge require node forge var obj nod...
IE漏洞除錯之CVE 2013 3893
前言 windows平台的漏洞挖掘和安全研究中,ie始終是繞不開的話題。ie漏洞就跟adobe系列一樣經典,是學習exploit shellcode的絕佳途徑。在ie漏洞中,uaf即use after free是最為經典的一類。uaf可以這樣簡單理解 a先後呼叫b c d三個子函式,b會把a的某個資...