您好,登錄后才能下訂單哦!
如何進行Buhtrap CVE-2019-1132攻擊事件相關漏洞樣本分析,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
2019年7月10日,在微軟7月補丁發放的第一天,eset發布文章“windows-zero-day-cve-2019-1132-exploit”披露了APT團伙buhtrap使用windows 0day CVE-2019-1132進行攻擊的一次在野活動,之后SHIVAM TRIVEDI于7月25對外放出了該漏洞相關的exp利用,本文針對該漏洞及buhtrap攻擊使用的樣本進行分析,以便于大眾了解buhtrap這個在國內鮮為人知的APT團伙。
Buhtrap是一個常年針對俄羅斯金融企業相關的攻擊團伙,其2014年就開始了相關的活動,而這也是buhtrap的第一次0day攻擊活動,但是實際上早在2016年3月GROUP IB就針對buhtrap發布了文章“BUTHRAP The evolution of targeted attacks against financial institutions”,如下圖所示就是GROUP IB總結的Buhtrap在2014年,2015年兩年內的戰績。
該部分使用SHIVAM TRIVEDI分享的相關exp代碼,感謝SHIVAM TRIVEDI的分享。
編譯對應exp,運行之后效果如下所示,獲得了一個管理員權限的shell。
利用代碼的主函數中一開始創建了三個menu菜單,并通過AppendMenuA創建對應下拉子菜單,然后創建兩個窗口,一個為主窗口,一個用于輔助后續利用的hunt窗口。
之后分別設置消息hook和事件hook函數。
在消息hook回調函數中監控對應的WM_NCCREATE消息,當監控到對應的消息時,通過SendMessage針對指定的menu發送MN_CANCELMENUS消息,該消息會取消對應的菜單。
在事件hook回調函數中,首先保存所有觸發菜單的hwnd到hwndMenuList中,并發送MN_OPENHIERARCHY消息,該消息將導致打開對應的子菜單。
之后對第一個hMenuList[0]菜單調用函數TrackPopupMenuEx,用于彈出顯示該菜單,調用完成之后將導致hMenuList[0]子菜單hMenuList[1]的ppopupmenuRoot被設置為null,之后設置0地址,將偏移0x1c的位置設置為hunt窗口的內核地址+0x12,hunt窗口的內核地址通過xxHMValidateHandle的方式獲取,該內核地址泄露的方式在win10 rs4之后被微軟修復。
這里一個最大的疑問就在于為什么TrackPopupMenuEx函數執行之后,對應的hMenuList[1]中的ppopupmenuRoot會被設置為null。
在解決這個問題前,我們需要對windows中的菜單對象有所了解,其中涉及到的內容主要包括:菜單對象,菜單層疊窗口對象和彈出菜單對象,菜單狀態對象(以下幾個菜單相關對象主要來自于小刀子同學之前的文章,文章對菜單對象分析得很詳細,感興趣的同學可以看看,見參考鏈接2)
菜單對象:菜單對象是菜單的實體,在內核中以結構體tagMENU的形式存在,用于描述菜單實體的菜單項,項數,大小等靜態信息,但本身并不負責菜單在屏幕中的顯示,通過用戶調用CreateMenu函數時在內核中創建,通過函數DsetroyMenu調用或進程結束時銷毀。
菜單層疊窗口對象(以下簡稱菜單窗口對象):菜單窗口對象是窗口結構體tagWND對象的特殊類型,當需要在屏幕中的顯示某個菜單時,如通過窗口區域右鍵鼠標,內核中將調用相關的服務函數根據目標菜單對象創建對應類型為MENUCLASS的菜單窗口對象,其主要負責描述菜單在屏幕中的顯示位置,樣式等動態信息,其擴展區域關聯對應的彈出菜單對象。
彈出菜單對象:彈出菜單對象為菜單窗口對象的擴展對象,用來描述其所代表的菜單的彈出狀態,以及菜單窗口對象,菜單對象,子菜單或父菜單的菜單窗口對象等用戶對象的相互關系。
當某個菜單在屏幕中彈出,菜單窗口對象和關聯的彈出菜單對象被創建,
菜單狀態對象:該結構體用來存儲和當前活躍菜單狀態相關的詳細信息,包括上下文菜單彈出坐標,關聯的位圖表面對象的指針,窗口設備上下文對象,之前的上下文菜單結構體的指針,及其他一些成員域。
菜單窗口對象實際是tagWND對象的特殊類型,其中比較重要的是偏移0x14處的bServerSideWindowProc,該字段用于標記對應的窗口對象是否在內核態執行,如果能修改該標記位,即能實現讓我們的窗口對應的回調處于內核態的執行權限,從而實現提權(類似的提取方式在CVE-2019-0808,CVE-2017-0263種都被使用),其偏移0xB0的位置為WndExtra Data Section,在這里指向了對應關聯的彈出菜單對象。
彈出菜單對象如下所示,其中偏移0x20ppopupmenuRoot標記了第一個彈出菜單對象,如第一個菜單對象的ppopupmenuRoot就是自身,這也是漏洞中被設置為null的位置。
偏移0x24的位置為ppmDelayedFree,該成員域用來將所有被標記為延遲釋放狀態的彈出菜單對象連接起來,以便在菜單的彈出狀態終止時將所有彈出菜單對象統一銷毀,根彈出菜單對象的ppmDelayedFree作為鏈表的入口,即第一個節點。
菜單狀態對象偏移0處的pGlobalPopupMenu指向對應的彈出菜單對象。
如下圖所示漏洞代碼中第一個菜單的彈出菜單對象如下所示,該彈出菜單對象的地址為0xfd78d628,其ppopupmenuRoot指向向了自身,同樣為0xfd78d628.
第二個菜單對象關聯的彈出菜單對象為0xfd6f3a68,其ppopupmenuRoot就指向了第一個菜單的彈出菜單對象。
漏洞利用中通過函數來TrackPopupMenuEx彈出hMenuList[0]菜單,TrackPopupMenuEx在內核中通過xxxTrackPopupMenuEx實現,xxxTrackPopupMenuEx首先通過xxxCreateWindowEx創建對應的菜單窗口對象tagMENUWND[0]。其中彈出菜單對象也會伴隨著一起生成。xxxCreateWindowEx中會發送對應的WM_NCCREATE,并被我們的hook回調捕獲。
xxxCreateWindowEx之后,通過菜單窗口對象獲取對應的彈出菜單對象,在偏移0xB0的位置,并設置對應的彈出菜單對象中的值,如下圖中就設置該彈出菜單對象的ppopupmenuRoot,之后通過xxxMNAllocMenuState創建對一個對應的菜單狀態對象。
xxxMNAllocMenuState中將彈出菜單對象設置到菜單狀態對象偏移為0x0的位置。
之后xxxWindowEvent(6, v51, -4, 0, 0);發送事件EVENT_SYSTEM_MENUPOPUPSTART,該事件會被我們的事件hook捕獲。
這里需要注意xxxWindowEvent發送事件EVENT_SYSTEM_MENUPOPUPSTART之后才進入到
xxxMNLoop函數中,該函數可以理解會對應菜單的消息循環處理函數,因此之后我們在菜單窗口對象創建時發送的WM_NCCREATE被應用層hook捕獲時,應用層發送的MN_CANCELMENUS還沒有被處理,其會在xxxMNLoop中被處理。當所有菜單消息處理之后,xxxMNLoop結束才會運行之后的xxxUnlockMenuState。
前面提到當菜單窗口對象創建的時候,會發送對WM_NCCREATE,并被我們的hook回調捕獲,在回調中判斷對應的消息是否為WM_NCCREATE,并確保hMenuList[0]菜單生成,且hMenuList[1]菜單沒有生產,如果條件滿足,則向hMenuList[0]菜單發送MN_CANCELMENUS,這里的bEnterEvent變量需要在第一個事件回調函數中才會被設置為true,因為當事件回調觸發時才表明xxxWindowEvent發送事件EVENT_SYSTEM_MENUPOPUPSTART,對應的菜單窗口對應已經創建。
該消息最終通過win32k!xxxMenuWindowProc派發給hMenuList[0]菜單,其在內核中通過xxxRealMenuWindowProc派發到xxxMNCancel處理
xxxMNCancel函數首先設置hMenuList[0]的彈出菜單對象fDestroyed字段,并調用函數xxxMNCloseHierarchy。
函數xxxMNCloseHierarchy中首先判斷fHierarchyDropped的值,該字段標記當前菜單對象已彈出子菜單,由于我們xxxMNCancel時對應的子菜單hMenuList[1]還沒有創建,從而確保對應的這個字段的判斷并不成立,從而直接跳過判斷,如果在判斷成立的情況下將會獲取hMenuList[0]對應彈出菜單對象偏移0x1c處的spwndNextPopup,該變量指向下一個彈出菜單對象(如果hMenuList[1]創建的話就是hMenuList[1]的彈出菜單對象,但是這里沒有),并發送MN_CLOSEHIERARCHY消息,而我們這里直接跳過了。
xxxTrackPopupMenuEx尾部通過xxxWindowEvent(6, v51, -4, 0, 0);發送了事件EVENT_SYSTEM_MENUPOPUPSTART,這將被我們的事件hook回調捕獲。
在事件回調中我們向hMenuList[0]發送MN_SELECTITEM,MN_SELECTFIRSTVALIDITEMMN_OPENHIERARCHY消息,MN_SELECTITEM,MN_SELECTFIRSTVALIDITEM會導致最終選中hMenuList[0]的下一個菜單hMenuList[1],之后通過MN_OPENHIERARCHY將打開對應的菜單窗口,即hMenuList[1]。
MN_OPENHIERARCHY消息在內核中最終通過xxxRealMenuWindowProc派發給函數
xxxMNOpenHierarchy。
xxxMNOpenHierarchy同樣通過xxxCreateWindowEx創建hMenuList[1]的菜單窗口對象。
獲取hMenuList[1]的彈出菜單對象,并設置相關字段,這里需要注意的是該彈出菜單對象被設置到對應ppopupmenuRoot的彈出菜單對象的ppmDelayedFree鏈表中,而這里ppopupmenuRoot就是hMenuList[0]的彈出菜單對象,也就是對應的hMenuList[0]的彈出菜單對象的ppmDelayedFree的第一個節點指向了hMenuList[1]的彈出菜單對象
之后調用函數HMAssignmentLock
此時第一次針對hMenuList[0]的xxxTrackPopupMenuEx函數執行到尾部的xxxUnlockMenuState,其參數為對應的hMenuList[0]的菜單狀態結構,菜單狀態結構偏移0x0的位置指向了hMenuList[0]的彈出菜單對象。
xxxUnlockMenuState經過一系列調用,最終執行到MNFlushDestroyedPopups,MNFlushDestroyedPopups中通過傳入的hMenuList[0]的彈出菜單對象獲取對應的ppmDelayedFree鏈表,并循環遍歷,如上所述該鏈表中保存了對應的子菜單的彈出菜單對象,之后判斷遍歷的彈出菜單對象fDestroyed是否設置(這里ppmDelayedFree鏈表的第一個節點就是hMenuList[1]的彈出菜單對象),這里需要注意的是由于我們之前在xxxMNCancel函數時,xxxMNCloseHierarchy中處理hMenuList[0]時,由于對應的fHierarchyDropped字段沒有設置,當時hMenuList[1]子菜單還沒有創建,因此跳過了其中的if語句,因此沒有向對應的子菜單發送MN_CLOSEHIERARCHY,因此我們的hMenuList[1]彈出菜單對象fDestroyed是沒有設置的,因此并沒有執行下圖中的if語句,而是進入了else if,在其中直接將對應的popumenuroot設置為了null,從而導致hMenuList[1]菜單的彈出菜單對象中的popumenuroot為空。
此時當我們通過hMenuList[1]調用TrackPopupMenuEx時,最終同樣會進入到xxxMNOpenHierarchy,過程和第一次一致。
xxxMNOpenHierarchy中最后調用到函數HMAssignmentLock,此時第一個參數會獲取hMenuList[1]彈出菜單對象的ppopupmenuRoot,由于之前第一次TrackPopupMenuEx調用已經將hMenuList[1]彈出菜單對象的ppopupmenuRoot設置為null,因此這里傳入的值其實為0x1c的值,因此上述代碼中通過設置null地址將0x1c的位置設置為hunt窗口對象偏移加0x12的位置,注意這里并不是直接設置為對應bServerSideWindowProc的偏移0x18,是因為后續利用處還有一個+4的操作。
如下所示傳入的0x1c處的值最終被函數HMUnlockObject使用,使其+4并進行dec的操作,將導致bServerSideWindowProc位設置
一旦hunt窗口的bServerSideWindowProc被設置,此時我們相當于使用內核態執行對應的應用層hunt回調,在對應回調中執行shellcode,來替換對應的進程令牌,實現權限提升。
整個過程如下所示,簡單來說就是在根菜單xxxTrackPopupMenuEx調用時,通過hook,在根菜單生成,子菜單未生成時的WM_NCCREATE消息中取消根菜單,之后在xxxTrackPopupMenuEx發送EVENT_SYSTEM_MENUPOPUPSTART事件時,通過hook 發送消息MN_SELECTITEM MN_SELECTFIRSTVALIDITEMMN_OPENHIERARCHY,迫使根菜單彈出子菜單,導致xxxMNOpenHierarchy調用,生成子菜單的彈出菜單對象,并鏈入到對應的根菜單的ppmDelayedFree鏈表中。根菜單xxxTrackPopupMenuEx最后調用xxxMNEndMenuState,遍歷ppmDelayedFree,由于取消根菜單時,子菜單沒有創建,對應的fDestroyed沒有設置,最終只是將子菜單的彈出菜單對象的ppopupmenuRoot字段設置為null,從而導致之后的null地址利用。
這里一個需要注意的就是第一次hMenuList[0]菜單對象調用TrackPopupMenuEx時,我們在hook消息和事件的過程中幾個重要消息的先后順序:
1.xxxCreateWindowEx調用創建菜單窗口對象,發送WM_NCCREATE到應用層,被我們的消息回調捕獲,回調中向hMenuList[0]菜單對象發送MN_CANCELMENUS消息。
2.xxxWindowEvent(6, v51, -4, 0, 0)發送EVENT_SYSTEM_MENUPOPUPSTART事件,被我們的事件回調捕獲,回調中向hMenuList[0]菜單對象發送
MN_SELECTITEM/MN_SELECTFIRSTVALIDITEM/MN_OPENHIERARCHY
3.hMenuList[0]菜單對象xxxMNLoop消息循環啟動,以此處理收到的消息,首先是MN_CANCELMENUS,導致hMenuList[0]菜單對象取消,之后
MN_SELECTITEM/MN_SELECTFIRSTVALIDITEM/MN_OPENHIERARCHY導致針對hMenuList[1]處理消息MN_OPENHIERARCHY
4.hMenuList[0]菜單對象取消后導致xxxMNLoop處理完消息后結束,執行xxxUnlockMenuState,最終hMenuList[1]彈出菜單對象ppopupmenuRoot被設置為null。
如下所示hMenuList[0]調用xxxTrackPopupMenuEx,對應的tagPOPOUPMENU彈出窗口對象為0xfe7034a8,此時fDesktroyed沒有被設置。
WM_NCCREATE被應用層hook代碼捕獲,并對該菜單發送了MN_CANCELMENUS,導致進入xxxMNCancel
xxxMNCancel之前,對應的hMenuList[0]tagPOPOUPMENU fDestroyed字段。
執行之后,hMenuList[0]tagPOPOUPMENU fDestroyed字段被設置。
xxxTrackPopupMenuEx繼續執行,xxxWindowEvent(6, v51, -4, 0, 0)發送EVENT_SYSTEM_MENUPOPUPSTART事件,被我們設置的事件hook捕獲,并針對hMenuList[0]菜單發送MN_OPENHIERARCHY,進入函數xxxMNOpenHierarchy,在xxxMNOpenHierarchy中創建hMenuList[1]對應的tagMENUWND/tagPOPUPMENU。
hMenuList[1] 的tagPOPUPMENU如下所示
hMenuList[1]的tagPOPUPMENUppopupmenuRoot 字段首先被設置為hMenuList[0] tagPOPUPMENU,同時hMenuList[1]tagPOPUPMENU被鏈入到hMenuList[0]tagPOPUPMENU的ppmDelayedFree中。
xxxTrackPopupMenuEx繼續向下執行,xxxUnlockMenuState中,hMenuList[0] tagMENUWND遍歷ppmDelayedFree,ppmDelayedFree保存了hMenuList[1] tagPOPUPMENU,由于對應的fDestroyed沒有設置,因此直接將hMenuList[1] tagPOPUPMENU的ppopupmenuRoot置null。
對應的函數調用如下所示
之后通過hMenuList[1]調用xxxTrackPopupMenuEx,最終在函數HMAssignmentLock中,如下所示hMenuList[1]tagPOPUPMENU的ppopupmenuRoot字段為0,最終會將0x1c處的值作為第一個參數傳入
而0x1c處的值被我們設置為了hunt窗口對象+0x12的位置,我們的目標是最終設置bServerSideWindowProc的值
最終進入函數HMUnlockObject,可以看到第一個參數就是我在0x1c位置布置的hunt tagWnd+0x12.
此時將tagWnd+0x12的地址+4,并將地址中對應的值減一,這將導致0x18處的bServerSideWindowProc值被設置。
減一之后。
可以看到此時hunt tagWnd對象的bServerSideWindowProc字段已經被設置。
此時向hunt窗口發送指定消息,觸發shellcode執行并替換進程令牌以實現越權。
這里有一個疑問,就是如果使用我之前的老版本的win7測試,發現漏洞并不能觸發,看了下代碼發現老版本的win32k.sys驅動中的xxxTrackPopupMenuEx函數中,并沒有調用xxxUnlockMenuState導致。
可以看到對應的tagPOPUPMENU并沒有設置為null。
但是這并不是意味著老版本的win32k中沒有xxxUnlockMenuState,實際上只是在xxxTrackPopupMenuEx中沒有調用而已.
微軟的補丁修改中直接將xxxMNOpenHierarchy中HMAssignmentLock觸發函數前設置了null監控,防止傳入對應null地址。
Eset在其文章中給出兩個該組織投遞的惡意樣本,具體的md5如下,雖然這兩個攻擊樣本都不是0day事件中使用的樣本,但是eset的文章中提到攻擊中使用的手法是一致的,因此從這些樣本中我們能看看這個團伙在攻擊中使用樣本的一些特點。
b54b618a9a6abd879e6703a9a4a53e94
f36fe1716c9e38fa39186b63339ebee6
b54b618a9a6abd879e6703a9a4a53e94
該樣本打開之后如下所示:
點擊確認宏運行之后,真正的載荷如下所示
可以看到是企業合同相關的內容。
Vbs惡意代碼會將對應的惡意exe及實際誘餌文檔拷貝到office目錄下,如下圖所示誘餌文檔為myfile.rtf。
對應的惡意exe偽裝為putty程序。
實際的誘餌和惡意exe是寫到控件中的。
如下所示,釋放到office目錄下的誘餌和惡意exe。
該putty實際上是通過nsis打包的安裝文件,通過7zip打開如下所示:
$0:實際的惡意代碼
$PLUGINSIDR:輔助nsis腳本的插件,實際就是一個寫好的dll
[NSIS].nsi:具體的nsis腳本
可以看到nsis是windows下安裝程序的制作程序,需要注意的是nsis中是通過腳本語言來描述安裝程序的行為和邏輯的,這就給了攻擊者很大的操作空間,我們可以在第二個樣本中看到。
該樣本的nsis腳本很簡單,一開始通過HideWindow字段標記該次安裝為隱藏安裝,之后調用fun_3,fun_3將壓縮包中$0目錄下的文件釋放到指定目錄,通過插件CreateMutex創建互斥量38A81F7C-266A-4509-82E2-34C6E0956EF7,最后調用fun_0.
fun_0中將avz.exe設置開機啟動,并運行。
釋放的惡意代碼目錄如下:
Avz.exe:該文件是一個白文件,通過其加載對應update.dll及winspool.drv文件
Update.dll:該文件是一個密碼竊取工具,主要用于竊取受害者機器上瀏覽器,郵箱等憑據
Winspool.drv:一個buhtrap常用的后門
Winspool.drv
Winspool.drv是一個dll,由avz.exe加載,對應的入口如下所示:
樣本中使用的字符串都通過加密算法加密,一共使用了三種加密手段,且每個字符使用不同的密鑰,調用時的堆棧也有所區別,以增加安全人員的分析成本。
主函數中的fun_HooksysApi用于hook系統api showwindow/createwinodwex/shell_notifyicona,如下所示fun_Hookapi函數中依次傳入hook目標api地址,用于保存hook api頭部內容的內存地址,hook回調函數。
fun_Hookapi中首先保存了目標api的前幾個字節的內容。通過VirtualProtect修改目標api內存頁屬性,寫入對應的jmp hook指令,最后VirtualProtect再次調用,以恢復之前的內存頁屬性。
fun_StoretheOriginaddress中直接通過memcpy的方式保存hook 目標api前幾個字節的內容。
如下所示CreateWindowEx的hook效果如下:
但是看過對應的hook回調函數,就會發現實際上這個樣本中的hook沒有作用,如下所示,hook回調的任務就是將執行流又傳遞給系統api,因此這里猜測這個hook api的功能目前應該還只是測試階段,而攻擊者應該是希望通過hook api的方式來轉移樣本的執行流程,類似銀行木馬icedid的操作。
對應的主線程中的代碼如下所示,一共再次啟動了三個線程其中
線程一:主線程
線程二:鍵盤記錄
線程三:類似守護線程。
fun_Connectcc中解密出對應的cc
主線程函數如下所示:
fun_ForsmartCard中用于讀取和電腦設備連接的smart card信息
和cc連接,并下載對應的payload,payload猜測有包含后續smartcad dump相關的內容。
加載后續的payload,支持exe和dll。
線程二創建了一個窗口,被設定了對應的窗口回調。
窗口回調中通過GetRawInputData的方式實現鍵盤記錄
需要注意的是該鍵盤記錄只記錄指定的進程,如下所示
線程三中監控系統中是否存在互斥量38A81F7C-266A-4509-82E2-34C6E0956EF7,該互斥量由一開始的nsis腳本創建。
加載模塊update.dll。
Update.dll
Update.dll相關的竊取目標如下所示:
f36fe1716c9e38fa39186b63339ebee6
該惡意文檔打開如下所示,誘餌文檔的內容是用戶如何通過一系列操作看到文檔的真實內容,但是這些操作實際是執行惡意宏的過程。
該樣本同樣通過惡意vbs執行釋放文件,如下所示。
確認運行之后的真實內容。
主要是一份采購清單。
釋放的惡意exe同樣是一個nsis的安裝程序,但是這個樣本相較前一個就比較復雜了
$PLUGINSDIR:輔助nsis腳本運行的插件,這個樣本中使用了多個插件
$TEMP:保存了對應的憑據竊取工具,和前一個樣本一致
$0:一段用于load 的shellcode
$0_1:Meterpreter
[NSIS].nis:對應的nsis腳本
$PLUGINSDIR中的插件如下所示:
Createmutex.dll:用于設置互斥量相關的操作,這也是前一個樣本中使用到的唯一一個插件
nsExec.dll:用于輔助nsis腳本執行cmd命令
System.dll:用于輔助nsis腳本調用系統api
Nsis腳本同樣通過HideWindow設置隱藏安裝,之后調用函數func_516.
該nsis腳本為了獲取更為強大的功能,通過調用插件System.dll的方式來調用windows系統api,如下函數就直接調用了VirtualAllocEx函數。
func_516經過一系列處理之后調用函數fun_389.
fun_389設置開機啟動,并修改了防火墻的過濾規則,以允許惡意代碼和cc的通信,之后調用fun_224.
文檔釋放的最終nsis安裝包。
通過nsis設置了具體的開機啟動項
fun_224用于在內存中直接加在兩段shellcode,具體步驟如第一個紅框所示。
最終shellcode $0,$0_1通過一個線程啟動。
Shellcode如下所示:
第一段load shellcode
第二段包含Meterpreter的shellcode
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。