作者:
Samsong
·
2016/05/25 12:47
Author: [email protected]
0x00 簡介
最近群裡提到TeslaCrypt的作者放出了主金鑰,簡單看了下,對他的加密流程比較感興趣。受條件限制,沒有拿到早期樣本(只拿到了晚一些的),放狗搜了搜也沒找到,但是找到了兩款解密程式。一款是Googulator開發的TeslaCrack,另外一款則是BloodDolly開發的TeslaDecoder。前者雖然開源,但支援解密的版本少於後者。本文透過分析及逆向樣本和這兩款工具,試圖瞭解TeslaCrypt的設計思路。
下文中所有圖片如無特殊說明,均為對BloodDolly開發的TeslaDecoder(簡稱“TD”)的逆向過程截圖。
0x01 加密流程簡述
TeslaCrypt(以及AlphaCrypt,下文統稱為“TC”)算是比較“成熟”的勒索軟體,其版本從0.2逐步升級到目前已知的最高版本4.0+(也不知道有沒有Insider Preview)。隨著版本的升級,其加密和金鑰處理技巧也在不斷升級。
勒索軟體的製作者為了打到目的,通常會給使用者一個比特幣錢包的地址。使用者向該錢包付款之後,可以得到一個解密金鑰,用此金鑰即可解密。有報告指出,不同的受害者需要向不同的錢包中打款,這暗示著比特幣錢包的生成過程可能與加密金鑰的產生存在一定關聯。因此,先大致瞭解下錢包是如何生成的。
比特幣錢包生成的基本步驟是:
- 初始化一對可用於ECDSA簽名的金鑰Public/PrivateBtcKey
- 用SHA256對PublicBtcKey做蛤希,得到S256_PublicBtcKey
- 用RIPEMD-160對上一個結果做雜湊,然後在雜湊前部加入版本號得到VR160_S256_PublicBtcKey
- 在上一雜湊前部加入版本號,並做兩次雜湊,將結果的前4位元組附加在VR160_S256_PublicBtcKey後,最後使用Base58演算法編碼。這時得到的就是長33個字元的錢包地址。
如果想知道關於橢圓曲線演算法的更多細節,有一篇文章比較適合參考閱讀。此外,TC還採用了ECDHE演算法進行金鑰交換,只是將DH裡的非對稱加密機制換成了橢圓曲線演算法,其他變化不大,可以參考這裡獲得更多細節。
TC被首次載入時,就生成了一對PublicBtcKey/PrivateBtcKey。其中,PublicBtcKey就是向使用者顯示的地址,而PrivateBtcKey則被髮送給C&C伺服器,以進行之後的轉賬操作。不同版本的TC,這一點是不變的。
TC作者本次公佈的金鑰是四號金鑰,應用於TC3.0以及TC4.0版本。這兩個版本都採用了比較完整的分層金鑰機制,並且提高了樣本隱蔽性。TC4.0的準備過程如下:
- 準備隨機數生成器等;
- 生成隨機數,並用714號曲線(即secp256k1)建立比特幣錢包,對應金鑰Public_BtcKey和Private_BtcKey;
- 對Private_BtcKey做SHA-256雜湊,得到Private_HashedPRBK,用Public_BtcKey算出錢包地址,一會展示給客戶;
- 用Private_HashedPRBK帶入曲線,得到第二對金鑰Public_HashedPRBK;
- 此外,TC的作者還擁有一對金鑰Public/Private_MalMaster。這對金鑰裡,Public_MalMaster是由TC作者置入程式的,而Private_MalMaster則是本次被作者公佈的“主金鑰”,難以被運算出來;
- 再生成用於加密傳輸資料的第三對金鑰Public/Private_Master;
- 用Private_Master和Public_MalMaster計算,得到用於對稱加密的金鑰Secret_Master;
- 以Secret_Master作為AES的金鑰,用AES_CBC方法,加密比特幣錢包的私鑰Private_BtcKey,得到加密後的結果Encrypted_PRBK;
- 將Encrypted_PRBK和Public_Master傳送給CC端;
- 攻擊者由Public_Master和Private_MalMaster算得Secret_Master;
- 用Secret_Master將Encrypted_PRBK解密為Private_BtcKey,得到可以收款的BTC錢包地址;
- 計算Private_BtcKey的雜湊值Private_HashedPRBK,作為收到付款之後返回客戶的金鑰;
現在TC已經做好了加密準備。TC的加密是以一個session為一環的,每次重啟、關閉計算機,都會終止當前的session,並啟動一個新的session。每次session裡的加密細節是:
- 生成一個Private_SessionKey和一個SessionIV,作為本次session裡對檔案進行加密的金鑰和CBC模式的初始化向量。
- 依據Private_SessionKey生成對應的金鑰對Public_SessionKey,並儲存;
- 用Private_SessionKey和Public_HashedPRBK生成一個用與對稱加密的金鑰Secret_Session;
- 用Private_SessionKey加密目標檔案,得到Encrypted_FILE;
- 用Secret_Session加密Private_SessionKey得到Encrypted_PSSK;
- 立刻沖洗Secret_Session和Private_SessionKey的儲存區域;
按照攻擊者的設定,使用者在被攻擊後,應該使用下面的流程來解密檔案:
- 向Public_BtcKey對應的錢包裡付款;
- 確認Private_BtcKey裡收到付款後,向客戶返回Private_HashedPRBK;
- 對每個檔案:
- 依據Private_HashedPRBK和Public_SessionKey,計算得出Secret_Session;
- 依據Secret_Session解密Encrypted_PSSK,即可得到Private_SessionKey;
- 依據Private_SessionKey解密Encrypted_FILE,即可得到原始檔;
在TC4.0中,作者在每個檔案頭裡都儲存了三個對解密必不可少的值:
- SessionIV
- Public_SessionKey和Encrypted_PSSK
此外還儲存了:
- Public_Master(同時傳送給CC)
- Encrypted_PRBK(同時傳送給CC)
- Public_HashedPRBK
- 原始檔案長度
而且,在金鑰沒有儲存意義後,立刻用資料對相應的儲存區域進行清洗,防止安全/取證軟體獲取到解密密碼。透過這裡也可以看出,病毒作者透過分析一些專殺工具和解密工具,對自己的技術也進行了升級。金鑰的分層機制也比較明確,在網路裡傳輸的資料,如果沒有Private_MalMaster,是無法解密BTC錢包地址的,而SessionKey的解密又依靠這個地址,從而保證除了攻擊者沒有第三方可以繞過邏輯解密檔案。最後完成的3.x和4.x版本,基本可以作為密碼學應用的示範程式。在作者公佈金鑰後,TD也嵌入了金鑰,並實現了上述的解密過程。
0x02 部分漏洞分析
TC的老版本則沒有新版本這麼“安全”了。對加密通道運用不當是比較常見的錯誤,在TC中也由發現。這是最早修復的漏洞,一個比較標誌性的版本是v6,在v6之前,所有的檔案都可以透過抓取感染後向CC通訊的網路流量來解密,但v6版本開始,這一做法便不能使用了。一種合理的猜想是,在舊版本的軟體中,可以直接解析出加密金鑰。對TD的分析證實了這一點。下圖是TD獲取網路流量後,判定金鑰與比特幣地址是否相符的(以免解密錯誤):
之後,TD便將金鑰放入對應區域中,其他操作則與正常解密類似:
從V2版本到V5版本的TC,將傳輸的私鑰以特定方式進行的加密,各版本的金鑰也有所不同,但由於金鑰是硬編碼在程式裡的,因此仍可以被TD直接提取出來,這就很尷尬了:
從TD的驗證邏輯推斷,舊版本的TC應該是向CC伺服器直接發回了BTC地址和Private_BtcKey(或簡單加密後的Private_BtcKey):
因此,在v5版本的某個變種中,TC作者移除了部分資料,使TC無法驗證網路請求中的BTC地址和私鑰是否相符,並在v6版本完全修改了向CC傳輸的資料,不再在通訊中直接暴露加密金鑰,徹底的封堵了這個邏輯漏洞。然而,利用這個漏洞,需要使用者持續收集網路流量,這在很多環境下不容易實現,因此這種方法的利用難度比較高。
第二個漏洞存在於TC的前兩個版本中。有一種比較簡單的方法,利用的主要是在加密設計過程中的漏洞。由於對資料儲存區域清洗不徹底,部分解密金鑰可能殘留在key.dat和登錄檔中。獲取了部分金鑰,可以極大的降低TD的解密難度,而且由於設計過程問題比較嚴重,這樣獲得的金鑰不是SessionKey而是使用者主金鑰,這樣就可以直接解密所有檔案了:
這個漏洞比較容易利用,修補難度也不高,因此只存活了兩個版本,就被勤勞的地下工作者修好了。
第三個漏洞就相對不太好利用。V7之前舊版本TC的弱點在於,在目標檔案中保留了“RecoveryKey”或與之相似的引數。這個引數是由一個私鑰和用於加密該私鑰的乘積,其存在意義不明,位置和數量也隨版本變化。比如在.xyz格式的檔案中,0x108偏移處的130個位元組,儲存的是檔案私鑰Private_SessionKey與檔案私鑰加密密碼Secret_Session的乘積。顯然,這個積可以被分解為多個質數的乘積,而Private_SessionKey的值可以由這些質數中的一個或多個相乘而來。這樣就產生了一個爆破思路:
- 分解乘積為素數表M
- 迴圈取M中的素數,計算乘積m
- 計算m在secp256k1模式下對應的公鑰值n
- 驗證n與Public_SessionKey是否相符。如果相符,則可用
這種方法能成功有兩個主要因素。最重要的一個是由於乘積的存在,增加了資訊量,也就弱化了保密特性。而另一個因素則是由於攻擊者在這裡採用了橢圓曲線演算法。這種演算法的保密關鍵點在於,解決ECDLP是困難的(在曲線Ep上給定一個點G,取任意一個整數k,那麼可以證得點P=k*G容易在同一條曲線上找到。但是,如果選擇適當的引數,那麼在已知P、G的情況下,求出k的群操作太慢了,而把G和Ep規定好,令k為私鑰,P為公鑰,就是橢圓曲線加密的基本原理),而不再一味依靠金鑰的位數。因此,在操作中,考慮到時間問題,一般把私鑰設定在160~300位,即使與RSA1024相比,這個長度也短的多,因此更容易被從素數表中挖掘出來(這裡的“更”是相對與RSA1024來說的,實際上也需要相當量的算力和運氣)。解決這個漏洞比較簡單,可以修改加密流程,也可以簡單的刪除這個乘積。因此,在V7以及之後的版本中,取消了這個乘積資料,這樣對V7和V8版本的解密就只能依靠攻擊者給出的金鑰才能解密了。
以上是我根據舊版本Teslacrypt的解密程式碼,瞭解到的一些漏洞資訊。自己的密碼學比較菜,如有不妥,還希望各位給一點人生的經驗。
0x03 相關連結
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!