冷眼Wins遠(yuǎn)程溢出漏洞 -電腦資料

電腦資料 時(shí)間:2019-01-01 我要投稿
【clearvueentertainment.com - 電腦資料】

    十一月底,Immunitysec公開(kāi)了一個(gè)WINS的遠(yuǎn)程安全漏洞,入侵者可利用該漏洞完全控制運(yùn)行著WINS服務(wù)的系統(tǒng),

冷眼Wins遠(yuǎn)程溢出漏洞

。其實(shí)這個(gè)漏洞早就被發(fā)現(xiàn)而且在地下流傳已久,不過(guò)是最近才公布而已。就其公布的原因,估計(jì)是因?yàn)檫@個(gè)漏洞有趣,而且造成的影響不是很大吧。漏洞本身的特性決定了這個(gè)漏洞的利用可以有多種路子,讓攻擊者使用不同的方法來(lái)獲得遠(yuǎn)程控制權(quán),也許就是Immunitysec公開(kāi)這個(gè)漏洞的初衷。不過(guò)微軟對(duì)這個(gè)漏洞很敏感,沒(méi)有發(fā)布補(bǔ)丁,因?yàn)檎f(shuō)自己沒(méi)有收到攻擊報(bào)文,所以,本文只是詳細(xì)的分析了整個(gè)漏洞的構(gòu)造、利用,并未給出具體的利用程序和代碼,相信讀過(guò)我們系列文章“菜鳥(niǎo)版Expliot指南”的朋友應(yīng)該都有能力寫上一段自己的代碼吧?

    冷眼Wins遠(yuǎn)程溢出漏洞

    文/圖 馬木留克

    關(guān)于這個(gè)漏洞的描述,比較官方的描述是這樣的:WINS服務(wù)支持一個(gè)稱之為“WINS 復(fù)制”的特性,不同的WINS服務(wù)器可以靠這個(gè)功能交換信息。WINS復(fù)制使用的也是監(jiān)聽(tīng)在TCP 42端口上的標(biāo)準(zhǔn)WINS協(xié)議。在WINS復(fù)制的會(huì)話過(guò)程中,服務(wù)器端會(huì)發(fā)送一個(gè)內(nèi)存指針給客戶端,客戶端用這個(gè)指針進(jìn)行后續(xù)的會(huì)話。如果客戶端在發(fā)送的數(shù)據(jù)中自己修改這個(gè)指針,使之指向用戶控制的數(shù)據(jù),最終就可以向任意地址寫入16個(gè)字節(jié)的數(shù)據(jù),通過(guò)覆蓋特殊地址可以執(zhí)行任意代碼。

    對(duì)于攻擊者而言,了解其中的細(xì)節(jié)非常必要。通過(guò)這一個(gè)描述,大致上我們已經(jīng)可以了解到,這不是一個(gè)典型的堆或者棧上的溢出,而是WINS用我們指定的一個(gè)數(shù)據(jù)作為指針,進(jìn)行了一些操作,最終導(dǎo)致可以寫16個(gè)字節(jié)的數(shù)據(jù)到任意地址——對(duì)于大多數(shù)情況而言,能寫16個(gè)字節(jié)的數(shù)據(jù)就已經(jīng)足夠了,典型的堆溢出甚至只需要寫4個(gè)字節(jié)的數(shù)據(jù),這個(gè)條件還是很寬松的。通過(guò)進(jìn)一步的分析,我們還可以知道,這里的“16個(gè)字節(jié)”是指連續(xù)的16個(gè)字節(jié),更為重要的是,WINS服務(wù)處理異常的機(jī)制非常的強(qiáng)勁,在你提交惡意的代碼造成漏洞利用之后,WINS服務(wù)不會(huì)掛掉,而是繼續(xù)的運(yùn)行,這就意味著我們可以反復(fù)地進(jìn)行“寫連續(xù)的16字節(jié)”。試想一下,我們可以反復(fù)的嘗試直到成功為止,這個(gè)過(guò)程中WINS服務(wù)不會(huì)因?yàn)槲覀兊膼阂夤舳霈F(xiàn)停止的情況。

    在反匯編WINS服務(wù)的守護(hù)進(jìn)程之前,我們可以想象一下各種可能的利用方式。按照Immunitysec的說(shuō)法,惡意用戶提交的數(shù)據(jù)是在堆上的,這就非常類似于遠(yuǎn)程堆溢出,加上可以寫任意值到任意的地址,可以想象,幾乎所有的堆溢出利用方式都可以應(yīng)用到這上面來(lái)。最常用的,寫top seh,然后看能不能通過(guò)寄存器來(lái)定位;其次,我們可以嘗試寫Lookaside表,通過(guò)多次發(fā)包來(lái)強(qiáng)制定位自己的ShellCode地址,然后通過(guò)改寫RtlEnterCriticalSection(0x7ffdf020)等固定的函數(shù)指針來(lái)獲得控制權(quán);再直接一點(diǎn),既然可以多次觸發(fā)而服務(wù)不崩潰,那反復(fù)利用這個(gè)漏洞,直接寫ShellCode到一塊固定的內(nèi)存(比如0x7ffdf222)去,繼而通過(guò)改寫固定的函數(shù)指針來(lái)獲得控制權(quán)也是一條路子。總之,漏洞本身的特性決定了這個(gè)漏洞的利用可以有多種路子,讓攻擊者使用不同的方法來(lái)獲得遠(yuǎn)程控制權(quán),也許就是Immunitysec公開(kāi)這個(gè)漏洞的初衷吧。

    Immunity在公布漏洞的同時(shí),公布了觸發(fā)漏洞的報(bào)文格式,如表1所示:

    報(bào)文長(zhǎng)度(除頭部4字節(jié))

    XX XX FF XX

    四字節(jié)指針(絕對(duì)地址)

    …… …… …… ……

    (表1)

    其中報(bào)文的長(zhǎng)度要小于0x2f87f8。報(bào)文本身沒(méi)有什么其它特殊的要求,滿足上述格式的都可以觸發(fā)漏洞。報(bào)文中的第三個(gè)DOWRD就是一個(gè)我們可以控制的指針,因此,我們可以設(shè)定這個(gè)指針指向我們發(fā)送的報(bào)文本身所在的地方,進(jìn)而控制隨后依據(jù)這個(gè)指針的內(nèi)存讀寫。

    在一臺(tái)Windows 2000 Server SP3 + MS04006補(bǔ)丁的機(jī)器上,反匯編Wins.exe可以得到如下的代碼:

    .text:0101FE34 sub_101FE34    proc near              ; CODE XREF: sub_101FD13+2A p

    .text:0101FE34

    .text:0101FE34 var_84         = dword ptr -84h

    ... ..

    .text:0101FE34 arg_4          = dword ptr 0Ch

    .text:0101FE34 arg_8          = dword ptr 10h

    .text:0101FE34 arg_C          = dword ptr 14h

    ... ...

    .text:0101FE64                mov    ebx, [ebp+arg_4]; 指向提交數(shù)據(jù)的指針

    .text:0101FE67                mov    al, [ebx+2]    ; Flag的第三個(gè)字節(jié)

    .text:0101FE6A                mov    cl, al

    .text:0101FE6C                and    cl, 78h

    .text:0101FE6F                cmp    cl, 78h       ; 和0x78與操作,這里必須跳轉(zhuǎn)

    .text:0101FE72                jz     loc_101FF07

    ... ...(中間三個(gè)跳轉(zhuǎn))

    .text:010200F6                push   eax            ; 可以控制的指針A

    .text:010200F7                lea    ecx, [eax+50h]

    .text:010200FA                push   ecx            ; 指針A + 50h

    .text:010200FB                push   dword ptr [eax+44h]

    .text:010200FE                push   [ebp+arg_8]    ; 數(shù)據(jù)的長(zhǎng)度(報(bào)文頭)

    .text:01020101                push   [ebp+arg_4]    ; 指向提交數(shù)據(jù)的指針

    .text:01020104                call   sub_1020610

    ... ...

    .text:01020638                xor    ebx, ebx       ; ebx置零

    .text:01020640                mov    eax, [ebp+arg_10] ; 指針A

    .text:01020643                cmp    eax, ebx       ; 是否為合法地址(not NULL)

    .text:01020645                jnz    loc_10206CC    ; 合法

    ... ...

    .text:010206CC                mov    ecx, [eax+2Ch] ; 指針A+2C地址的內(nèi)容

    .text:010206CF                mov    [ebp+var_20], ecx

    .text:010206D2                lea    edi, [ecx+48h] ; 拷貝的源地址

    .text:010206D5                mov    esi, [ebp+arg_C]; 目的地址A+44地址的內(nèi)容

    .text:010206D8                movsd              ; 十六字節(jié)的寫操作,源/目的可控

    .text:010206D9                movsd

    .text:010206DA                movsd

    .text:010206DB                movsd

    可以看到提交報(bào)文中第三個(gè)DOWRD指針指向的內(nèi)容最終進(jìn)行了一系列的寫操作,

