狄仁傑探案之「永恆之藍」
本故事純屬虛構,如有雷同,實屬巧合。
唐武周年間,利用了永恆之藍漏洞(CVE-2017-0144)的WannaCry 蠕蟲爆發。朝野之間,電腦屏幕盡呈一片血色,剛剛寧定不久的武周天下,又面臨一場浩劫。狄仁傑,元芳,狄春三人奉旨研究此漏洞,尋求破解之計。
深夜,狄公交給管家狄春一手稿,命其按此準備。但見手稿上寫道
1) 靶機Win 7 SP1x86 虛擬機一台,無補
2) 攻擊機器一台,虛擬機上安裝NSA的EternalBlue 復現工具,詳參ShadowBroker釋放的NSA工具部分(windows)fb.py復現和中招檢查方法 - FreeBuf.COM | 關注黑客與極客
3) Windbg 遠程調試環境,
4) IDA
不出半個時辰,管家狄春已準備妥當。狄公喚上元芳一同開始查看。
狄公一如既往問道,「元芳,你怎麼看。」
「大人,卑職查看發現,所有感染的電腦 srv!SrvTransaction2DispatchTable的0x0e項均被替換。我們只需順著這個線索往回順藤摸瓜,定能找到真相。」 元芳答道。
狄公讚許的點了點頭,「不錯,一般來說,漏洞分析,第一步我們只需找到控制是如何轉移的。第二步,便是往回順藤摸瓜,看數據是如何被損壞,而導致控制轉移的。」狄公隨即在windbg中敲下了如下命令。
運行fb.py,很快便見windbg斷下在如下地址狄公似乎想到了什麼,緊接著狄仁傑道,「然而這裡並非兇案第一現場,這段代碼應該是shellcode,我們尚需弄清控制是如何轉移到這shellcode的。」
元芳用.writemem命令將這段shellcode dump 了出來,仔細查看。「shellcode入口應該便是這裡。」 元芳指著這段代碼道。
狄仁傑不僅不慢重新啟動調試,敲下如下命令。「可是大人,這地址 –每次調試,不會變化嗎?」 元芳有些疑惑道。狄公笑笑,「那就讓我們來試試運氣吧… …」
「大人你看,真的斷下來了。」 元芳看見斷點真的命中了。
狄公捋了下鬍子,微微一笑,「看來我們的運氣不錯啊」,他凝視了一下屏幕,繼續敲下
狄公道,「棧頂的91a18290 很可能就是轉移到shellcode的call指令的返回地址。」
狄公隨即打開Disassembly窗口
狄公道,「應該就是這條call dword ptr [eax+4] 指令,將控制轉移到了shellcode,元芳你看」元芳道,「大人,這第一步我們算是完成了,我們找到了控制是如何轉移的。如果卑職沒有猜錯的話,ffdff190開始的數據,除了ffdff194,其餘的地址都為0,像是偽造出來的。」狄公點點頭,「我們現在需要做的就是,看看數據是從哪裡來的,以及是如何被損壞的。」
狄公查看了調用堆棧
「是用IDA 分析代碼的時候了。」狄公用 IDA 載入了 srvnet.sys文件,開始靜態分析。約莫一柱香的功夫,狄公緩緩說道,「元芳啊,你看,數據可以追溯回到SrvNetWskReceiveComplete 這個函數。這個函數是個IRP的完成常式。這個函數的第三個參數Context是IRP的Context。而Context 偏移0×24 處,存放了一個指針,裡面存放了連接信息,我們姑且稱其為Connection吧。這個Connection 會被作為第一個參數,傳入SrvNetIndicateData(),而緊接著又會被作為第一個參數傳入到 SrvNetCommonReceiveHandler。也就是說,Contex 由SrvnetAllocateBuffer分配,類型為SRVNET_BUFFFER 定義見下圖
該結構的0×24處的Connection被損壞了,於是便有了我們看到的一幕。你看,在調用SrvNetIndicateData()時,代碼如下而我在查看堆棧發現了於是我可以斷定,
時,edi的值為ffdff020 壓入了棧中。 於是我利用如下斷點,重新調試一下SrvNetWskReceiveComplete+0×14我發現esi,也就是CONTEXT 的地址為0x86acd010, 而其偏移0×24, 也就是地址0x86acd034的地方,被損壞,變成了0x ffdff020。我們不妨再來試試手氣,說不定,這個0x86acd034地址每次也不變呢。」
狄公又重啟了調試,設置如下斷點
斷點再次命中。狄公再次查看堆棧狄公鄒了下眉頭,多年的辦案經驗,讓他想到了問題似乎出在了srv.sys!SrvOs2FeaToNt 函數的memmove上如果往常一樣,他在這個函數上設置了如下斷點,列印出每次調用的參數列印出信息如下兩條引起了狄公的注意利用!pool命令驗算是否越界,第一條,並沒有問題。而第二條
這個memmove調用將向86accff9 開始的0xa8 個位元組里拷貝,即結束地址為86acd0a1。這已經越過了分配的地址 86acd000。元芳見此,立刻說道,「大人我明白了,原來是memmove拷貝越界了導致內存損壞。」
狄公卻擺手示意:「不,目前我們還不能解釋為什麼拷貝會越界。元芳,這個看來就交給你了」。
元芳會意,即刻開始分析並調試SrvOs2FeaToNt 和調用函數SrvOs2FeaListToNt 的代碼。一個多時辰後,元芳突然興奮的說道:「大人,我找道了。」
狄公微微一笑,「不妨說來聽聽。」
元芳道,「是,大人。卑職看來,這段代碼其實是用來將OS/2 的FEA轉化成NT的擴展屬性EA。而問題就出現在SrvOs2FeaListToNt這廝身上,這廝會修改FEALIST的大小。而問題恰恰出現在了這裡。
這裡 v1 存放的是FEALIST 的大小,是個DWORD,本意是根據v3和v1的差值縮小FEALIST的大小。可是這裡卻用了WORD來計算。我調試時發現,
這裡,本來試圖把FEALIST的大小從00010000 縮小到0000ff5d。
然而,用了WORD來計算,
結果反倒變成了 0x1ff5d,一下變大了。
如此一來,下面也都錯了。其實破解之策異常簡單,僅需改成即可。」狄公點點頭,「不錯,元芳,一語中的啊。」
元芳道,「可是卑職尚有一事不明
v1 如果是WORD指針,還尚可理解。 可v1這裡是DWORD指針,這行代碼,轉化成WORD再計算,甚是怪異,莫非作者喝醉了不成?」狄公微微一笑,「問得好啊,我其實也曾有過如此疑問。細細想來,如果作者沒有喝醉,那還有一種可能… …」
「哦,還望大人明示。「 元芳有些不解。
狄公說道,「還有一種可能,便是代碼中可能使用了StoreUnsignedShort 這樣的宏來賦值,這樣一來,錯誤便更加隱蔽而不易被人察覺。」
「原來是這樣!」元芳道,「這下卑職徹底明白了。」
狄公道:「元芳啊,分析漏洞不應放過每個細節。我且問你,「你有沒有想過 0xffdff1f1地址中存放的shellcode是如何拷貝進去的啊?」
「這個。。。」元芳竟然一時語塞,「待卑職調試一下。」
元芳不由大吃一驚,「大人,怎麼會這樣,好象—竟是TCP/IP協議棧拷貝進去的。」狄公微微一笑道:「你恰恰忽略了一點,在memmove拷貝的時候,覆蓋掉的不僅僅是Context->Connection。他同時也覆蓋了相鄰SRVNET_BUFFER.MDL的內容(偏移0x2c起),從而使得TCP/IP協議棧拷貝到了ffdff1f1內存中。在x86上,ffdf1000開始到ffffffff地址,都是保留給HAL用的。你看下下面這張圖便明白了。」
狄公道,「我們可以復命了。」朝堂之上,狄公娓娓道來,整個攻擊攻錯大致是這樣的。首先,歹人發送SMB 的 Session Setup AndX (0×73) 命令,跟據其響應中的 Native OS 獲取目標操作系統的版本信息。有圖為證
緊接著,歹人的計劃緊鑼密鼓的展開。他利用了SMB.SMB_COM_NT_TRANSACT SMB_COM_TRANSACTION2_SECONDARY 在內存中精心布局,形成了一些連續的SRVNET_BUFFER內存區域。然後他關閉了一個鏈接,從而釋放掉一個SRVNET_BUFFER,而這個釋放掉的SRVNET_BUFFER空洞恰恰又會被FeaList 分配內存時重用(有圖為證)。而SrvOs2FeaListToNt 中的Bug又導致了拷貝時越界,直接覆蓋掉了其後的SRVNET_BUFFER,修改了MDL。於是後面的發送的數據就被錯誤的拷貝到了MDL 指定的內存中,也就是HAL保留的內存。而這時,歹人開始了致命的以一擊,發送最後一個SMB_COM_TRANSACTION2_SECONDARY 分片,從而觸發了控制轉移。奏畢,滿朝皆驚。曾泰贊曰,「大人真乃神人也!」退朝後,狄公卻仍是心事重重,元芳便上前問道,「大人似乎還有心事?」
狄公嘆道:「這永恆之藍,猶如浩瀚的大海,深藏著詭譎與恐懼,吞噬著無辜和善良。雖然此案已結,可我始終卻還有種不祥的預感,歹人不會就此罷休,總覺得似乎還有事情發生」。
不出所料,數日後,殿上急召狄仁傑覲見。 狄公緩緩嘆道,「該來的總會來的,不會是Samba服務真的也出問題了吧。」但見一個微胖的身影在暮色中匆匆向大殿走去… …
參考文獻:MS17-010 EternalBlue SMB Remote Windows Kernel Pool CorruptionNSA Eternalblue SMB 漏洞分析Microsoft Windows Windows 7/2008 R2 (x64) - EternalBlue SMB Remote Code Execution (MS17-010)
推薦閱讀:
※對比特幣挖礦木馬分析研究和清除
※攜程新風控數據平台建設
※卡巴斯基發布2018年威脅預測,威脅情報共享成網路安全新趨勢
※淺談DDOS攻擊的應對策略
TAG:网络安全 |