1. 程式人生 > 其它 >CobaltStrike逆向學習系列(10):TeamServer 啟動流程分析

CobaltStrike逆向學習系列(10):TeamServer 啟動流程分析

這是[信安成長計劃]的第 10 篇文章
關注微信公眾號[信安成長計劃]

0x00 目錄

0x01 基本校驗與解析

0x02 初始化

0x03 啟動 Listeners

在之前的分析中,都是針對 CobaltStrike 整體通訊流程的,也就忽略了中間的一些細節,其中一些細節對理解整個 CobaltStrike 也是非常重要的

0x01 基本校驗與解析

先取了預設埠

接著對 Java 環境及一些引數進行了驗證,並校驗了 license

這裡重點看一下對於引數的檢測,可以看到有校驗兩個引數是否存在,當你在跑 Controller 的時候,最好也一樣將其引數加上,不然有可能會出現一些莫名其妙的問題

對於 IP 等內容的判斷就不重點關注了,看一下他在解析 C2Profile 時候的對比,如果有指定的話,會走下面那個流程,直接將地址傳入 LoadProfile

而在預設情況下,則呼叫了 LoadDefaultProfile,但它實際還是呼叫了 LoadProfile,然後直接載入了 resources 中的預設檔案

之後就到了最關鍵的初始化環境的地方

0x02 初始化

先在 C2Profile 中增加了兩項內容,license 認證中的水印與當前的路徑,具體作用暫時也不清楚

接著初始化 Resources 物件,並傳入了 this.calls,它是一個 HashMap,對於後續所有的呼叫都至關重要

在初始化 Resources 的時候,對兩個內容進行了初始化,它們內部都建立了新執行緒,根據名字也可以明顯的看出,ServerBus 是 TeamServer 所有執行內容的通道,所有的呼叫都是從這裡走的,Archiver 屬於日誌型別的操作了,在除錯的時候,時不時出現的 archiver 型別的資料包也就是從這裡出來的

在 ServerBus 中,除了將 calls 傳入之外,就直接 new 執行緒了

整個的邏輯也很明確,與 TeamQueue 等檔案的處理方式是類似的,在接收到資訊以後,從 calls 中獲取到對應的型別,然後呼叫對應的 call 來完成後續的流程處理

再來看一下 Archiver 的相關處理,除了後面會 broadcast 資訊之外,剛開始的 PersistentData 還是比較重要的

在中間直接建立了新執行緒

處理邏輯跟前面也差不多,判斷是否有資料,如果有處理

大致也就猜出來是將資料儲存到檔案中

回到主流程中,接著將 C2Profile、IP、密碼等資訊也儲存到 this.resources 中

然後往 this.calls 中存入了幾個測試資料

對於這種 Test 的操作,在 CS 中也有很多,還有一個專門用來負責處理斷言操作的類

然後往 this.calls 中存入了資料

這些實際上才是最關鍵的內容,根據上面 ServerHook 可以看到,在執行的時候,會根據這個型別來決定呼叫哪個類中的 call,也就決定了最終的處理流程

接下來的一眾操作都是這個樣子,為後續處理做了相當充足的工作

而且中間也能夠看到很多東西了,釋出任務時候的 beacons.task,啟動監聽的 listeners.go 都是在這裡設定的,所以也就是說在 Controller 與 TeamServer 通訊時,所傳輸的 beacons.task 等,最終都是在 ServerHook 中根據之前儲存好的型別來最終決定處理流程的

經過這一波操作,this.calls 已經增加到了 64 個,接著又進行了一堆操作,增加了對資料的處理

所遍歷的就是下面這些內容

然後通過如下的方式來進行了批量的新增,this.calls 最終達到了 106 個

接下來就是之前分析的與 Controller 進行通訊的部分了

0x03 啟動 Listeners

為了驗證前面所提到的流程,這裡用啟動監聽來作為說明

跟入後可以發現,它在 ServerBus 中增加了一項

所以就直接在 ServerBus 的處理執行緒中擷取到

取出型別是 Listeners,就直接呼叫到了 Listeners 中的 call 方法,但是很明顯它什麼也沒幹,又用剛才的邏輯呼叫到了 beacons.start

一樣通過剛才的邏輯進入相應的處理

在其中它根據 Listener 初始化了相對應的監聽

這裡用的是 HTTP

接著初始化了 RSA 公私鑰

如果檔案存在的話,就不會再生成了,所以還是自己做一份為妙

然後也將這些資訊儲存到了 BeaconC2 當中

接著就根據剛才初始化到資訊啟動相應的監聽

然後將監聽類與 Payload 儲存到一個 HashMap 當中

就完成了監聽的啟動

接著又用同樣的邏輯呼叫了 listeners.set_status,然後將資訊儲存到 Listeners 的 Map 當中

然後又呼叫了broadcast,通過 BroadcastWriter 將資訊回傳到 Controller

這樣也就完成了所有的操作