電腦資料

冷眼Wins遠(yuǎn)程溢出漏洞》(http://clearvueentertainment.com)。如果以Where表示寫操作的目的(esi),What表示寫操作的數(shù)值(edi),簡(jiǎn)化后這個(gè)指針指向如下所示的結(jié)構(gòu)如表2所示:

    where – 48h (lea  edi, [ecx+48h])  offset:0h

    … … … … … … … … … … … …

    what * 4  (4個(gè)DOWRD)        offset:24h

    (表2)

    精心控制發(fā)送報(bào)文中的指針的值,最后可以寫四個(gè)DWORD。我們可以猜測(cè)我們發(fā)送的報(bào)文的大概位置,然后設(shè)定這個(gè)指針,那么,WINS就會(huì)把我們報(bào)文中的數(shù)字寫到報(bào)文中指定的位置去。提交報(bào)文的長(zhǎng)度可以很長(zhǎng)(前面說(shuō)了,只要小于0x2f87f8都是可以的),所以我們猜測(cè)起來(lái)還是比較方便,關(guān)鍵是這個(gè)指針指向的內(nèi)容必須符合一定結(jié)構(gòu)(見(jiàn)上表),一個(gè)比較好的方式是按照如下的結(jié)構(gòu)指定我們發(fā)送報(bào)文中的內(nèi)容(如表3所示)。

    Where – 48h (DWORD) * 9

    What * 4 (4個(gè)DWORD) * 9

    (表3)

    這樣,我們只要大量的填充上述結(jié)構(gòu),就可以提高成功率——只要有一次猜測(cè)的指針指向數(shù)據(jù)塊的位置是Where(連續(xù)九個(gè)為一組)就算成功。內(nèi)存中大量的上述結(jié)構(gòu),加上這里堆分配的一些特性,最差情況下猜37次就可以猜到一個(gè)(連須36次都指針都猜到了What上),這個(gè)成功率還是可以接受的。從測(cè)試的情況來(lái)看,觸發(fā)這個(gè)漏洞后極有可能導(dǎo)致堆內(nèi)存沒(méi)有正確釋放,一個(gè)可能的利用辦法就是先發(fā)送由一個(gè)大量上述結(jié)構(gòu)填充的報(bào)文,設(shè)定指針指向一個(gè)會(huì)造成異常的地址(比如0xffffffff,但不能是0x0,WINS里面判斷過(guò)這種情況),讓這塊內(nèi)存不釋放,然后后面都發(fā)小包來(lái)暴力猜測(cè)地址,從而準(zhǔn)確的控制寫入的源和目的地址。

    好不容易才解決了寫16字節(jié)到任意地址的方式,那么要寫什么東西到哪里去呢?前面說(shuō)過(guò)一些類似于堆利用的方法,可以去試試看,寫出來(lái)的東西通用性應(yīng)該很好,下面嘗試的是另外一種方法。

    要獲得控制權(quán)就要想辦法讓程序執(zhí)行到我們所指定的位置去。一般來(lái)說(shuō)寫一個(gè)程序會(huì)調(diào)用的函數(shù)指針是最好,如果不行的話也可以考慮寫棧上的返回地址。上面的反匯編中,sub_1020610是導(dǎo)致寫16字節(jié)的函數(shù),這個(gè)函數(shù)并沒(méi)有異常,我們可以考慮在這個(gè)地方先下一個(gè)斷點(diǎn),繼續(xù)跟蹤一直到有Ret的出現(xiàn)。Ret的意義在于把棧頂?shù)臄?shù)據(jù)作為返回值,也就是[ESP]->EIP,我們要是能夠找準(zhǔn)當(dāng)時(shí)棧頂?shù)奈恢萌缓蟾采w掉,就可以準(zhǔn)確地控制程序的流向。

    那么,讓程序流向何處呢?當(dāng)然是我們的ShellCode。我們的ShellCode可以隨報(bào)文一塊兒送過(guò)去,所以在堆上一定能找到一份拷貝。報(bào)文已經(jīng)有了大量的如表3所定義的結(jié)構(gòu),然后在報(bào)文的最后寫入ShellCode,中間可用大量的NOPs來(lái)填充。在猜指針的時(shí)候我們就大致的猜到了堆所在的地址,所以根據(jù)猜測(cè)的地址來(lái)定位ShellCode也是可以的。這樣子,把堆上ShellCode的地址寫到棧上函數(shù)的返回地址就可以獲得控制權(quán)了。這一步可能也需要暴力猜解,因?yàn)闂I系姆祷氐刂房赡懿⒉淮_定。

    在測(cè)試的過(guò)程中,我們發(fā)現(xiàn)棧上返回地址的位置幾乎是固定的,都是0x53df4c4,在對(duì)近70臺(tái)機(jī)器的測(cè)試中,約有半數(shù)以上這個(gè)地址都是有效的。所以如果不打算寫復(fù)雜的程序暴力猜測(cè),這個(gè)地址就足夠了。測(cè)試中涉及到了中文版幾乎所有SP和MS04006補(bǔ)丁的情況,可見(jiàn)這個(gè)還是有一定的通用性的。倘若只是玩票性質(zhì)的寫寫EXP,可以直接設(shè)置Where的值為0x53df4c4 – 48h。

    同樣的,在上述的測(cè)試過(guò)程中,我們發(fā)現(xiàn)第一個(gè)發(fā)送過(guò)去的報(bào)文總是拷貝到一個(gè)固定的位置,如果用表三所示的數(shù)據(jù)結(jié)構(gòu)來(lái)填充報(bào)文,那么這個(gè)數(shù)據(jù)結(jié)構(gòu)第一次出現(xiàn)的位置幾乎都固定在0x05391eac。這個(gè)幾率大概是八成左右,偶爾的失敗情況不詳,但是有一點(diǎn)可以肯定的是,如果你造成了異常而導(dǎo)致堆沒(méi)有被正確釋放,那么后續(xù)報(bào)文被拷貝到的地址肯定在這之后。

    有了上述兩個(gè)地址,要寫一個(gè)成功率一般的利用程序已經(jīng)不難,按照上面的報(bào)文格式,設(shè)定四字節(jié)的指針為0x05391eac,然后填充一個(gè)圖三所示的結(jié)構(gòu),里面Where都填充為固定的棧上的函數(shù)返回地址0x53df4c4 – 48h,所有的What都填上我們猜測(cè)的一個(gè)大概的ShellCode的位置(比如0x05392000),接下來(lái)填充大約0x200個(gè)NOPs也就是0x90,然后加上一個(gè)任意的ShellCode,把這個(gè)報(bào)文發(fā)送到目標(biāo)主機(jī)的TCP 42口,就有很大的可能性獲得對(duì)方的控制權(quán)了。如果你的ShellCode不是以ExitProcess(0)結(jié)束的,那么你還可以反復(fù)的利用這個(gè)漏洞來(lái)獲得控制權(quán),只是每次的結(jié)果用的都是第一次發(fā)送的ShellCode——堆內(nèi)存沒(méi)有被釋放而且我們猜測(cè)的是第一次發(fā)送的地址,如果你用的是Bind port的,那還好,如果是Reverse過(guò)來(lái)的那就麻煩了,別人要是搶先一步,用這種方法就算成功了你也沒(méi)有機(jī)會(huì)的。

    至于其它的利用方式,說(shuō)實(shí)話寫RtlEnterCriticalSection不太穩(wěn)定,暴力猜解可是可以,還是麻煩了一點(diǎn),不知道有沒(méi)有其他的利用方式。表面上看起來(lái)難以利用的漏洞公布出來(lái),沒(méi)有0day的利用方法怎么也說(shuō)不過(guò)去,只有看看以后是否有好的方法公布出來(lái)了。

    關(guān)于這個(gè)漏洞的危害,報(bào)告也說(shuō)明了,理論上來(lái)說(shuō)對(duì)于所有開(kāi)放了WINS服務(wù)(簡(jiǎn)單的用TCP端口42來(lái)判斷)的Windows NT、Windows 2000、Windows 2003都有危險(xiǎn),在這個(gè)補(bǔ)丁沒(méi)有出來(lái)的時(shí)候,最好還是把WINS服務(wù)關(guān)掉,或者用防火墻一類濾掉所有指向TCP42的報(bào)文。也就是因?yàn)槁┒礇](méi)有出補(bǔ)丁就公開(kāi)了這件事情,據(jù)說(shuō)微軟搞得很惱火(微軟12月1日?qǐng)?bào)告稱沒(méi)有收到受此漏洞攻擊的報(bào)告,這簡(jiǎn)直是笑話,EXP是很容易寫的,至少可以弄個(gè)不怎么通用的出來(lái),我才不相信沒(méi)有受到攻擊,最多是沒(méi)有報(bào)告罷了),頂著風(fēng)頭外面誰(shuí)也不敢給出利用程序來(lái)。同樣的,老獨(dú)物WTF雖然也很期盼,但估計(jì)沒(méi)這個(gè)膽把利用程序放到光盤里面去,大家要爽估計(jì)只有等到微軟出了補(bǔ)丁后再放出利用程序來(lái)了,據(jù)說(shuō)一月份就會(huì)出補(bǔ)丁,那么最快二月份可能就可以得到EXP。至于稍微懂行一點(diǎn)的朋友,想必都已經(jīng)寫出來(lái)了,有興趣的的朋友也可以按照上面說(shuō)的方法來(lái)寫一個(gè)出來(lái),我已經(jīng)說(shuō)得很清楚很明顯了,不是么?

最新文章