<sub id="dfg0s"></sub><wbr id="dfg0s"></wbr>
<sub id="dfg0s"><listing id="dfg0s"></listing></sub>
<sub id="dfg0s"></sub>
<dd id="dfg0s"><address id="dfg0s"></address></dd>
  • <sub id="dfg0s"><table id="dfg0s"></table></sub>

    <nav id="dfg0s"></nav>

    CVE-2018-8897 調試分析

    1526884676b73bad.png

    漏洞說明

    系統內核通過Mov到SS(stack segment)或Pop到SS指令進行堆棧切換操作后處理異常情況時發現了一個缺陷.在堆棧切換操作期間,處理器沒有傳送中斷和異常,而是在堆棧切換后面的第一條指令執行完傳送.一個沒有特權的系統用戶可以利用這個漏洞來破壞系統內核,導致拒絕服務.實際上MOV到SS會延遲一些調試異常(例如一個硬件斷點)直到下條指令完成;如果跟隨MOV到SS或者POP到SS后面的指令是SYSCALL 、SYSENTER、INT 3之類的指令,調試異常被捕獲之后將轉移到Ring0執行.

    樣本環境

    首先從https://github.com/can1357/CVE-2018-8897下載POC源代碼,用vs2015新建立一個win32控制臺工程;POC里面有個64位匯編的asm文件,使用VC++自帶的匯編編譯器編譯Native.asm 為一個obj文件[ml64.exe/FlNative /c /Zi Native.asm],再把obj添加到工程里面[右擊工程名字,點擊屬性;點擊配置屬性→鏈接器→輸入→附加依賴項;輸入obj名字],然后編譯得到一個POC,編譯POC一步算完了.

    樣本是Win7x64位的,接下來搭建一個Win7x64的VMWar環境,運行poc.exe嘗試觸發一次,POC顯示失敗了.

    POC失敗問題先暫停.關于WinDBG的內核調試,WinDBG與VMWare雙機內核調試工具的配置請使用VirtualKD.如何安裝使用請自行搜索.

    1526885152b72a5a.jpg

    修復樣本

    回看一下上面的問題,樣本為什么會失敗?看下前面錯誤提示之前的代碼,這段代碼與KeBugCheckEx與PsGetCurrentProcess函數有關.

    在IDA中打開目標系統的ntoskrnl.exe文件,看KeBugCheckEx的匯編代碼,代碼應該搜尋0x53E0這個偏移,gs:20h是一_KPRCB結構的變量_KPCR→CurrentPrcb,這些結構一般是公開的,利用搜索引擎很容易獲得.0x53EO偏移處保存的一個CONTEXT結構,也就是Prcb.Context.

    1526885180c96c08.png

    PsGetCurrentProcess的匯編代碼,代碼應該是搜尋0x70值.GS寄存器等于32位系統FS寄存器,其實這里指向內核結構_KPCR結構.0x188的偏移位置是_KTHREAD結構,0x70的偏移位置是_KTHREAD結構,也就是KThread.ApcStateFill.Process

    15268851879425be.png

    1526885207437d46.png

    PsGetCurrentProcess函數的有關實現.

    1526885224edfbe1.png
    現在說下修復方法,找到自己系統上這兩個函數數據結構的偏移,如果發現沒有這兩個數據結構的偏移,那么請找一個函數修復這個偏移.測試系統上Prcb.Context對應不上,需要修復偏移.
    8.png

    打開WinDBG進行雙機內核調試,輸入命令dt _KPRCB查找_CONTEXT的偏移地址,測試系統偏移為0x4bd8.

    1526885236243fac.png

    修改POC里面的偏移地址,然后運行POC測試

    1526885243749cf0.png

    在vmware里面運行到漏洞觸發那里還是崩潰了?為什么呢?原因是讀取GS的基址失敗了.原因很有可能就是vmware不支持rdgsbase之類的指令,嘗試了二進制翻譯功能,仍然提示錯誤.怎么解決呢?請看下面.

    如果本機打了補丁的請卸載名字為KB4103712 與KB4103718的補丁,卸載補丁后再次運行.運行結果是直接重啟.WHAT?說明已經觸發了漏洞,但是例如ROP與Shellcode之類的可能還需要修復.先看一下攻擊過程.

    攻擊過程

    源碼中首先檢測內核頁表隔離(KPTI,kernel page table isolation, Windows內核中又叫KvaShadow)是否被啟用,這好像與一個INTEL漏洞相關.

    1526885267037a59.png

    使用VirtualLock函數把兩個函數的代碼鎖定在物理頁面,供內核使用.

    1526885274197f76.png

    得到內核基址并加載(LoadLibrary)內核ntoskrnl.exe到自身進程.

    15268852939a0ee0.png

    分配4個內核對象(_KPCR,_KTHREAD,_KPROCESS,_KPRCB)供內核使用.

    15268853201e0fee.png

    內核結構_KPCR的偏移0x180處是_KPRCB結構.

    15268853313941c4.png

    解析內核模塊,查找一些用于ROP技術的小組件.

    1526885337f40ee6.png

    找到內核結構_KPRCB成員Context的偏移地址,找到進程_EPROCESS的偏移地址.前面講過,不重復講.

    填充_KPCR,_KPRCB,_KTHREAD結構體,相關成員的偏移地址在不同的系統可能會一樣,請自己修復.

    15268853521ff1de.png

    讀取堆棧段寄存器保存到變量SavedSS.

    1526885360a440a3.png

    創建一個線程,獲得填充_KPRCB對象的成員_CONTEXT的偏移地址,并等待RtlCaptureContext函數調用獲得泄漏的RSP,漏洞觸發前會一直等待,實際上異常才會進入這個函數.等待第二次RtlCaptureContext被調是計算兩次RSP的差異值來預測下一次RSP的值,并預測返回指針的位置,并建立RtlCaptureContext需要的上下文.第一條ROP的RETN位置放在XMM13寄存器.

    設置輔助線程的優先級為最高并分離當前線程與創建的輔助線程,讓它們在不同的CPU上執行,接著獲取了一些內核函數的地址.

    1526885441041574.png

    給線程設置兩個異常,一個在SS段寄存器為讀寫異常,另一個寫異常位于結構_KPRCB→ProcessorState(_KPROCESSOR_STATE)→SpecialRegisters(_KSPECIAL_REGISTERS)→Cr8.

    WinDBG輸入u KeBugCheckEx,紅色部分,如果偏移不一樣則需要修復這個結構.

    開始填充rop到XMM寄存器.

    最后讀取gs段寄存器基址,重設基址指向自己填充的_KPCR結構,然后觸發漏洞,恢復GS段寄存器,并使用SS段寄存器去觸發漏洞.

    先使用mov ss指令切換堆棧,并且會產生前面的ss調試異常,但mov ss切換后不會立即發送異常要等下一條指令執行完成后才發送;緊接著是一個int 3指令,由于前面會改變了gs段寄存器的基址,進入內核之后要使用SWAPGS指令交換gs段寄存器.

    可能需要修復的一些數據偏移,根據不同的系統偏移不同.

    小結

    由于無法使用WinDBG對本機進行內核調試驗證,修復POC里面的數據偏移,如果數據偏移沒有修改正確就測試POC,可能會造成系統重啟.快點自己動手試下吧.

    標簽: 漏洞分析

    作者:pig 來源:黑客視界 瀏覽量:5182 時間: 2018-05-21

    加入墨者學院可立即獲得20墨幣

    可免費開啟靶場環境

    點擊注冊領取

    已有賬號,立即登錄

    你是不是好久没有被C了_少妇找技师做性按摩视频在线观看_午夜福利电影_777766香港开奖结果 7777