<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    R3藍屏的多種方式及原理分析(一)

    VSole2021-10-22 16:29:52

    前言

    藍屏死機(英語:Blue Screen of Death,縮寫:BSoD)指的是微軟Windows操作系統在無法從一個系統錯誤中恢復過來時所顯示的屏幕圖像。藍屏有它存在的理由,在遇到非常嚴重的嚴重錯誤時,為了避免更嚴重的錯誤,立馬中止系統的所有操作,順便給個提示,讓你知道錯誤的原因,對于一個專業人員來說,這些機制確實是非常重要的。但當你正在寫論文還未保存,眼前卻一片藍色的時候,我想你一定也會黯然神傷吧。這個讓普通人恨之入骨,專業人員愛恨交織的東西,究竟有怎樣的魔力?本文只探討由R3引起的BSoD,明眼人都知道研究R0的藍屏純屬脫褲子放屁。

    涉及到的知識點:

    1. 調用未公開的API實現Ring3的BSoD行為
    2. 通過對比Reactos源碼挖掘NT內核的更多秘密
    3. 借助IDA的靜態分析探究BSoD的流程
    4. windbg的Local Kernel Debugging和雙機調試的各種技巧

    下圖為經典的Win10藍屏

    背景

    相信很多人都對R3下的藍屏很好奇,我也不例外,簡單講幾個用處,可以用于自己程序的反調試手段,不過藍屏比起其他反調試手段顯然太過暴力,屬于殺敵一千自損八百的情況,當然這種手段也比較好破解。對于各安全廠商而言,這應該是需要特別注意的,如何連這都攔截不了,后面的防護也只是癡人說夢。在網上一搜索了一大圈,大部分文章都是介紹API的,里面各種藍屏方式,其實都是一個套路,講解原理的確實少之又少。后來尋了半天終于找到一篇,Ring3觸發BSOD代碼實現及內核逆向分析,我也是受到啟發,寫下了本文,上文主要對Process進行了探究,本文將從各個方面更加深入的探究它的原理機制。

    Ring3藍屏的方式

    簡單的可以分成3大類,如果還有其他種類的歡迎大家補充,網上各大文章里的手段基本是第二類的衍生,但本質還是利用它是Critical Process,但是無論哪種最后調用的一定是由Ring0調用nt!KeBugCheckEx

    第一類藍屏:NtRaiseHardError

    特別注意:需要SeShutdownPrivilege權限,因此需要利用RtlAdjustPrivilege提權,但是無需繞過UAC(無需以管理員身份運行)

    NTSTATUSNTAPINtRaiseHardError(    IN NTSTATUS   ErrorStatus,            // 錯誤代碼    IN ULONG      NumberOfParameters,    // 指定了Parameters指針數組包含的指針個數    IN PUNICODE_STRING  UnicodeStringParameterMask OPTIONAL,    // 該參數的各個二進制位與Paramenters指針數組一一對應,如果某一位為1,則說明對應的參數指針指向的是一個UNICODE_STRING,否則是一個整數    IN PVOID      *Parameters,            // 參數    IN HARDERROR_RESPONSE_OPTION ResponseOption,    // 枚舉類型 本文使用6號,具體含義見下面的代碼    OUT PHARDERROR_RESPONSE      Response            // 返回值);
    

    以下是RtlAdjustPrivilege可獲取的各種權限,單獨提出來的2個是需要用到的

    1.SeCreateTokenPrivilege 0x22.SeAssignPrimaryTokenPrivilege 0x33.SeLockMemoryPrivilege 0x44.SeIncreaseQuotaPrivilege 0x55.SeUnsolicitedInputPrivilege 0x06.SeMachineAccountPrivilege 0x67.SeTcbPrivilege 0x78.SeSecurityPrivilege 0x89.SeTakeOwnershipPrivilege 0x910.SeLoadDriverPrivilege 0xa11.SeSystemProfilePrivilege 0xb12.SeSystemtimePrivilege 0xc13.SeProfileSingleProcessPrivilege 0xd14.SeIncreaseBasePriorityPrivilege 0xe15.SeCreatePagefilePrivilege 0xf16.SeCreatePermanentPrivilege 0x1017.SeBackupPrivilege 0x1118.SeRestorePrivilege 0x12    19.SeShutdownPrivilege 0x13    20.SeDebugPrivilege 0x1421.SeAuditPrivilege 0x1522.SeSystemEnvironmentPrivilege 0x1623.SeChangeNotifyPrivilege 0x1724.SeRemoteShutdownPrivilege 0x1825.SeUndockPrivilege 0x1926.SeSyncAgentPrivilege 0x1a27.SeEnableDelegationPrivilege 0x1b28.SeManageVolumePrivilege 0x1c29.SeImpersonatePrivilege 0x1d30.SeCreateGlobalPrivilege 0x1e31.SeTrustedCredManAccessPrivilege 0x1f32.SeRelabelPrivilege 0x2033.SeIncreaseWorkingSetPrivilege 0x2134.SeTimeZonePrivilege 0x2235.SeCreateSymbolicLinkPrivilege 0x23
    

    我們可以在自己的電腦上查看一下自己的權限

    普通用戶權限

    繞過UAC時的權限

    第二類藍屏:Critical Process/Thread

    如果對于系統啟動過程非常熟悉的話,應該聽說過一些系統的關鍵進程如csrss.exe掛了的話,則整個系統必然掛,這就是屬于這一類藍屏的特色了,只要某個線程或者進程掛了,整個系統就會藍屏,所以你可能會想,那我只要把這種進程線程關了不就可以藍嗎?那確實,但是你的想法肯定也早就在微軟的考慮中,對于那些系統線程,在EHTREAD的SystemThread位置將會是1,這下好了,在關閉線程的函數里判斷SystemThread的值,如果是,我就不關,這你不就沒辦法了嗎,對于這部分在后面的逆向部分會提到。咱們先來驗證一下是否能關閉系統進程

    那不如換種思路,既然無法將系統的Critical Process/Thread關掉,那我把自己設置成Critical Process/Thread“身份”,然后把自己關掉總可以了吧。

    我們需要以下API來改變自己的“身份”,以下均為導出但未文檔化的函數(在ntdll中),因此可以使用GetProcAddress直接獲取,不必搜索特征碼,倒是省了一個大麻煩。但是需要SeDebugPrivilege權限,上面可以看到,那是通過UAC之后才有的權限,因此必須繞過UAC才能使用以下API

    NtSetInformationProcess

    NtSetInformationThread

    RtlSetProcessIsCritical 實際是對NtSetInformationProcess的封裝

    RtlSetThreadIsCritical 實際是對NtSetInformationThread的封裝

    第三類藍屏:系統資源耗盡

    將物理內存占滿應該可以實現藍屏,讀者可以自行測試,不是本文講解的重點

    NtRaiseHardError逆向分析

    0.實現代碼

    先直接上藍屏代碼,通過代碼來進行分析

    #include #include // 需要的Shutdown權限,至于為什么是19看上面RtlAdjustPrivilege的介紹const ULONG SE_SHUTDOWN_PRIVILEGE = 19;
    typedef struct _UNICODE_STRING{    USHORT Length;    USHORT MaximumLength;    PWCH   Buffer;}UNICODE_STRING, *PUNICODE_STRING;
    typedef enum _HARDERROR_RESPONSE_OPTION{    OptionAbortRetryIgnore,    OptionOk,    OptionOkCancel,    OptionRetryCancel,    OptionYesNo,    OptionYesNoCancel,    OptionShutdownSystem} HARDERROR_RESPONSE_OPTION, *PHARDERROR_RESPONSE_OPTION;
    typedef enum _HARDERROR_RESPONSE{    ResponseReturnToCaller,    ResponseNotHandled,    ResponseAbort,    ResponseCancel,    ResponseIgnore,    ResponseNo,    ResponseOk,    ResponseRetry,    ResponseYes} HARDERROR_RESPONSE, *PHARDERROR_RESPONSE;
    // 函數指針typedef NTSTATUS(NTAPI *NTRAISEHARDERROR)(    IN NTSTATUS             ErrorStatus,    IN ULONG                NumberOfParameters,    IN PUNICODE_STRING      UnicodeStringParameterMask OPTIONAL,    IN PVOID                *Parameters,    IN HARDERROR_RESPONSE_OPTION ResponseOption,    OUT PHARDERROR_RESPONSE Response    );
    typedef BOOL(NTAPI *RTLADJUSTPRIVILEGE)(ULONG, BOOL, BOOL, PBOOLEAN);
    HARDERROR_RESPONSE_OPTION ResponseOption = OptionShutdownSystem;HARDERROR_RESPONSE Response;
    NTRAISEHARDERROR NtRaiseHardError;RTLADJUSTPRIVILEGE RtlAdjustPrivilege;
    int main(){    // 任何進程都會自動加載ntdll,因此直接獲取模塊地址即可,不必再LoadLibrary    HMODULE  NtBase = GetModuleHandle(TEXT("ntdll.dll"));    if (!NtBase) return false;
        // 獲取各函數地址    NtRaiseHardError = (NTRAISEHARDERROR)GetProcAddress(NtBase, "NtRaiseHardError");    RtlAdjustPrivilege = (RTLADJUSTPRIVILEGE)GetProcAddress(NtBase, "RtlAdjustPrivilege");    // 提權    BOOLEAN B;    if (!RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &B) == 0)    {        printf("提權失敗");        getchar();        return 0;    }    NTSTATUS status = NtRaiseHardError(0xC0000217, 0, NULL, NULL, OptionShutdownSystem, &Response);    return 0;}
    

    開啟雙擊調試,直接藍,連調試的機會都不給你,可以說確實很無解了,至少咱們后面的分析的Critical Thread是可以被windbg斷下來的。這個函數本來是用來顯示錯誤信息的,現在卻被用來干這種事,世事難料,安全的對抗是永無止境的。

    1.棧回溯-觀察整體

    先通過棧回溯觀察下程序的運行流程,便于后續的分析,在KeWaitForSingleObject返回地址處下個斷點,直接藍了,說明該函數就是藍屏的“元兇”,這個函數非常復雜,它具體干了咱們不用管,在這個例子中大致就是等待服務程序插入線程來處理它的關機請求。

    2.IDA分析NtRaiseHardError

    分析基于20H1版本的內核,在win7 x64以上這些函數基本沒啥變化。

    為了方便理解,下文用PX來代指NtRaiseHardError的參數,a代表當前函數的參數,P1就是NtRaiseHardError的第一個參數,a5則為當前函數的第五個參數。

    由于第四個參數為0因此直接跳過中間大部分步驟,直接開始調用ExpRaiseHardError(),P1 P2 P3 a5分別是NtRaiseHardError傳進來參數1、2、3、5,Dst和v26是一個局部變量數組int64[5],v22則用于返回Response至a6。當然如果你在R0調用,則PreviousMode=0會走下面那個分支調用ExRaiseHardError()

    下面讓我們看看ExpRaiseHardError干了什么

    3.ExpRaiseHardError

    不要看上面的參數,是錯的,流程卻是對的,IDA的F5果然還是不靠譜,算了,還是手動分析參數吧。

    事實證明,千萬不能信任IDA的F5,重要環節還得自己來,用windbg驗證一下,bp nt!ExpSystemErrorHandler下個斷點,64位函數使用rcx rdx r8 r9來傳遞前四個參數的值,因此rcx rdx r8 r9應該分別是P1 P2 P3 v26的值,可以發現完全符合,證明我們分析的參數是正確的。

    4.ExpSystemErrorHandler

    這函數沒做什么事,直接調用了ExpSystemErrorHandler2(),依舊不需要看上面的參數順序,并不正確,經過分析跟ExpSystemErrorHandler的參數完全一樣

    ExpSystemErrorHandler2(P1, P2, P3, v26數組地址, a5);

    5.ExpSystemErrorHandler2

    ExpSystemErrorHandler2進行一些列字符串的操作,然后調用了PoShutdownBugCheck,第三個參數是最初的P1(錯誤碼)。我們通過棧回溯可以知道,并不會執行下面的KeBugCheckEx,因為調用PoShutdownBugCheck時就已經藍屏了。

    6.PoShutdownBugCheck

    沒做什么有用的事,將函數分發給了ZwInitiatePowerAction,大家也不要看見KeBugCheckEx就興奮,下面的KeBugCheckEx依舊沒有執行的機會。

    Nt是給R0調用的,Nt系列的更底層,Zw系列的函數是給R3調用的,需要做一些檢查,不管怎么說最后調用的一定是Nt的,所以咱們直接分析Nt的。

    7.NtInitiatePowerAction

    前面一大堆加鎖、去鎖,咱們不管它,看關鍵步驟,執行到這里,調用KeWaitForSingleObject

    然后等待system線程掛靠,導致藍屏

    總結

    整個流程大致如下圖所示

    由此看來,NtRaiseHardError的藍屏“旅程”并不復雜,后面的進程線程藍屏才是真正的挑戰,由于文章篇幅限制,只能放到下一節內容來進行講解,后續的分析會比這個更加深入,更加曲折,更加刺激!

    函數調用藍屏
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    近日,Cyber??Ark安全研究員Eviatar Gerzi發現Windows終端和基于Chrome的網頁瀏覽器上存在多個高危DoS(拒絕服務)漏洞。
    概述在windows系統上,涉及到內核對象的功能函數,都需要從應用層權限轉換到內核層權限,然后再執行想要的內核函數,最終將函數結果返回給應用層。本文就是用OpenProcess函數來觀察函數從應用層到內核層的整體調用流程。OpenProcess函數,根據指定的進程ID,返回進程句柄。NTSTATUS Status; //保存函數執行狀態。OBJECT_ATTRIBUTES Obja; //待打開對象的對象屬性。HANDLE Handle; //存儲打開的句柄。CLIENT_ID ClientId; //進程、線程ID. dwDesiredAccess, //預打開進程并獲取對應的權限。ObjectNamePresent = ARGUMENT_PRESENT ; //判斷對象名稱是否為空
    CVE-2021-24086漏洞分析
    2022-07-19 16:41:30
    漏洞信息2021年,Microsoft發布了一個安全補丁程序,修復了一個拒絕服務漏洞,編號為CVE-2021-24086,該漏洞影響每個Windows版本的IPv6堆棧,此問題是由于IPv6分片處理不當引起的。
    Win32k組件最初的設計和編寫是完全建立的用戶層上的,但是微軟在 Windows NT 4.0 的改變中將 Win32k.sys 作為改變的一部分而引入,用以提升圖形繪制性能并減少 Windows 應用程序的內存需求。窗口管理器(User)和圖形設備接口(GDI)在極大程度上被移出客戶端/服務端運行時子系統(CSRSS)并被落實在它自身的一個內核模塊中。
    IDA故障參考
    2023-07-10 10:08:00
    IDA故障排除過程記錄由于IDA閉源,又加上其十分無效的官方文檔。因此如果出現任何錯誤,都需要進行分析和查錯,這一過程很麻煩。按下確定之后,IDA就隨風而逝了。你氣急敗壞的不斷導入文件,但是IDA就是屹然不動。觀察故障的表和log,也沒有任何反饋。簡稱,用IDA調試IDA。首先你要禁用所有plugin。使用WinDBG打開導出的dump文件:windbg大名鼎鼎,其威名必不用說。
    MITM Fuzz下圖是用戶層與內核層實現通信的過程,可以看到,最后是通過NtDeviceIoControlFile來分發給相應驅動對象的派遣函數的,因此,可以通過對該函數進行HOOK操作。如果將修改以后的數據發送給NtDeviceIoControlFile函數以后,發生了內核崩潰或,往往預示著該驅動程序可能存在內核漏洞。
    在所有函數調用發生時,向棧幀內壓入一個額外的隨機 DWORD,隨機數標注為“SecurityCookie”。在函數返回之前,系統將執行一個額外的安全驗證操作,被稱做 Security check。
    API(Application Programming Interface),我們調用時只需提供正確的參數以及接收返回值就可以判斷API執行是否成功或者通過GetLastError獲得錯誤原因.
    VulFi,即“漏洞發現者”,它是一個IDA Pro插件,可以幫助廣大研究人員在二進制文件中查找漏洞。它的的主要目標是在一個單一視圖中給研究人員提供包含了各種函數交叉引用的相關信息。需要注意的是,搜索函數時需要精確匹配。這意味著or 不會被檢測為標準函數,因此在尋找潛在漏洞時不會被考慮。除此之外,VulFi將盡最大努力來過濾所有明顯的誤報。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类