當前位置:
首頁 > 新聞 > macOS 平台的一款後門樣本的分析

macOS 平台的一款後門樣本的分析

本文將分析的樣本是OSX.TinyShell的變種:TinyTim。早在2018年,我就發現有攻擊者正在使用Tiny SHell的改良版。這個後門(Tiny SHell,是開放源碼的)的運行方式類似於SSH的可疑版本。雖然我已經有一段時間沒有遇到新的示例了,但是我完全相信攻擊者仍然在使用它。

目前,尚未有專門的文章討論討論有關該惡意軟體的技術細節。這可能是因為實際上,它相對於其開源形式幾乎沒有什麼變化,但是這些修改的確使我們能夠通過多種方式檢測其獨特性。由於該惡意軟體已被惡意行為者修改,因此稱其為Tiny SHell似乎並不準確。因此,我將這個特定的修改版本稱為「TinyTim」(因為我開始嘗試在假期前後撰寫此博客文章,並將發布拖到現在為止)。

本文中使用的樣本可以在VirusTotal上找到(SHA256:8029e7b12742d67fe13fcd53953e6b03ca4fa09b1d5755f8f8289eac08366efc)。

在VirusTotal頁面上,你會注意到許多反病毒掃描程序將其標記為OSX.Keydnap,但我不知道這種聯繫是如何產生的,因為我看不到它們之間的共同點。

發現過程

第一次觀察表明,這個惡意軟體是由開發人員簽名的。我不知道這是一個合法的被盜的簽名證書,還是它是由攻擊者創建和擁有的。這很有趣,因為惡意軟體通常僅用於攻擊Gatekeeper的簽名。正如我之前發現的那樣,這個惡意軟體是通過SSH使用受攻擊的憑證在受害系統上釋放的。也許攻擊者是有意使用帶符號的二進位代碼來進行混合(因為macOS上的大多數二進位代碼都是帶符號的)。使用macOS的代碼簽名實用程序,我們可以轉儲惡意軟體的代碼簽名信息:

如上所述,我們今天看到的這種變體是直接基於開源Tiny SHell後門的。Tiny SHell源代碼進行的主要更改之一是添加了一個稱為MyDecode的函數,攻擊者使用此函數對二進位文件內的某些「敏感」字元串進行編碼。如果我們想對這裡發生的事情有個更好的了解,就必須在Hopper等反彙編程序中打開它。

在main函數內部,第一個檢查顯示TinyTim添加了一些基本的反調試函數。在開始時,我們看到ptrace與ptrace_deny_attach參數一起使用,如果程序在附加到調試器時執行,ptrace_deny_attach參數將立即關閉程序,我們必須記住這一點。

在檢查調試器是否存在之後,它調用getuid,它返回執行程序的用戶的用戶ID。在這種情況下,惡意軟體會檢查根用戶的UID是否為0。在這兩種情況下,MyDecode函數最終運行在一個看起來像是亂碼的字元串上。如果我們在左邊的標籤中選擇_MyDecode並按下x,則可以很好地看到引用此函數的所有位置:

main調用11個,tshd_runshell調用2個,顯然,這個惡意軟體經常依賴於這個函數。如果我們把Hopper視圖切換到偽代碼,我們會看到此函數實際上是非常基本的:

這裡要重點關注的關鍵項是r14 ^ r15,這是惡意軟體常見的兩個位元組的簡單XOR運算。我們看到r14和r15的值是傳遞給該函數的第二個和第三個參數的值。此處傳遞的第一個參數是攻擊者想要取消屏蔽的字元串。如果回到主代碼,我們可以看一下攻擊者調用MyDecode時傳遞的值:

在前幾個調用中,我們看到MyDecode使用XOR模式0x4 ^ 0x2對每個字元串進行解碼。我們有一些選項可以將這些字元串轉換回可讀的文本。我們可以調試程序,也可以編寫簡單的腳本為我們解碼字元串。或者,我們可以同時做!讓我們從調試開始。

準備調試

