當前位置:
首頁 > 新聞 > Encryption 101系列:解密程序的設計思路

Encryption 101系列:解密程序的設計思路

在本系列的第1、2、3部分中,我們分別介紹了加密的基礎知識,深入剖析了一個勒索軟體樣本,並討論了加密系統可能存在的弱點。在本文中,我們將對一個帶有弱加密演算法的勒索軟體進行深入分析,然後,圍繞該勒索軟體逐步展開設計相應解密程序的具體思路。

本文旨在幫助惡意軟體分析師在分析和破解勒索軟體加密的道路上邁出堅實的第一步。通過閱讀本文,讀者就會明白在破譯密文的過程中,深入考察勒索軟體本身是多麼重要的一項工作了。

儘管現代操作系統都內建了相應的加密軟體包和API,但許多惡意軟體作者在使用這些軟體的過程中仍然會出現紕漏,這就給我們(分析師)利用其糟糕的編碼技能設計解密程序創造了良機。

關於勒索軟體樣本

在本文中,我們使用的勒索軟體樣本是PrincessLocker。當然,Hasherezade已經針對該軟體進行了深入的分析,並創建了相應的keygen和解密程序。如果讀者對這些感興趣的話,請訪問:https://hshrzd.wordpress.com/2016/11/17/princess-locker-decryptor/。

軟體分析

在本文中,我們不會對軟體的脫殼技術進行介紹,相反,這裡假設您已經掌握了PrincessLocker的脫殼技術,並已經了解其基本功能。下面給出該樣本未加殼之前的哈希值:

4142a59be1f59dbd8e1be832df893d08

以及初次加殼處理後的哈希值:

14c32fd132942a0f3cc579adbd8a51ed

首先,我們會對未加殼的樣本進行靜態分析,之後,再對其經過加殼的樣本進行動態分析。

靜態分析

既然我們只關心代碼中的加密部分,那麼就從搜索加密字元串或API並進行交叉引用開始吧。經過初步分析,我們發現在函數地址10007980處使用了CryptDeriveKey API。

這裡,傳遞給CryptDeriveKey的、用於演算法ID的參數是0x660E,即CALG_AES_128。

由此得知,在這個地方生成了一個AES密鑰,這個AES密鑰的「密碼」就是pHash變數的值。如果我們跟蹤這個變數的話,我們會看到它被傳入10007BB9,即call esi指令。實際上,這些字元串都經過了混淆處理,所以使用靜態分析很難看出它們的真面目。因此,我們下面將藉助調試器來對付加殼後的文件14c32fd132942a0f3cc579adbd8a51ed。

調試代碼

對於加過殼的文件,為了定位脫殼後的目標代碼所在位置,我通常會從脫殼的樣本中尋找一個API調用,並設置一個斷點以進入該庫代碼。如果我們轉到被調用的主函數,並轉至這個派生密鑰的調用,那麼說明它就是導出函數「Zero」。

就這裡來說,我們可以在TranslateMessage和OpenMutexW處設斷點。不過,我不想在TranslateMessage處試運氣,所以選擇了OpenMutexW。

如果Olly軟體已經安裝了StringOD插件的話,按下control + G組合鍵就會彈出如下所示的菜單:

在文本框中,輸入將帶我們進入庫代碼的目標API調用的名稱,這樣就可以在這個調用處設置一個斷點,接著,單擊運行直至觸發這個斷點為止,然後跟蹤,直到這個函數返回,將我們帶至脫殼後的文件中,這樣我們就可以進行調試了。

如果我們繼續該操作,並在之前所在的call esi處設置斷點,就會發現,它就是cryptHashData,因此,它會對lpString進行了哈希處理,並將該字元串輸出的哈希值用於生成AES密鑰的輸入。

靜態分析

如果我們利用IDA跟蹤lpString的話,就會發現,它實際上就是這個函數的參數arg_0,同時,從表面上看,它也是一個隨機生成的字元串。

跳出這個函數後,我們看到:

var_54是剛才考察的那個函數的參數。它是一個字元串,後面先對其進行哈希運算,然後將其用於AES密鑰。我想通過跟蹤這個變數,弄清楚它會被填充到什麼地方。通過olly,我們可以為這個地址的內存寫入設置斷點,但是就本例來說,只要考察將它用作參數的函數就可以輕鬆找到答案了。

圖中高亮顯示的函數是我無意中發現的,這裡將其標註為RandomGenFunc。該函數以edx為參數,該參數是一個用於生成密鑰的變數。所以,這裡很可能就是變數填充和隨機密碼字元串被創建的地方。

我們發現,它使用了srand(),並且以time64()為種子值。為了確保不會搞混,這裡給出time64的精確描述。

如果我們仔細查看各個子函數的話,就會發現這種行為發生在一個循環中。srand()函數會再次被調用,並且還是使用time64()的返回值作為種子值,然後在循環中調用rand以生成新的數字。

從這裡可以看出,它正在使用當前系統時間作為一個種子值,如果您還記得srand()和rand()的功能的話,自然會明白seed參數實際上決定了每次調用rand()所輸出的隨機數集。所以,如果種子相同,那麼生成的序列也是一樣的。這一點,正是我們要利用的主要弱點。

如上所示,這裡使用了一個隨機的字符集「0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabc…」,並且在一個循環內部,rand()會被重複地調用。實際上,這是在通過字符集的子字元串位置來逐字元構建字元串。

所以,現在我們的問題已經有眉目了:AES密鑰是由當前時間的種子創建的隨機字元串生成的。如果我們能夠找到加密過程中使用的當前時間,我們就可以再現AES密鑰。當然,這些都可以通過暴力破解方法在合理的時間內完成。

這方面的知識,我們在上一篇中做過了詳細說明;如果讀者還不熟悉的話,可以重新回顧一下。

小結

在本文的上篇中,我們通過靜態分析和動態調試技術,深入考察了勒索軟體加密代碼的內部工作機制,找出了其主要的弱點。在下篇中,我們為讀者介紹如何針對加密代碼的弱點來設計相應的解密程序。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 嘶吼RoarTalk 的精彩文章:

數據安全,撲騰無止境
CVE-2018-6376:Joomla!二階SQL注入漏洞

TAG:嘶吼RoarTalk |