作者:雪諾凜冬實驗室 gd
原文鏈接:https://mp.weixin.qq.com/s/R1BoWivtTxo0zFk4nyBFTw
前言
隨著近幾年HW實戰的開展所有人都對Cobaltstrike不再陌生,相關安防設備一直在思考如何在流量側/終端側識別出CS的行蹤。攻擊者除了使用習慣上基于插件進行開發提效外,還有一些需要關注對抗的點來提升CS的隱藏性,我們會分兩篇文章將CS在流量層面、內存層面對抗側二次開發做出的思考實踐與大家分享交流。
流量層面的思考
從流量整體偽裝的角度來看,最好的效果就是和正常流量混為一體,以此為出發點來構思流量隱蔽方案。
-
有些思路會說改變CS原有的加密方式,自定義編碼/加密的算法,不局限于C2 profile里面的幾種算法。不管是哪種算法,我覺得目前基于HTTPS流量的通信方式是最好的,對于中間流量設備來說所觀測到的https流量也是最多的,我們的c2混在其中讓其無法區分。
-
當然即使是完全加密的流量,也能使用其他方式進行特征抽象。比如 SPLUNK 和 RITA(一款用于網絡流量分析的開源框架)都曾實踐過對通信頻率,發送/接收平均字節數,連接數進行分析,使用數學的方式提取檢測特征。當然我們也可以做出應對,增加流量發送的隨機性,對于Beacon在靜默狀態和使用狀態設置不同的通信頻率,達到在時序性上的對抗。
在實踐中我們更關注第一點。傳統的域前置方式利用HTTPs隱藏真實的請求Host,來繞過安全設備的流量檢測。從中間設備觀察到的DNS和TLS sni均是可信域名。但隨著云服務廠商進一步限制,域前置的使用范圍進一步縮小。我們使用了Shadow-TLS這一方式,不再依賴于云廠商的實現缺陷,也能達到隱蔽流量的效果。
Cobalt Strike 流程概述
cs.auth 認證流程
cs的 license 核心是非對稱加密算法,對于關鍵的beacon相關文件使用rsa公鑰加密,license 文件則是包含了cobalt stirke版本、watermark標志、license過期時間以及beacon解密私鑰等信息。
主函數
客戶端主函數 agressor, server端主函數 server.TeamServer,其中客戶端主要是啟動之前校驗一下license,然后是啟動圖形界面,數據初始化。客戶端這塊不是主要關注的點,我們主要關注的點在服務端。也就是 TeamServer 類。
TeamServer 類也繼承于 Starter 啟動器父類,也會檢測license合法性,獲取過期時間水印等參數,解析 c2profile 配置文件,拉起server服務、listener,等待客戶端連接上來,其中listener是由nanohttpd服務承載。
beacon的生成
當選擇一種生成模式之后從通用模板artifact.exe當中填充beacon.dll的shellcode,profile配置也是在這個時候經過xor加密填充到預留的空間。
beacon的上線流程
收集一波主機信息之后向server發送一個上線包,此時產生一個session id作為這臺肉雞的標識,后續則不停發送心跳包(結合隨機垃圾數據以免成為固定特征)等待下一次指令。
第一步明顯特征規避
二階段加載特征
二開第一步先把常規的cs特征規避了,像是profile配置、端口證書這些都不需要代碼層面的改動,github上比較火的開源profile配置也已經被檢測為特征了。我們更關注的是需要代碼改動的特征,cs 的 stage 二階段遠程加載需要下載beacon的shellcode,當訪問url路徑符合checksum8計算的值,listener就會返回二階段所需要運行的真正執行beacon的shellcode。使用二階段加載beacon的功能會增加資產測繪被發現的風險,而且beacon的一階段也不具備什么特殊的功能,不太符合實際場景的需求,大家可能更傾向于stageless或者定制化二階段加載。這里的做法是直接刪除該服務,畢竟怎么也不會用上單一的二階段加載beacon。
ja3/ja3s | jarm 指紋修改
JA3 是由 John Althouse、Jeff Atkinson 和 Josh Atkins 創建的開源項目。 JA3/JA3S 可以為客戶端和服務器之間的通信創建 SSL 指紋。唯一簽名可以表示從 Client Hello 數據包中的字段收集的幾個值:
- SSL Version
- Accepted Ciphers
- List of Extensions
- Elliptic Curves
- Elliptic Curve Formats
JA3 工具用于為與服務器的客戶端信標連接生成簽名。另一方面,JA3S 能夠生成服務器指紋。兩者的結合可以產生最準確的結果。JA3S 可以捕獲完整的加密通信并結合 JA3 的發現來生成簽名。更詳細的信息可以直接查看官方github倉庫:https://github.com/salesforce/ja3。
本來 ja3/ja3s 指紋不算是什么很強的特征,因為它只是一個tls握手包的hash值,ja3s是被動流量,jarm是主動探測,這個指紋取決于你的tls所使用的參數,也就是說完全有可能別人寫的https服務也和cs的listener撞上了,但是我們不能不修改,因為放著這樣一個特征不去管也會成為可能突破口,修改的辦法也很簡單,在nanohttpd服務中,修改SSL相關的任意參數就能達到效果。