在開始之前,我們必須採取以下步驟來準備這個可執行文件,以便它能夠運行。

1. 通過chmod x賦予TinyTim可執行文件許可權;

2. 使用以下代碼刪除已撤銷的簽名:codesign --remove-signature;

3. 使用xattr -d com.apple.quarantine刪除隔離位(假設已下載此惡意軟體);

4. 刪除前面討論的ptrace調用,這是一種防調試技術,如果檢測到調試器,它將關閉該程序。我們可以通過在ptrace調用上放置一個斷點,然後跳過它來完成此操作,或者我們可以簡單地NOP它,因此我們不必每次運行時都擔心一個額外的斷點。

攻擊過程

現在,我們已經完成了所有的設置,我們可以在調試器中打開TinyTim並開始使用MyDecode函數。讓我們在函數末尾的返回處放一個斷點,然後啟動調試器:

當在調試器中命中斷點時,這意味著MyDecode函數剛剛完成運行。如果使用x / s $ rdx命令列印RDX寄存器,我們可以看到已解碼的字元串:

在本例中,我們看到已解碼的字元串是「/Users/%@/Library/Fonts/.cache」。請記住,我們是以基本用戶的身份運行的,從我們在main中看到的情況來看,如果它作為根用戶運行,將使用不同的路徑(請參見第一個屏幕快照中的if/else語句)。我們可以繼續「跳轉到下一個斷點」並列印每個字元串。結果並不令人驚訝:

0x10000c260: 「/Users/%@/Library/Fonts/.cache」

0x7ffeefbffa40: 「PROG_INFO」

0x7ffeefbffa50: 「name_masq」

0x7ffeefbffa60: 「CONN_INFO」

0x7ffeefbffb28: 「domain」

0x7ffeefbffa70: 「」

0x7ffeefbffa70: 「next_time」

大多數安全分析人員都將上述字元串視為後門配置選項,這些選項可能是從「/Users/%@/Library/Fonts/.cache」文件中讀取了這些選項。但是,由於沒有在指定位置創建配置文件,因此沒有成功讀取這些配置。還要注意,其中一個已解碼的字元串是空的。這有點奇怪,但我們稍後會再討論它。讓我們一起整理一些快速的python代碼,這些代碼也可以解開這些字元串,因為這樣做不會造成任何攻擊性。這沒有什麼複雜的,我們只需要遍歷提供的字元串中的每個字元,並在其上運行XOR方案來獲得已解碼的字元。

現在我們無需使用調試器就可以輕鬆解碼:

太棒了!我們現在可以獲取存儲在可執行文件中的各種字元串,並以純文本的形式查看它們。繼續,我們可以嘗試創建一個配置文件來查看發生了什麼,但是我們不知道配置文件的格式,接下來看看是否可以解決這個問題。

發現配置格式的關鍵實際上是在getProfileString函數中,該函數僅引用fopen,fgets,fseek和fclose函數。這些函數通常用於打開、關閉和移動文件的不同內容。

我們可以看到fopen打開了指定為arg0的文件,在本例中,arg0是惡意軟體的配置文件。然後開始解析它。在文件的底部,我們看到sscanf正在使用某些特定的格式:

你可以使用sscanf函數在網上找一下,或者你可以使用我們應該已經使用過的方法,即使用GetProfileString函數,它可以準確地揭示我們所要查找的內容。

這裡我們有一個函數,它是來自Windows的某種類型的埠,允許用戶讀取ini格式的配置文件。如果考慮一下我們前面看到的MyDecode函數的值,這是有意義的。這意味著所有大寫的項都是lpAppName值,小寫的項是lpKeyName值。當然,這在Mac上感覺有點不自然,因為這是Windows ini格式的一部分,但實際上它只是一個文本文件,這真的是一種格式嗎?這意味著我們的配置文件應該如下:

