Flare-On 2018 writeup(下)
程式先修改登錄檔,複製自身自執行
然後釋放下載後門的程式碼,載入記憶體執行
後門下載器載入庫函式從ldr連結串列中遍歷模組和模組函式,使用Hash來獲取API定位,此後的API都用這種方法遍歷,由於是病毒經典使用方法,可以搜到hash表,沒有搜尋到的可以動態修改hash引數來取結果
ofollow,noindex" target="_blank">https://www.scriptjunkie.us/files/kernel32.dll.txt
後門下載器搜尋了必要的庫函式,通過DNSQuery_A中查詢到的DNS附加資料,夾帶了加密的PE檔案
然後解密,並執行到指定的函式
直接執行起來,可以發現通過DNS查詢到的資料解密後會有彈窗
並在桌面上放了一個crackme.exe
從pcap.pcap中dump出網包中的DNS資料,將DNS查詢資料用網包資料覆蓋得到真正的後門檔案,後門下載器會執行到他的匯出函式Shiny
該函式查詢當前eip的位置,搜尋到自身的PE頭,獲取所有Sector相關的資訊,重新載入到申請的記憶體頁中,並從Dll入口點開始執行
對必要資源初始化和庫函式定位後,後門開始連線主控機,並等待互動
後門主要的流程從ShakeAndInitAes開始,連線主控機後,主控機和肉雞各生成一個隨機數以商定之後的AES通訊密碼
此後由主控機發出請求,肉雞執行對應命令,如果檢測到資料異常則斷開socket重新握手商定
所有收發包都由統一規則進行封裝,封裝大致格式
對原始資料進行了AES加密和Zlib壓縮操作,並加入一些資訊以及校驗頭,標明瞭長度、包型別、當前包AES_IV、hash等其他校驗冗餘資訊
通過對網包的復原和回放、解碼可以發現,肉雞A被感染後通過TCP 9443與主控機通訊,主要經歷了握手、上報了Malware各類版本、獲取計算機名、磁碟、列目錄、檔案資訊、ping主機、http請求、SMB廣播控制
肉雞A在感染受控過程中通過SMB2協議對病毒檔案進行廣播,感染肉雞B,並通過肉雞A接管肉雞B,通過SMB2協議建立命名管道進行互動,互動資料的打包解包方式和TCP方式一致
肉雞B受控經歷了一些磁碟、檔案資訊上報,並通過肉雞A寫入了Cryptor.exe,並執行Cryptor.exe level9.crypt level9.zip,然後執行刪除相關檔案,最後通過FTP上傳level9.crypt
將level9.crypt從網包中dump,可以看出已經被Cryptor.exe加密了,取得Cryptor.exe,為.Net編寫的檔案加密程式,de4dot反混淆後整理
程式對原始檔案進行Hash計算、將檔名長度、檔名、檔案Hash作為檔案頭進行AES加密,最後在加密資料頭部加上cryptar及github版本
AES加密會從github一專案獲取資訊作為檔案加密AES的Key和IV,可以發現github專案最新版本已經不是level9.crypt的版本從網咖或者git中拿當時版本的資訊
獲取20180810的資訊對level9.crypt進行AES解密,得到level9.zip檔案
該zip包被加密了,密碼需要在肉雞A和主控機的通訊中尋找
搜尋zip敏感字,找到密碼really_long_password_to_prevent_cracking
解壓zip包,取得一張空白圖片和一個並沒有任何作用的exe
上色,取得flag
Suspicious Floppy Disk
拿到floppy.img,得到一系列檔案
可以發現大概為dos系統盤,和原版img進行比較,多了infohelp.exe、key.dat等檔案
使用dosbox+ida5.5對infohelp.exe進行除錯,由於是16位程式,無法使用F5外掛,掏出王爽老師的彙編書籍溫習一下16位x86彙編,然後在除錯時,地址前加上對應的段名。
可以發現大致行為是輸入password,將輸入的password寫入password.dat然後開啟message.dat顯示失敗資訊
ida對該檔案進行逆向,可以發現
程式由16位Watcoom編譯,使用對應的watcom編譯帶除錯符號的庫,並製作FLIRT signature的簽名檔案,ida識別出大部分函式
程式由sub_10000作為入口主要流程如下
printf("input pw") scanf("%s", &pw) fopen("key.dat") fwrite(pw) fclose() fopen("message.dat") fread() fclose() printf(msg)
所以這個程式並沒有直接藏有密碼資訊
使用WinHex發現了映象中還有一些碎片檔案可以通過特徵恢復,但並沒有什麼發現,進一步觀察發現映象的mbr和原版dos相比被篡改了其中一段
使用vm+ida對更改的mbr進行除錯,起始流程如下
0:0x7c00: memcpy &mbr_cpy_600h, &mbr_7c00h, 0x200 -> 0x662 0:0x662h memcpy 0:0x800, &tmp.dat, 0x6000 call tmp.dat sub_0 -> 0:0x800 0:0x800 (tmp.dat sub_0:) 0:0x413 -= 0x0020 (0:0x413 = 0x025d) 0:0x6ff3 = 0x9740 memcpy 9740:0, 0:0x843(&tmp.dat+0x43, NICK RULES ~ NICK RULES), 0x5eb0 0x9740:0x5e5a = dw 0xca000117 (real int 13h) 0x9740:0x5e6f = db 0 0:0x200 = dw 0xca000117 (real int 13h) 0:0x4c = dw 0x97400012 (int 13h hook to 0x9740: 0x12) -> ret 0:0x671
篡改的mbr載入了tmp.dat中的函式,對0:0x4c地址的資料進行改寫了,然後解碼恢復原版mbr繼續執行
0:0x4c這個地址正是int 13h中斷服務函式地址,篡改後的地址為0x97400012
查閱資料,這種在mbr將系統服務進行hook的技術在bootkit很常用,由於預先於作業系統、應用程式載入所以很難被查殺
繼續跟進,可以發現進入偽造的int 13h函式會先記錄int 13h所有的引數並執行真正的系統服務,然後對引數進行比對進入相應的handler,主要是讀扇區時,hook解碼原版mbr以及在開啟message.dat檔案時會call tmp.dat中的函式,寫扇區時也會有對應的handler
由img中的引數得知LBA=0x200 * 【柱面 * 36 + 磁頭*18 + 扇區 – 1 】,經過計算可以發現cx = 0x2111, dh = 1, al = 1時正好對應message.dat,讀取該檔案時執行事先載入tmp.dat中的函式
介面如下
也就是通過Infohelp.exe作為觸發器,當輸入密碼開啟message.dat顯示不正確的資訊時,實際被hook到另一個解密程式,通過跟蹤恢復出這個handler
通過infohelp輸入完密碼後對key.dat寫扇區的hook handler,先取得密碼,然後在讀取message.dat時執行真正的密碼檢查函式,並返回結果
由於這個bootkit對vm的bios相容性不好,並不能進入dos系統執行infohelp(bochs據說可以正常執行和除錯),我在int 13h進行其他服務時,修改了引數以觸發解密程式
解密程式如下
查閱wiki資料,這是one-instruction set computer (oisc),subleq的軟體模擬,本來旨在於只支援一種指令的低成本晶片,也同時給逆向帶來麻煩
在python中重構subleq的模擬環境
參考網上關於Flare-on 2017,11題類似的subleq題解,進行側通道攻擊,通過不同密碼輸入的cpu titk、pc graph等手段,除了發現密碼中輸入了@會大大增加計算量以外並沒有明顯發現
然後進行資料流分析,追蹤密碼的流向,對讀寫密碼的敏感位置進行標記,得到巨量的操作一時沒有總結出規律
最後這段程式也是由出題者編寫的編譯器編譯的,本著編譯本身有一些規律,參考去年11題官解,對subleq進行命令組合
去年官解並沒有把所有的指令定義列出,不斷嘗試和摸索中定義了以下指令
其中最難的是subleq通過指令修改了自身指令,這種情況通過指令操作的target address寫入了已經識別為指令的地址區域列出,進一步可以發現這些自身修改的指令主要用於指標操作*(%a) = %b, %b = *(%a), jmp *(%a)等操作,可以理解通過修改自身指令替換簡單mov中的操作地址,來實現指標訪問
反編譯器的設計思路是先區分指令區、資料區(通過執行的實際情況可以覆蓋大多數),標記subleq基礎指令(如 subleq s,d,t / subleq z,d / subleq z,z等),基礎指令由3個運算元構成,通過區分源、目標、跳轉地址是否為零是否相等區分出不同的基礎指令,包括資料也認為是一種特殊指令,儲存
然後將簡單指令組合成複合指令,複合指令一般會以基礎指令的固定組合重複多次,並且意義明顯,如mov或者跳轉操作
然後將指令解析成對應的LikeC,並分別生成具有完全標籤和自動簡化標籤的兩個檔案
防止因為一些指標跳轉,無法找到對應指令位置的情況,然後對LikeC進行靜態分析
這段subleq程式大致如下
查閱資料,這又是一個vm,oisc的另一種rssb
同樣的進行側通道和資料流分析,一時沒有掌握到規律,在編寫一個反彙編器
rssb比subleq還要抽象,基礎指令只有一條rssb x,但是x有幾個特殊值 Line"/>
x為-2時代表返回,-1只填補位置,0為當前程式指標,1為rssb累加器,2為常0暫存器,6為輸出暫存器
當然這個是由本題的編譯器定義的,並不一定通用,類似subleq反彙編器一樣,合併基礎指令為複合指令如下
生成對應的rssb解析檔案和LikeC(帶完整標籤/自動簡化標籤)
進行靜態分析,還原,關鍵函式如下
可以發現@作為檢查密碼的結尾字元,而最後的密碼校驗方式是自定義hash演算法與預定的hash表比對
hash計算公式如下
for i in range(15): hash[i] = (((key[i+1]-32) << 7 + (k[i]-32)) ^ (i * 33) + magicsum) & 0xffff
其中magicsum是所有密碼的ascii和加3072乘密碼長度
magicsum = 3072 * len(key) + sum(key)
由於magicsum不得知,key也不知到,只有期望的hash表,magicsum只能為0~0xffff
進行列舉倒推key[],然後檢查magicsum是否符合約定並列印
找到明文資料[email protected],至此Flare-on5完成
Easter Egg
彩蛋關,malware skillz關卡中通過DNS協議下載的crackme
程式帶殼,上來pushad,esp定律,下esp寫入斷點F9
停在OEP 0x401000,dump源程式
拖入IDA
程式混淆了字串和控制流結構
大致流程是分別putc:Password:
然後getc,一位一位校驗
然後輸出校驗結果,一般password一位字元的校驗程式如下,由於所有的字元處理都是線性處理,先設定輸入password為’\x00’ * 40然後在關鍵的比較位置下bp取出jz的比較值
如比較值為0xc8,正確輸入時應為0x00,則意味著該位password實際應該為(char) (0x00-0xc8),即’8’
解出所有的password位:83cbeb65375d4a1263c2e28bc9cf4f8a8c8f834e