這里列出幾個已知的ja3/ja3s指紋信息:
JA3
- 72a589da586844d7f0818ce684948eea
- a0e9f5d64349fb13191bc781f81f42e1
JA3s
- b742b407517bac9536a77a7b0fee28e9
- ae4edc6faf64d08308082ad26be60767
可以看到修改過后的值:

Sigma 檢測規則
根據開源的sigma檢測規則,上面公開了一些關于cs beacon的特征,像是cs默認證書以及檢測被公開的一些profile配置,這里提幾個實戰中可能遇到的:
- 查看DNS日志基于dns_stager_subhost的默認DNS c2行為

- 基于對單個域的大量DNS查詢檢測

- 還有一分鐘內從單一來源查找多條TXT記錄

如果實戰中遇到只有DNS出網的上線需求的話可以考慮使用DNS beacon, 注意一下默認的DNS行為就行,使得DNS請求趨于正常流量,根據配置就可以做到。只是需要注意一下一些通用的檢測手段。
第二步隱蔽通信流量
接下來是本次二開CS中的重點,傳統的CDN域前置隱藏c2的方式大家早已熟知了,CDN廠商也做了限制手段,想要再做出提升,唯有另辟蹊徑,因此我們將目標對準了Shadow-TLS,以此達到更好的隱蔽流量的效果。
一般使用域前置時,把CDN作為白名單域名,當作一個靶子,中間設備所觀測到的是一直與CDN通信:

現在CDN廠商使用應對手段禁止域前置被惡意使用:
- 對比SNI和Host是否相等,如果是HTTPS流量需要解密
- 禁止未驗證的域名加速
傳統CDN域前置遇到了些許阻礙,但有另一種思路,shadow-tls 將任意白名單域名作為影子域名,借用TLS連接建立起偽裝,這或許是個不錯的選擇。
在講shadow-tls之前我們先簡單回顧下TLS握手的流程:

客戶端發送握手,服務端返回握手、證書,雙方協商密鑰,之后統一用一個密鑰對稱加密之后的內容。那么怎么在這上面做文章呢?shadowtls的實現方式:

客戶端請求與中間人服務器建立連接,握手階段服務端將客戶端的請求轉發到?個可信域名上(顧名思義Shadow域名),這樣保證流量側看到的服務端證書是?個可信域名的證書,在握手結束后,client 和 server 切換模式,利用已建立的連接傳輸自定義數據即可。這樣做其實相當于一次 “TLS 表演”,給中間設備看的。并且在client Response中使用預定共享key返回8字節的hmac值,用于區分客戶端流量和主動探測流量,正確響應主動探測流量。
snowc2的實現方式
我們如何在CS中實現呢?這里我們用了更為直接的辦法,在接收到影子域名的 server hello 握手包之后替換掉證書部分,使用c2 server的證書協商出密鑰完成握手,接著就是正常的https流量 application data,同樣給中間設備做了一次“TLS 表演”。
對于CS Server來說想要實現這部分功能,需要覆蓋JDK類,這里用到了 java 提供的 endorsed 技術,可以簡單理解為 -Djava.endorsed.dirs 指定的目錄面放置的 jar 文件,將有覆蓋系統 API 的功能。我們找到 CertificateMessage.java 文件中 T12CertificateProducer 類的 onProduceCertificate 方法,這個方法是處理tls握手時返回 sever hello 消息中的證書數據部分的,我們在其發送證書信息之前,替換成白名單域名的證書。這里給出演示DEMO,實際項目實現需完成更多細節。

既然服務端使用了白名單域名證書,客戶端也要寫一個替換證書,只不過要替換成原來的證書,寫一個簡單判斷即可。

在tls握手階段,判斷 server hello 消息頭,識別出證書消息,將其替換為我們原來的自簽名證書。
最終效果
當我們自建域前置并結合shadow tls時:
client -> tls -> cdn -> c2 server
tls 請求
SNI: allow.com
http 請求
Host: allow.com
中間設備所觀測到的將會是,客戶端向 allow.com 發起了請求,經過TLS握手進行后續的通信,證書也是 allow.com,從明面上來講,已經找不出毛病。


可以看到客戶端和cs server的tls握手通信變成了與 www.baidu.com 域名證書的握手。此外除了https連接請求之外,我們也加入了dns請求的流量,以讓其看起來更像正常的通信流量。
這次二開我們專注在C2流量層面所做的事就告一段落,后續會更新內存層面的去特征化實踐,請大家繼續關注雪諾凜冬實驗室。
Reference
- https://www.ihcblog.com/a-better-tls-obfs-proxy/
- https://thedfirreport.com/2022/01/24/cobalt-strike-a-defenders-guide-part-2/
- https://github.com/salesforce/ja3
- https://github.com/snowtech-cn/shadow-tls-client
- https://github.com/snowtech-cn/serverhelloEndorsed
關于雪諾凜冬實驗室

本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/2046/
暫無評論