這裡使用的值當然是為我自己的測試而設置的,但是這種格式應該可以達到目的。一種簡單的確認方法是在getProfileString底部附近的strcpy函數上放置一個斷點,因為這個函數可能用於保存從配置文件中取出的字元串。一旦斷點被命中,我們就可以使用x/s $RDI列印RDI寄存器(當函數被調用時,RDI應該總是保持arg0)來顯示傳遞給strcpy函數的第一個參數,然後繼續到下一個斷點並重複。

使用正確的配置文件格式之後,我們將更接近於可操作的惡意軟體。然而,仍有一些懸而未決的問題。讓我們重新檢查放置在myDecode函數上的斷點,然後再次列印出每個解碼後的值。你還記得嗎,我們嘗試列印的第六個字元串是空字元串,讓我們看看是否有任何變化?

現在,解碼後的字元串顯示為749060607。請注意,該字元串在域字元串解碼後立即解碼。只需看一下就可以看出它與我們提供的localhost IP地址的長度相同-127.0.0.1。

如果我們使用我們編寫的myDecode.py腳本並在127.0.0.1上運行它,那麼我們是否可能得到749060607?

事實證明,我們在配置文件中使用的IP地址必須使用XOR方案進行編碼。這對於攻擊者而言是明智的。這樣可以確保即使找到配置文件,也無法以純文本方式找到命令和控制IP或域。如果他們使用的是已知的惡意IP地址,這還可以確保通過簡單的YARA規則無法提取他們使用的C2。因此,如果我們希望看到與該惡意軟體的成功連接,則必須確保首先對存儲在配置文件中的IP或域進行了相應的編碼。由於XOR是可逆的,並且我們已經知道所使用的方案,因此最終變得非常簡單。我們可以通過在python myDecode腳本中翻轉單個運算符來實現:

它以所需的掩碼格式提供了127.0.0.1,可以在我們更新配置文件後正確解碼:

現在你可能認為我們已經準備好連接回C2伺服器了,然而,TinyTim還有另一個反調試技巧。如果我們再看一下偽代碼中的main函數,我們會注意到connect函數的調用依賴於一個非匹配的字元串比較。

讓我們在此strcmp函數上添加一個斷點,並通過列印寄存器RDI和RSI(傳遞給strcmp的第一個和第二個參數)來查看正在比較的內容:在連接到指定的C2之前,要進行一次檢查,以確保這不是試圖連接到運行惡意軟體的同一台計算機,這是惡意軟體開發者的另一個聰明舉動。有很多方法可以繞過這個問題。為了簡單起見,我將在VM中啟動微型Tiny SHell伺服器,獲取該VM的本地IP地址,使用XOR模式重新詢問IP,並將其添加到配置文件中,這樣問題就解決了。運行TinyTim現在將創建到我的VM上的Tiny SHelll伺服器的連接,這樣最後一個問題就解決了。

TinyTim想要一個密碼,這是意料之中的,因為在其開源形式Tiny SHell中,用戶需要輸入密碼。但是,因為我們沒有在配置文件中看到指定的密碼選項,所以我們知道它必須存儲在可執行文件的某個地方。開源的Tiny SHell將該密碼稱為機密,在Hopper中,我們可以對秘密進行簡單的搜索:

現在,我們會看到一個XREF指向一個有趣的字元串" lcc,./3,我們可以嘗試使用此密碼作為密碼,但是與可執行文件中的其他所有字元串一樣,實際上已經對其進行了編碼,這很有可能會有所幫助。因此,我們將首先使用python腳本對其進行解碼:

一直以來,我們的目標都是讓惡意軟體連接到我們的C2伺服器,以查看是否可以通過任何方式對其進行進一步修改。事實證明,從此以後,這種惡意軟體的行為就像開源的Tiny SHell。因此,主要的增加是編碼字元串,增加了用於快速更改的配置文件以及少量的反調試技術。與其繼續使用我們的反編譯器,不如僅僅看一下Tiny SHell客戶端源代碼就更有意義了。

參考及來源:https://objective-see.com/blog/blog_0x58.html

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


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

Zeek:一款開源的網路流量安全監控平台
你會信任你的AutoIT反編譯程序嗎?