# 0x0F. Cycldek Triad Analysis [TOC] ## 前言 感恩大神讓我有幸能拿到Sample,機會難得,決定跟著學習記錄一下分析過程 卡巴斯基分析參考的Link: https://securelist.com/the-leap-of-a-cycldek-related-threat-actor/101243/ <br> ## Quick Summary 從圖中可以看出,最後的Payload被相當噁心的一層一層包起來 本文會介紹如何一層一層把Payload拆回來 ![](https://i.imgur.com/bfYEBZo.png) > Source:https://securelist.com/the-leap-of-a-cycldek-related-threat-actor/101243/ <br> 另外,本篇在最後會用到大量Windows PE的概念,推薦可以參考這裡 https://raw.githubusercontent.com/corkami/pics/master/binary/pe102/pe102.svg <br> ## Finder.exe 根據PE Studio,引用函數表會用到outllib.dll 標準的DLL Side Loading Attack :::info 這是一種白加黑的攻擊手法,透過安插一個惡意dll在乾淨的binary裡面,將自己植入process中 ::: ![](https://i.imgur.com/Ohl8yz6.png) <br> ## outllib.dll 這個dll是個loader,但有許多有趣的地方,以下列出幾個 ### Handle & EntryPoint - GetModuleHandle(0) = 回傳自身Process Handle (Finder.exe) - Handle to process = **Base address** at which they are load ![](https://i.imgur.com/d20N7xo.png =80%x) <br> - 馬上看到下面handle值被增加了,這其實在計算program entry point - VirtualProtect改變permission ![](https://i.imgur.com/vSA4hsi.png =80%x) <br> ### Hooking Execution Flow 更改完permission,樣本做了個覆寫 ``` E9 new_function ==> 轉成assembly ==> JMP new_function ``` ![](https://i.imgur.com/zpBwF4R.png =80%x) <br> ### new_function - `CreateFile(..,rdmin.src,...)` :成功的話往右邊走 ![](https://i.imgur.com/SAZrDaR.png =80%x) <br> 緊接著使用 - HeapAlloc(FileSize) - VirtualProtect(RWE) - ReadFile(rdmin.src) ![](https://i.imgur.com/5lDQKDv.png =60%x) <br> ### Decryption Loop & call - 無效decryption loop ![](https://i.imgur.com/gXmIfF4.png =80%x) <br> - 真正的解密loop - XOR 7A ![](https://i.imgur.com/GVM6iAt.png =80%x) <br> - 呼叫解密後的rdmin file ![](https://i.imgur.com/jHE46ZO.png =50%x)) <br> 到這裡,已知outllib.dll會load rdmin.src檔案,並且用xor 7a做解密 下一步,可以將rdmin.src在010 Editor做解密 看看會得到什麼? <br> ## rdmin.src 首先,將rdmin.src整個檔案`xor A7` 另存新檔`rdmin_src_xor_7a` ![](https://i.imgur.com/ObTpAsi.png) <br> ### 尋找Kernel32.dll ![](https://i.imgur.com/s6vr2Zh.png =60%x) <br> 以及對應的pseudo code - PEB結構 - 尋找Kernel32.dll ``` FS:[0x30] -> PEB PEB[0xC] -> LDR LDR[0x1C] -> InitializationOrderModuleList: _LIST_ENTRY ``` ![](https://i.imgur.com/hmRcEy2.png =70%x) <br> ### Function Table 原本是function string hash value 使用HashDB可以返推出API名稱 | Before | After | |:------------------------------------:|:------------------------------------:| | ![](https://i.imgur.com/9PgVhKu.png) | ![](https://i.imgur.com/2flWzWv.png) | <br> ### Resolve_Function 被大量呼叫,且看起來在parse PE結構 可以嘗試用IMAGE_DOS_HEADER來解析 ![](https://i.imgur.com/k4na20p.png =50%x) <br> Insert`ntapi` ![](https://i.imgur.com/boCi89K.png =80%x) <br> 回到Structure Tab,新增 - `IMAGE_DOS_HEADER` - `IMAGE_NT_HEADERS` - `IMAGE_EXPORT_DIRECTORY` ![](https://i.imgur.com/4ZYD8jH.png) <br> 新增之後如下: | Before | |:-------------------------------------:| | ![](https://i.imgur.com/5BpJx50.png ) | | After | |:------------------------------------:| | ![](https://i.imgur.com/Nvxow4s.png) | <br> ## Cross Reference Back & More Analysis Cross Reference回去 ### 新增Table structure (v5) ![](https://i.imgur.com/tjE6ANR.png =50%x) <br> 經過分析,結果大概會變成這樣,接下來一一介紹 - FunctionTable structure - `v14` = start of encrypted payload :::info 這邊的FunctionTable是我自己在IDA新增的一個structure 單純是對應`prepare_API_structure`中,開發者定義的架構 ![](https://i.imgur.com/LVsD8T1.png =60%x) ::: ![](https://i.imgur.com/JzSWiCm.png) <br> ### Decrypt + Decompress - RC4 Decryption, Key=`8f-2;g=3/c?1wf+c92rv.a` - 增加一些參數,以及decompression,根據enum判斷為LZNT1規格 - `memcpy(buffer,starts=0x1478,length=[0x1470]=0x24df)` ![](https://i.imgur.com/4pbBubp.png) <br> #### 010 Editor 回到010 Editor打開`rdmin_src_xor_7a` 從`0x1478`開始,選擇長度`0x24edf` Copy as Hex Text -> CyberChef ![](https://i.imgur.com/dRGXyKR.png =70%x) <br> CyberChef decrypt RC4 - From Hex - RC4 Decrypt ![](https://i.imgur.com/mLOoSPh.png) <br> 使用Python decompress ![](https://i.imgur.com/f4Zrj6T.png =70%x) <br> 儲存後看起來是binary data,並不是預期中的PE檔案 可以繼續回去看看IDA發生什麼事 ![](https://i.imgur.com/IyUWFg9.png) <br> ## PE Fix 正常情況下,經過一連串的side loading/xor/RC4/decompress 理應看到一個完整的PE檔案 但這個Sample的developer相當厲害,所有PE的Header都被去掉了 - MZ - PE - .... 會在程式中重新build回來 所以接下來,要看惡意程式如何rebuild PE Header ![](https://i.imgur.com/orEouNi.png) <br> ### 010 Editor 要Rebuid的東西相當多,可以嘗試在010 Editor中直接使用template system去觀看/Fix Header 就不用看太多pseudo code了 記得要從Template Repository中下載EXE Template ![](https://i.imgur.com/S9ELTrS.png) <br> ### Fix PE Header In 010 Editor 這邊有幾個東西要修,一個一個來看 - e_lfanew 這邊IDA pseudo code有點噴掉,不能顯示正確該減掉的數值 e_lfanew應該要減去 `0x1240040` | pseudo code | assembly | | -------- | -------- | | ![](https://i.imgur.com/2RhqYDR.png) | ![](https://i.imgur.com/GELJFjK.png) | <br> 利用Tools -> Hex Operation來修改數值,變回`08 01 00 00` ![](https://i.imgur.com/qYJmREz.png =70%x) <br> 重新Load一次template,可以知道PE\0\0的正確位置應該在`0x108` ![](https://i.imgur.com/LO1vYPp.png) <br> 而且能在template中看到新Parse出的IMAGE_NT_HEADER 不過可以看到 IMAGE_MACHINE也在等待輸入,32bits為 `0B 01` ![](https://i.imgur.com/4gaBPBy.png =80%x) <br> - AddressOfEntryPoint AddressOfEntryPoint也需要被修正 根據IDA,`AddressOfEntryPoint -= 1400010h` ![](https://i.imgur.com/HI8gpsm.png =80%x) <br> 修復後的AddressOfEntryPoint為`0xE1DE`,相對合理許多 ![](https://i.imgur.com/JgHj7sY.png) <br> 除了上述兩個之外,列出了一些也要修正的部分如下 :::info 其他在IDA中顯示需要修復的如下 ``` e_lfanew -= 0x1240040 SizeIfImage += 0x2402200 SizeOfHeaders -= 0x20A000 ?? 0x144A040 AddressOfEntryPoint -= 1400010h NumberOfSections -= 0xAD49 For each section: SizeOfRawData -= 0x2400A1 VirtualAddress -= 0x1004080 ``` ::: <br> 修正完之後,就可以得到一個新的最後payload ![](https://i.imgur.com/SV2m59Q.png) <br> ## 結論 本篇介紹了許多拆解難度較深的Anti-Reversing花招 在最後面也遇到了比較少遇過的手動PE Fix 這部分會需要一些Windows PE的概念 如果有不清楚的地方,推薦可以參考aaaddress1大神的書 https://www.books.com.tw/products/0010890871?sloc=main 最後也感謝贈與Sample讓我玩的好心大神QQ ~~分析完真的快吐血~~ <br> [-0xbc](https://hackmd.io/@0xbc000) ###### tags: `Malware Analysis` `Reverse Engineering` `tutorials`