## Info [ 來源 ] : cyberdefenders.org [ 名稱 ] : [DeepDive Lab](https://cyberdefenders.org/blueteam-ctf-challenges/deepdive/) [ 描述 ] : 客戶已提供了受感染機器的記憶體映像檔,我們作為安全藍隊分析師要分析並找出攻擊細節 [ 題目提供 ] : banking-malware.vmem ## 解題 ### Q1 : 對於這個記憶體樣本您應該使用什麼 profile? 查看 image 的基本資訊 ``` python2 imageinfo -f banking-malware.vmem ``` #### 獲得以下資訊 : ![image](https://hackmd.io/_uploads/S1u7KLdqJg.png) - 建議 profile : Win7SP1x64、Win2008R2SP1x64_24000、Win2008R2SP1x64_23418、Win2008R2SP1x64、Win7SP1x64_24000、Win7SP1x64_23418 - 64 bit - 無 PAE ( 是 32 bit 才需要的功能 ) - KDBG ( Kernel Debug Block ) 是 Windows 核心偵錯結構,存放 Kernel 相關資訊 - 單核心 - 系統安裝了 Service Pack 1 (SP1) 可以排除 : Win7SP0x64、Win2008R2SP0x64 > 補充 : Service Pack 是 Windows 的大型更新包,修復漏洞、提升穩定性、增加功能,Windows 7 只有 SP1,沒有 SP2,Windows 10/11 則不再使用 SP - 24000 版本較新,可能會有更多的功能 - win7server、跟 win7 選不出來 #### Win7SP1x64_24000 ### Q2 : 記憶體樣本的KDBG虛擬位址是多少? ![image](https://hackmd.io/_uploads/BylyXP_cJl.png) 承上題的結果 KDBG(Kernel Debugger Block)是一個 Windows 內部資料結構,KDBG 是 Windows 核心為偵錯目的而維護的結構。它包含正在運行的 process 和已載入的核心模組的清單 > note : L 代表它是一個長整數,是在 Python 2 中的表示方式 #### KDBG : 0xf80002bef120 ### Q3 : 有一個惡意進程正在運行,但它是隱藏的。它的名字是什麼? psxview:可以透過布林值看 process 是否出現在 pslist 和 psscan 中。 ![image](https://hackmd.io/_uploads/B1mf8w_5Jg.png) #### vds_ps.exe ### Q4 : 惡意進程的物理偏移量是多少? 承上題的結果 #### 0x000000007d336950 ### Q5 : 隱藏可執行檔的完整路徑(包括可執行檔名稱)是什麼? 用剛才找到 offset 做查詢 ``` python2 vol.py -f banking-malware.vmem --profile=Win7SP1x64_24000 dlllist --offset=0x000000007d336950 ``` dlllist 列出 vds_ps.exe 載入的所有 DLL,並提供記憶體位址、路徑等資訊。 ![image](https://hackmd.io/_uploads/HyubiDu9Jx.png) #### C:\Users\john\AppData\Local\api-ms-win-service-management-l2-1-0\vds_ps.exe ### Q6 : 這是哪種惡意軟體? ``` python2 vol.py -f banking-malware.vmem --profile=Win7SP1x64_24000 procdump --offset=0x000000007d336950 -D dump\ ``` ![image](https://hackmd.io/_uploads/H1Q1yddq1x.png) ![image](https://hackmd.io/_uploads/SyHNJuu9kg.png) ### emotet >補充 : Emotet 惡意軟體的初始版本是一種銀行木馬,旨在從受感染的主機中竊取銀行憑證。 AKA 木馬的一種 ### Q7 : 該惡意進程的記憶體中註入了兩個 PE。包含最大注入 PE 的 Vad 的大小是多少(以位元組為單位)?以十六進位回答,例如:0xABC >補充 : VAD 虛擬位址描述符,是 Windows 作業系統記憶體管理系統中的一個基本元件。它主要負責管理和追蹤進程虛擬位址空間內的記憶體分配。 VAD 的結構是一棵二元樹,每個節點代表一塊虛擬記憶體。這些節點包含有關記憶體區塊的重要訊息,包括其起始位址、大小和狀態。 像下圖 : ![image](https://hackmd.io/_uploads/B1kH4d_cJe.png) VAD 會追蹤進程位址空間中所有分配的記憶體區域。例如記憶體範圍、訪問權限和類型(私有或映射)。例如,當 DLL 載入到進程中時,就會建立一個 VAD 節點來記錄其記憶體區域、存取權限以及它所對應的檔案。 [ref](https://www.tophertimzen.com/resources/cs407/slides/week03_01-MemoryInternals.html#slide44) [ref](https://www.linkedin.com/pulse/understanding-virtual-address-descriptor-vad-windows-memory-taz-wake-etoue/) malfind 指令可以根據 VAD 標籤和頁面權限等特徵來幫助尋找使用者模式記憶體中隱藏或註入的程式碼/DLL ``` python2 vol.py -f banking-malware.vmem --profile=Win7SP1x64_24000 malfind --offset=0x000000007d336950 ``` ![image](https://hackmd.io/_uploads/Symnb_d9Jx.png) 可以從圖看到 0x2a10000 和 0x2a80000 兩個的檔案都是 MZ 開頭,代表他是 DOS MZ 可執行檔。 查看 0x2a10000 的 VAD info ``` python2 vol.py -f banking-malware.vmem --profile=Win7SP1x64_24000 vadinfo -a 0x2a10000 --offset=0x0000000 07d336950 ``` ![image](https://hackmd.io/_uploads/BkKz5ddckx.png) 查看 0x2a80000 的 VAD info ``` python2 vol.py -f banking-malware.vmem --profile=Win7SP1x64_24000 vadinfo -a 0x2a80000 --offset=0x0000000 07d336950 ``` ![image](https://hackmd.io/_uploads/B1U_q_dqJe.png) 可以算出 0x2a80000 的 vad 比較大 ![image](https://hackmd.io/_uploads/HkXCs__cJl.png) #### 0x36fff ### Q8 : 此程序已從 ActiveProcessLinks 清單中取消連結。按照其前進鏈接。這會導致什麼過程?用其名稱和副檔名回答 pslist 是依照按順序列出了它們的,所以先前知道 vds_ps.exe 是 pid 2448 他介在 2424 跟 2616 之間,所以下一個執行的是 2616 SearchIndexer ![image](https://hackmd.io/_uploads/rJVu7Y_cJl.png) #### SearchIndexer.exe ### Q9 : 惡意行程的 pooltag 在 ascii 中是什麼? 當電腦執行程式建立一個 process 的時候,Windows 會在 kernel 中創建一個對應的物件,並使用 _OBJECT_HEADER 來管理它。這些物件的記憶體來自 pool ,pool 是系統為物件提供的動態記憶體區塊。 POOL_HEADER 會記錄這塊記憶體的大小 (BlockSize)、類型 (PoolType),並且 PoolTag 可以識別該記憶體區塊來自哪種 kernel 機制 ex : 當我們執行一個檔案的時候,會先創建 Process > 記憶體分配 > Kernel 物件管理 > 執行 Process #### 創建 Process : Windows 會透過 NtCreateProcess 或 NtCreateUserProcess API 來創建新的 process #### 記憶體分配 : 然後會有 MiCreateProcessAddressSpace() 來負責分配進程的虛擬地址空間,像是 - 程式代碼段 (.text) - 資料段 (.data) - 堆棧 (Stack) - 堆區 (Heap) ExAllocatePoolWithTag() 會從非分頁池 (NonPaged Pool) 或分頁池 (Paged Pool) 取得記憶體空間,這時候就會到物件管理 #### Kernel 物件管理 當系統從 Pool 分配一個物件時,會自動建立 : - _POOL_HEADER (記憶體池標頭) 記錄該物件的分配資訊 (大小、類型、PoolTag),他位於物件記憶體的起始地址 - _OBJECT_HEADER (對象標頭) 管理該物件內容包括 : - PointerCount (引用計數) - HandleCount (句柄計數) - TypeIndex (物件類型) - InfoMask (擴展資訊) 這是 POOL_HEADER 的架構圖 ![image](https://hackmd.io/_uploads/HyyOanOcJl.png) 確定的內容有 : - pool_header:0x10 bytes - 每一個的optional_header大小都不同 - OBJECT_HEADER : 0x30 bytes InfoMask 值 ![image](https://hackmd.io/_uploads/ry303hdcJl.png) 進到 volshell ``` python2 vol.py -f banking-malware.vmem --profile=Win7SP1x64_24000 volshell ``` 輸入以下指令 ``` dt( "_OBJECT_HEADER" ,0x000000007d336950-0x30 , space=addrspace().base) ``` - dt : Display Type,用來顯示結構的內部資料 - 指定的從 0x000000007d336950 惡意進程的位置減掉 header 的 0x30 bytes 開始分析 ![image](https://hackmd.io/_uploads/ByshSpdq1g.png) 發現 infoMask = 8,對應 infoMask 表發現物件有 object header process quota info >_OBJECT_HEADER_QUOTA_INFO 是 Windows kernel 物件管理機制中的額外資料結構,它負責追蹤物件的記憶體使用量,來監控物件的記憶體配額 (Quota),還有追蹤 proces 對資源的使用量 _OBJECT_HEADER_QUOTA_INFO 的大小通常為 0x20 bytes 最後要看到 pool header 就需要原本的位置減掉 0x30 object header 再減掉 0x20 OBJECT_HEADER_QUOTA_INFO 再減掉 0x10 pool_header 才會到 pool_header 的起點 輸入以下指令 ``` dt( "_POOL_HEADER" ,0x000000007d336950-0x60, space=addrspace().base) ``` ![image](https://hackmd.io/_uploads/rJV9O6dcJe.png) ![image](https://hackmd.io/_uploads/HyemFa_qye.png) ![image](https://hackmd.io/_uploads/SkXjY6dc1g.png) 但是因為是 little Endian 所以是反過來 #### R0oT ### Q10 : 隱藏執行檔的 pooltag 的實體位址是什麼? 把剛才 0x000000007d336950-0x60 + 0x4 就可以了 ![image](https://hackmd.io/_uploads/H1UqCpu9ye.png) #### 0x7d3368f4